Files
health-app/src/services/trainer.js
infinicaretech 7ef6b6f9ee
Some checks failed
CI/CD - Build, Push & Deploy / Build & Push Docker Image (push) Has been cancelled
CI/CD - Build, Push & Deploy / Update GitOps Manifest (push) Has been cancelled
fix: prevent form reset on error, add multi-select for goal/activity/injury
- Remove profileNextStep(1) from saveProfile catch block so users stay
  on current step when an error occurs instead of being sent back to step 1
- Convert Goal, Activity Level, and Injury Area fields from single-select
  (radio/dropdown) to multi-select checkboxes with comma-separated storage
- Add validateMultiEnum backend validation for comma-separated enum values
- Update trainer.js filterByInjury and goal checks for multi-value support
- Update dietitian.js TDEE, calorie, and water calculations for multi-values

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 15:49:35 +00:00

1343 lines
146 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use strict";
// ─────────────────────────────────────────────────────────────────────────────
// Utility: generate GIF URL from exercise name
// ─────────────────────────────────────────────────────────────────────────────
function slugify(name) {
return name
.toLowerCase()
.replace(/\s*\(.*?\)\s*/g, "")
.trim()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-|-$/g, "");
}
function gifUrl(name) {
return `https://assets.infinicaretech.com/exercises/${slugify(name)}.gif`;
}
// ─────────────────────────────────────────────────────────────────────────────
// Exercise Database (150+ exercises)
// Each exercise has: name, name_tr, muscle_group, secondary_muscles, equipment,
// location, difficulty, sets, reps, rest_seconds, tempo, gif, instructions,
// contraindicated_injuries, contraindicated_conditions, alternatives, calories_per_set
// ─────────────────────────────────────────────────────────────────────────────
const EXERCISES = {
chest: [
{ name: "Bench Press", name_tr: "Bench Press", muscle_group: "chest", secondary_muscles: ["triceps", "shoulders"], equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 4, reps: "8-10", rest_seconds: 90, tempo: "2-0-2-0", gif: gifUrl("Bench Press"), instructions: ["Lie flat on bench", "Grip barbell slightly wider than shoulder-width", "Lower bar to mid-chest with control", "Press up to full lockout"], contraindicated_injuries: ["shoulder", "wrist", "elbow"], contraindicated_conditions: ["heart_condition", "high_blood_pressure"], alternatives: ["dumbbell-press", "push-up"], calories_per_set: 9 },
{ name: "Incline Dumbbell Press", name_tr: "Eğik Dumbbell Press", muscle_group: "chest", secondary_muscles: ["triceps", "shoulders"], equipment: "dumbbell", location: ["gym", "home"], difficulty: "intermediate", sets: 4, reps: "10-12", rest_seconds: 75, tempo: "2-0-2-0", gif: gifUrl("Incline Dumbbell Press"), instructions: ["Set bench to 30 degrees", "Press dumbbells up from shoulder level", "Lower with control to full stretch", "Keep feet flat on floor"], contraindicated_injuries: ["shoulder", "wrist"], contraindicated_conditions: ["heart_condition"], alternatives: ["incline-push-up", "landmine-press"], calories_per_set: 8 },
{ name: "Decline Bench Press", name_tr: "Decline Bench Press", muscle_group: "chest", secondary_muscles: ["triceps", "shoulders"], equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 3, reps: "8-10", rest_seconds: 90, tempo: "2-0-2-0", gif: gifUrl("Decline Bench Press"), instructions: ["Secure legs on decline bench", "Grip barbell shoulder-width", "Lower to lower chest", "Press up explosively"], contraindicated_injuries: ["shoulder", "wrist", "elbow"], contraindicated_conditions: ["high_blood_pressure"], alternatives: ["dips", "decline-dumbbell-press"], calories_per_set: 9 },
{ name: "Cable Flyes", name_tr: "Kablo Flye", muscle_group: "chest", secondary_muscles: ["shoulders"], equipment: "cable", location: ["gym"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-1", gif: gifUrl("Cable Flyes"), instructions: ["Stand between cable stations", "Keep slight bend in elbows", "Bring hands together at chest height", "Squeeze chest at peak contraction"], contraindicated_injuries: ["shoulder"], contraindicated_conditions: [], alternatives: ["dumbbell-flye", "resistance-band-flye"], calories_per_set: 6 },
{ name: "Dips", name_tr: "Paralel Bar Dips", muscle_group: "chest", secondary_muscles: ["triceps", "shoulders"], equipment: "bodyweight", location: ["gym", "home"], difficulty: "intermediate", sets: 3, reps: "10-12", rest_seconds: 75, tempo: "2-0-2-0", gif: gifUrl("Dips"), instructions: ["Grip parallel bars", "Lean forward slightly for chest focus", "Lower until upper arms parallel to floor", "Press up to lockout"], contraindicated_injuries: ["shoulder", "wrist", "elbow"], contraindicated_conditions: ["heart_condition"], alternatives: ["bench-dips", "push-up"], calories_per_set: 8 },
{ name: "Push-Up", name_tr: "Sinav", muscle_group: "chest", secondary_muscles: ["triceps", "shoulders", "core"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "15-20", rest_seconds: 45, tempo: "2-0-2-0", gif: gifUrl("Push-Up"), instructions: ["Place hands shoulder-width apart", "Keep body in straight line", "Lower chest to near floor", "Push up to full extension"], contraindicated_injuries: ["wrist", "shoulder"], contraindicated_conditions: [], alternatives: ["knee-push-up", "wall-push-up"], calories_per_set: 7 },
{ name: "Dumbbell Pullover", name_tr: "Dumbbell Pullover", muscle_group: "chest", secondary_muscles: ["back", "triceps"], equipment: "dumbbell", location: ["gym", "home"], difficulty: "intermediate", sets: 3, reps: "12", rest_seconds: 60, tempo: "3-0-2-0", gif: gifUrl("Dumbbell Pullover"), instructions: ["Lie across bench with upper back supported", "Hold dumbbell with both hands above chest", "Lower weight behind head in arc", "Pull back to start with chest and lats"], contraindicated_injuries: ["shoulder", "back"], contraindicated_conditions: [], alternatives: ["cable-pullover", "straight-arm-pulldown"], calories_per_set: 7 },
{ name: "Machine Chest Press", name_tr: "Makine Gogus Presi", muscle_group: "chest", secondary_muscles: ["triceps", "shoulders"], equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 3, reps: "10-12", rest_seconds: 75, tempo: "2-0-2-0", gif: gifUrl("Machine Chest Press"), instructions: ["Adjust seat height so handles align with mid-chest", "Grip handles firmly", "Press forward to full extension", "Return slowly under control"], contraindicated_injuries: ["shoulder"], contraindicated_conditions: [], alternatives: ["push-up", "dumbbell-press"], calories_per_set: 7 },
{ name: "Pec Deck", name_tr: "Kelebek Makinesi", muscle_group: "chest", secondary_muscles: ["shoulders"], equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-1", gif: gifUrl("Pec Deck"), instructions: ["Adjust pads to shoulder height", "Place forearms against pads", "Bring arms together in front", "Squeeze chest and return slowly"], contraindicated_injuries: ["shoulder"], contraindicated_conditions: [], alternatives: ["cable-flyes", "dumbbell-flye"], calories_per_set: 5 },
{ name: "Landmine Press", name_tr: "Landmine Press", muscle_group: "chest", secondary_muscles: ["shoulders", "triceps"], equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 3, reps: "10-12", rest_seconds: 75, tempo: "2-0-2-0", gif: gifUrl("Landmine Press"), instructions: ["Place one end of barbell in landmine attachment", "Hold other end at shoulder height", "Press up and forward", "Lower with control"], contraindicated_injuries: ["wrist"], contraindicated_conditions: [], alternatives: ["incline-dumbbell-press", "push-up"], calories_per_set: 7 },
{ name: "Floor Press", name_tr: "Yer Presi", muscle_group: "chest", secondary_muscles: ["triceps"], equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "10-12", rest_seconds: 75, tempo: "2-1-2-0", gif: gifUrl("Floor Press"), instructions: ["Lie on floor with knees bent", "Hold dumbbells above chest", "Lower until triceps touch floor", "Press back up"], contraindicated_injuries: ["wrist", "elbow"], contraindicated_conditions: [], alternatives: ["bench-press", "push-up"], calories_per_set: 7 },
{ name: "Resistance Band Chest Press", name_tr: "Bantli Gogus Presi", muscle_group: "chest", secondary_muscles: ["triceps", "shoulders"], equipment: "resistance_band", location: ["home", "none"], difficulty: "beginner", sets: 3, reps: "15-20", rest_seconds: 45, tempo: "2-0-2-0", gif: gifUrl("Resistance Band Chest Press"), instructions: ["Anchor band behind you at chest height", "Grip handles", "Press forward until arms extended", "Return slowly"], contraindicated_injuries: ["shoulder", "wrist"], contraindicated_conditions: [], alternatives: ["push-up", "floor-press"], calories_per_set: 5 },
{ name: "Knee Push-Up", name_tr: "Dizden Sinav", muscle_group: "chest", secondary_muscles: ["triceps", "shoulders"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 45, tempo: "2-0-2-0", gif: gifUrl("Knee Push-Up"), instructions: ["Start on hands and knees", "Keep back straight from knees to head", "Lower chest toward floor", "Press up"], contraindicated_injuries: ["wrist", "knee"], contraindicated_conditions: [], alternatives: ["wall-push-up", "resistance-band-chest-press"], calories_per_set: 5 },
{ name: "Svend Press", name_tr: "Svend Press", muscle_group: "chest", secondary_muscles: ["shoulders"], equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 45, tempo: "2-1-2-0", gif: gifUrl("Svend Press"), instructions: ["Hold plate or light dumbbells at chest", "Press forward squeezing chest", "Extend arms fully", "Return to chest"], contraindicated_injuries: ["wrist"], contraindicated_conditions: [], alternatives: ["cable-flyes", "push-up"], calories_per_set: 5 },
],
back: [
{ name: "Deadlift", name_tr: "Deadlift", muscle_group: "back", secondary_muscles: ["legs", "glutes", "core"], equipment: "barbell", location: ["gym"], difficulty: "advanced", sets: 4, reps: "6-8", rest_seconds: 120, tempo: "2-0-2-0", gif: gifUrl("Deadlift"), instructions: ["Stand with feet hip-width apart", "Grip bar outside knees", "Keep back flat, chest up", "Drive through heels to stand"], contraindicated_injuries: ["back", "knee", "hip", "wrist"], contraindicated_conditions: ["heart_condition", "high_blood_pressure", "has_osteoporosis"], alternatives: ["rack-pull", "romanian-deadlift"], calories_per_set: 12 },
{ name: "Barbell Row", name_tr: "Barbell Row", muscle_group: "back", secondary_muscles: ["biceps", "core"], equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 4, reps: "8-10", rest_seconds: 90, tempo: "2-0-2-1", gif: gifUrl("Barbell Row"), instructions: ["Hinge at hips with flat back", "Grip bar shoulder-width", "Pull bar to lower chest", "Squeeze shoulder blades together"], contraindicated_injuries: ["back", "wrist"], contraindicated_conditions: ["high_blood_pressure"], alternatives: ["dumbbell-row", "cable-row"], calories_per_set: 9 },
{ name: "Lat Pulldown", name_tr: "Lat Pulldown", muscle_group: "back", secondary_muscles: ["biceps", "shoulders"], equipment: "cable", location: ["gym"], difficulty: "beginner", sets: 4, reps: "10-12", rest_seconds: 75, tempo: "2-0-2-1", gif: gifUrl("Lat Pulldown"), instructions: ["Grip bar wider than shoulder-width", "Sit with thighs secured under pad", "Pull bar to upper chest", "Control the return"], contraindicated_injuries: ["shoulder"], contraindicated_conditions: [], alternatives: ["pull-up", "resistance-band-pulldown"], calories_per_set: 7 },
{ name: "Seated Cable Row", name_tr: "Oturarak Kablo Row", muscle_group: "back", secondary_muscles: ["biceps", "shoulders"], equipment: "cable", location: ["gym"], difficulty: "beginner", sets: 3, reps: "10-12", rest_seconds: 75, tempo: "2-0-2-1", gif: gifUrl("Seated Cable Row"), instructions: ["Sit with feet on platform", "Grip handle with arms extended", "Pull handle to torso", "Squeeze shoulder blades, return slowly"], contraindicated_injuries: [], contraindicated_conditions: [], alternatives: ["dumbbell-row", "resistance-band-row"], calories_per_set: 7 },
{ name: "T-Bar Row", name_tr: "T-Bar Row", muscle_group: "back", secondary_muscles: ["biceps", "core"], equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 3, reps: "10-12", rest_seconds: 75, tempo: "2-0-2-1", gif: gifUrl("T-Bar Row"), instructions: ["Straddle the bar", "Grip V-handle attachment", "Pull toward chest", "Lower with control"], contraindicated_injuries: ["back", "wrist"], contraindicated_conditions: ["high_blood_pressure"], alternatives: ["barbell-row", "dumbbell-row"], calories_per_set: 8 },
{ name: "Pull-Up", name_tr: "Barfiks", muscle_group: "back", secondary_muscles: ["biceps", "shoulders", "core"], equipment: "bodyweight", location: ["gym", "home"], difficulty: "intermediate", sets: 3, reps: "8-12", rest_seconds: 90, tempo: "2-0-2-1", gif: gifUrl("Pull-Up"), instructions: ["Grip bar with overhand grip wider than shoulders", "Hang with arms extended", "Pull chin above bar", "Lower with control"], contraindicated_injuries: ["shoulder", "elbow", "wrist"], contraindicated_conditions: [], alternatives: ["lat-pulldown", "resistance-band-assisted-pull-up"], calories_per_set: 8 },
{ name: "Chin-Up", name_tr: "Chin-Up", muscle_group: "back", secondary_muscles: ["biceps"], equipment: "bodyweight", location: ["gym", "home"], difficulty: "intermediate", sets: 3, reps: "8-12", rest_seconds: 90, tempo: "2-0-2-1", gif: gifUrl("Chin-Up"), instructions: ["Grip bar with underhand grip shoulder-width", "Hang at full extension", "Pull chin over bar", "Lower slowly"], contraindicated_injuries: ["shoulder", "elbow", "wrist"], contraindicated_conditions: [], alternatives: ["lat-pulldown", "resistance-band-row"], calories_per_set: 8 },
{ name: "Single Arm Dumbbell Row", name_tr: "Tek Kol Dumbbell Row", muscle_group: "back", secondary_muscles: ["biceps", "core"], equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "10-12", rest_seconds: 60, tempo: "2-0-2-1", gif: gifUrl("Single Arm Dumbbell Row"), instructions: ["Place one knee and hand on bench", "Row dumbbell to hip with other arm", "Squeeze shoulder blade at top", "Lower with control"], contraindicated_injuries: [], contraindicated_conditions: [], alternatives: ["barbell-row", "cable-row"], calories_per_set: 7 },
{ name: "Face Pull", name_tr: "Face Pull", muscle_group: "back", secondary_muscles: ["shoulders"], equipment: "cable", location: ["gym"], difficulty: "beginner", sets: 3, reps: "15", rest_seconds: 45, tempo: "2-1-2-0", gif: gifUrl("Face Pull"), instructions: ["Set cable at face height", "Grip rope attachment with overhand grip", "Pull toward face, separating ends", "Squeeze rear delts at peak"], contraindicated_injuries: ["shoulder"], contraindicated_conditions: [], alternatives: ["band-pull-apart", "reverse-fly"], calories_per_set: 5 },
{ name: "Machine Row", name_tr: "Makine Row", muscle_group: "back", secondary_muscles: ["biceps"], equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 3, reps: "10-12", rest_seconds: 75, tempo: "2-0-2-1", gif: gifUrl("Machine Row"), instructions: ["Adjust chest pad", "Grip handles", "Pull toward torso", "Return slowly"], contraindicated_injuries: [], contraindicated_conditions: [], alternatives: ["cable-row", "dumbbell-row"], calories_per_set: 7 },
{ name: "Straight Arm Pulldown", name_tr: "Duz Kol Pulldown", muscle_group: "back", secondary_muscles: ["core"], equipment: "cable", location: ["gym"], difficulty: "intermediate", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-0", gif: gifUrl("Straight Arm Pulldown"), instructions: ["Stand facing cable machine", "Grip bar with straight arms", "Pull bar down to thighs", "Return with control"], contraindicated_injuries: ["shoulder"], contraindicated_conditions: [], alternatives: ["dumbbell-pullover", "lat-pulldown"], calories_per_set: 6 },
{ name: "Resistance Band Row", name_tr: "Bantli Row", muscle_group: "back", secondary_muscles: ["biceps"], equipment: "resistance_band", location: ["home", "none"], difficulty: "beginner", sets: 3, reps: "15", rest_seconds: 45, tempo: "2-1-2-1", gif: gifUrl("Resistance Band Row"), instructions: ["Sit on floor with legs extended", "Loop band around feet", "Pull handles to torso", "Squeeze shoulder blades"], contraindicated_injuries: [], contraindicated_conditions: [], alternatives: ["dumbbell-row", "inverted-row"], calories_per_set: 5 },
{ name: "Inverted Row", name_tr: "Ters Row", muscle_group: "back", secondary_muscles: ["biceps", "core"], equipment: "bodyweight", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "10-15", rest_seconds: 60, tempo: "2-0-2-1", gif: gifUrl("Inverted Row"), instructions: ["Lie under a bar or sturdy table", "Grip bar with overhand grip", "Pull chest to bar", "Lower with control"], contraindicated_injuries: ["wrist", "shoulder"], contraindicated_conditions: [], alternatives: ["dumbbell-row", "resistance-band-row"], calories_per_set: 6 },
{ name: "Rack Pull", name_tr: "Rack Pull", muscle_group: "back", secondary_muscles: ["glutes", "core"], equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 4, reps: "6-8", rest_seconds: 120, tempo: "2-0-2-0", gif: gifUrl("Rack Pull"), instructions: ["Set bar at knee height in rack", "Grip bar outside knees", "Drive hips forward to stand", "Lower back to rack"], contraindicated_injuries: ["back", "wrist"], contraindicated_conditions: ["high_blood_pressure"], alternatives: ["deadlift", "dumbbell-row"], calories_per_set: 10 },
{ name: "Pendlay Row", name_tr: "Pendlay Row", muscle_group: "back", secondary_muscles: ["biceps", "core"], equipment: "barbell", location: ["gym"], difficulty: "advanced", sets: 4, reps: "6-8", rest_seconds: 90, tempo: "1-0-2-0", gif: gifUrl("Pendlay Row"), instructions: ["Set up like a deadlift with flat back", "Explosively row bar to lower chest", "Lower bar to floor each rep", "Reset position between reps"], contraindicated_injuries: ["back", "wrist"], contraindicated_conditions: ["heart_condition", "high_blood_pressure"], alternatives: ["barbell-row", "dumbbell-row"], calories_per_set: 9 },
],
legs: [
{ name: "Barbell Squat", name_tr: "Barbell Squat", muscle_group: "legs", secondary_muscles: ["glutes", "core"], equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 4, reps: "8-10", rest_seconds: 120, tempo: "2-0-2-0", gif: gifUrl("Barbell Squat"), instructions: ["Position bar on upper traps", "Feet shoulder-width apart", "Squat until thighs parallel to floor", "Drive through heels to stand"], contraindicated_injuries: ["knee", "back", "hip", "ankle"], contraindicated_conditions: ["heart_condition", "high_blood_pressure"], alternatives: ["goblet-squat", "leg-press"], calories_per_set: 11 },
{ name: "Romanian Deadlift", name_tr: "Romen Deadlift", muscle_group: "legs", secondary_muscles: ["back", "glutes"], equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 4, reps: "10-12", rest_seconds: 90, tempo: "3-0-2-0", gif: gifUrl("Romanian Deadlift"), instructions: ["Hold bar at hip level", "Hinge at hips pushing them back", "Lower bar along thighs to shin level", "Drive hips forward to return"], contraindicated_injuries: ["back", "hip", "wrist"], contraindicated_conditions: ["high_blood_pressure"], alternatives: ["dumbbell-rdl", "leg-curl"], calories_per_set: 9 },
{ name: "Leg Press", name_tr: "Bacak Presi", muscle_group: "legs", secondary_muscles: ["glutes"], equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 4, reps: "10-12", rest_seconds: 90, tempo: "2-0-2-0", gif: gifUrl("Leg Press"), instructions: ["Sit in machine with back flat", "Place feet shoulder-width on platform", "Lower platform by bending knees", "Press back without locking knees"], contraindicated_injuries: ["knee"], contraindicated_conditions: [], alternatives: ["goblet-squat", "wall-sit"], calories_per_set: 9 },
{ name: "Walking Lunges", name_tr: "Yuruyus Hamle", muscle_group: "legs", secondary_muscles: ["glutes", "core"], equipment: "dumbbell", location: ["gym", "home"], difficulty: "intermediate", sets: 3, reps: "12 each leg", rest_seconds: 75, tempo: "2-0-2-0", gif: gifUrl("Walking Lunges"), instructions: ["Hold dumbbells at sides", "Step forward into lunge position", "Lower back knee toward floor", "Push off front foot to next step"], contraindicated_injuries: ["knee", "ankle", "hip"], contraindicated_conditions: ["has_arthritis"], alternatives: ["stationary-lunge", "step-up"], calories_per_set: 8 },
{ name: "Leg Curl", name_tr: "Bacak Curl", muscle_group: "legs", secondary_muscles: [], equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-0", gif: gifUrl("Leg Curl"), instructions: ["Lie face down on machine", "Adjust pad above heels", "Curl legs toward glutes", "Lower with control"], contraindicated_injuries: ["knee"], contraindicated_conditions: [], alternatives: ["resistance-band-leg-curl", "glute-bridge"], calories_per_set: 6 },
{ name: "Leg Extension", name_tr: "Bacak Extension", muscle_group: "legs", secondary_muscles: [], equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-0", gif: gifUrl("Leg Extension"), instructions: ["Sit on machine with back against pad", "Hook feet under roller pad", "Extend legs fully", "Lower with control"], contraindicated_injuries: ["knee"], contraindicated_conditions: [], alternatives: ["bodyweight-squat", "wall-sit"], calories_per_set: 6 },
{ name: "Calf Raise", name_tr: "Baldır Kaldirma", muscle_group: "legs", secondary_muscles: [], equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 4, reps: "15-20", rest_seconds: 45, tempo: "2-1-2-0", gif: gifUrl("Calf Raise"), instructions: ["Stand on calf raise platform", "Lower heels below platform edge", "Rise up on toes as high as possible", "Pause at top and lower slowly"], contraindicated_injuries: ["ankle"], contraindicated_conditions: [], alternatives: ["bodyweight-calf-raise", "seated-calf-raise"], calories_per_set: 5 },
{ name: "Front Squat", name_tr: "On Squat", muscle_group: "legs", secondary_muscles: ["core", "glutes"], equipment: "barbell", location: ["gym"], difficulty: "advanced", sets: 4, reps: "8-10", rest_seconds: 120, tempo: "2-0-2-0", gif: gifUrl("Front Squat"), instructions: ["Rest bar on front delts in rack position", "Keep elbows high", "Squat to full depth", "Drive up keeping torso upright"], contraindicated_injuries: ["knee", "back", "wrist", "ankle"], contraindicated_conditions: ["heart_condition", "high_blood_pressure"], alternatives: ["goblet-squat", "leg-press"], calories_per_set: 10 },
{ name: "Bulgarian Split Squat", name_tr: "Bulgar Split Squat", muscle_group: "legs", secondary_muscles: ["glutes", "core"], equipment: "dumbbell", location: ["gym", "home"], difficulty: "intermediate", sets: 3, reps: "10-12 each leg", rest_seconds: 75, tempo: "2-0-2-0", gif: gifUrl("Bulgarian Split Squat"), instructions: ["Place rear foot on bench behind you", "Hold dumbbells at sides", "Lower until front thigh is parallel", "Drive up through front heel"], contraindicated_injuries: ["knee", "ankle", "hip"], contraindicated_conditions: ["has_arthritis"], alternatives: ["stationary-lunge", "goblet-squat"], calories_per_set: 8 },
{ name: "Hack Squat", name_tr: "Hack Squat", muscle_group: "legs", secondary_muscles: ["glutes"], equipment: "machine", location: ["gym"], difficulty: "intermediate", sets: 4, reps: "10-12", rest_seconds: 90, tempo: "2-0-2-0", gif: gifUrl("Hack Squat"), instructions: ["Position shoulders under pads", "Place feet shoulder-width on platform", "Lower by bending knees", "Press back up without locking"], contraindicated_injuries: ["knee", "back"], contraindicated_conditions: [], alternatives: ["leg-press", "goblet-squat"], calories_per_set: 9 },
{ name: "Goblet Squat", name_tr: "Goblet Squat", muscle_group: "legs", secondary_muscles: ["glutes", "core"], equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-0", gif: gifUrl("Goblet Squat"), instructions: ["Hold dumbbell at chest level", "Feet slightly wider than shoulder-width", "Squat keeping torso upright", "Push through heels to stand"], contraindicated_injuries: ["knee", "ankle"], contraindicated_conditions: [], alternatives: ["bodyweight-squat", "wall-sit"], calories_per_set: 7 },
{ name: "Hip Thrust", name_tr: "Hip Thrust", muscle_group: "legs", secondary_muscles: ["glutes", "core"], equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 4, reps: "10-12", rest_seconds: 90, tempo: "2-1-2-0", gif: gifUrl("Hip Thrust"), instructions: ["Sit on floor with upper back on bench", "Roll barbell over hips", "Drive hips up squeezing glutes", "Lower with control"], contraindicated_injuries: ["back", "hip"], contraindicated_conditions: [], alternatives: ["glute-bridge", "dumbbell-hip-thrust"], calories_per_set: 8 },
{ name: "Step-Up", name_tr: "Step-Up", muscle_group: "legs", secondary_muscles: ["glutes", "core"], equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "12 each leg", rest_seconds: 60, tempo: "2-0-2-0", gif: gifUrl("Step-Up"), instructions: ["Stand facing a sturdy bench or step", "Step up with one foot", "Drive through heel to stand on top", "Step down with control"], contraindicated_injuries: ["knee", "ankle"], contraindicated_conditions: [], alternatives: ["walking-lunges", "goblet-squat"], calories_per_set: 7 },
{ name: "Bodyweight Squat", name_tr: "Vucut Agirligi Squat", muscle_group: "legs", secondary_muscles: ["glutes", "core"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "15-20", rest_seconds: 45, tempo: "2-0-2-0", gif: gifUrl("Bodyweight Squat"), instructions: ["Stand with feet shoulder-width apart", "Extend arms forward for balance", "Squat until thighs parallel", "Stand back up"], contraindicated_injuries: ["knee", "ankle"], contraindicated_conditions: [], alternatives: ["wall-sit", "chair-squat"], calories_per_set: 6 },
{ name: "Wall Sit", name_tr: "Duvar Oturusu", muscle_group: "legs", secondary_muscles: ["core"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "30-45 seconds", rest_seconds: 45, tempo: "isometric", gif: gifUrl("Wall Sit"), instructions: ["Lean back against wall", "Slide down until thighs parallel to floor", "Hold position", "Keep back flat against wall"], contraindicated_injuries: ["knee"], contraindicated_conditions: [], alternatives: ["bodyweight-squat", "chair-squat"], calories_per_set: 5 },
{ name: "Resistance Band Leg Curl", name_tr: "Bantli Bacak Curl", muscle_group: "legs", secondary_muscles: ["glutes"], equipment: "resistance_band", location: ["home"], difficulty: "beginner", sets: 3, reps: "15", rest_seconds: 45, tempo: "2-1-2-0", gif: gifUrl("Resistance Band Leg Curl"), instructions: ["Anchor band low", "Loop around ankle", "Curl heel toward glutes", "Lower with control"], contraindicated_injuries: ["knee", "ankle"], contraindicated_conditions: [], alternatives: ["glute-bridge", "bodyweight-squat"], calories_per_set: 5 },
],
shoulders: [
{ name: "Overhead Press", name_tr: "Overhead Press", muscle_group: "shoulders", secondary_muscles: ["triceps", "core"], equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 4, reps: "8-10", rest_seconds: 90, tempo: "2-0-2-0", gif: gifUrl("Overhead Press"), instructions: ["Grip bar at shoulder-width", "Start at collarbone level", "Press overhead to lockout", "Lower back to collarbone"], contraindicated_injuries: ["shoulder", "back", "wrist"], contraindicated_conditions: ["high_blood_pressure", "heart_condition", "has_epilepsy"], alternatives: ["seated-dumbbell-press", "landmine-press"], calories_per_set: 8 },
{ name: "Lateral Raise", name_tr: "Lateral Raise", muscle_group: "shoulders", secondary_muscles: [], equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 4, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-0", gif: gifUrl("Lateral Raise"), instructions: ["Stand with dumbbells at sides", "Raise arms out to sides to shoulder height", "Keep slight bend in elbows", "Lower with control"], contraindicated_injuries: ["shoulder"], contraindicated_conditions: [], alternatives: ["cable-lateral-raise", "resistance-band-lateral-raise"], calories_per_set: 5 },
{ name: "Front Raise", name_tr: "On Raise", muscle_group: "shoulders", secondary_muscles: ["chest"], equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "12", rest_seconds: 60, tempo: "2-0-2-0", gif: gifUrl("Front Raise"), instructions: ["Stand with dumbbells in front of thighs", "Raise one or both arms to shoulder height", "Keep arms nearly straight", "Lower slowly"], contraindicated_injuries: ["shoulder"], contraindicated_conditions: [], alternatives: ["resistance-band-front-raise", "cable-front-raise"], calories_per_set: 5 },
{ name: "Reverse Fly", name_tr: "Ters Fly", muscle_group: "shoulders", secondary_muscles: ["back"], equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "15", rest_seconds: 60, tempo: "2-1-2-0", gif: gifUrl("Reverse Fly"), instructions: ["Hinge forward at hips", "Let dumbbells hang below", "Raise arms out to sides", "Squeeze shoulder blades at top"], contraindicated_injuries: ["shoulder"], contraindicated_conditions: [], alternatives: ["face-pull", "band-pull-apart"], calories_per_set: 5 },
{ name: "Arnold Press", name_tr: "Arnold Press", muscle_group: "shoulders", secondary_muscles: ["triceps"], equipment: "dumbbell", location: ["gym", "home"], difficulty: "intermediate", sets: 3, reps: "10-12", rest_seconds: 75, tempo: "2-0-2-0", gif: gifUrl("Arnold Press"), instructions: ["Start with dumbbells at shoulders palms facing you", "Rotate palms outward as you press up", "Full lockout overhead", "Reverse the rotation on the way down"], contraindicated_injuries: ["shoulder", "wrist"], contraindicated_conditions: ["high_blood_pressure"], alternatives: ["seated-dumbbell-press", "lateral-raise"], calories_per_set: 7 },
{ name: "Shrugs", name_tr: "Omuz Silkme", muscle_group: "shoulders", secondary_muscles: [], equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-0", gif: gifUrl("Shrugs"), instructions: ["Hold dumbbells at sides", "Shrug shoulders straight up toward ears", "Hold at top briefly", "Lower with control"], contraindicated_injuries: ["neck"], contraindicated_conditions: [], alternatives: ["barbell-shrugs", "resistance-band-shrugs"], calories_per_set: 5 },
{ name: "Seated Dumbbell Press", name_tr: "Oturarak Dumbbell Press", muscle_group: "shoulders", secondary_muscles: ["triceps"], equipment: "dumbbell", location: ["gym", "home"], difficulty: "intermediate", sets: 4, reps: "8-10", rest_seconds: 90, tempo: "2-0-2-0", gif: gifUrl("Seated Dumbbell Press"), instructions: ["Sit with back supported", "Hold dumbbells at shoulder height", "Press overhead to lockout", "Lower to shoulder level"], contraindicated_injuries: ["shoulder", "wrist"], contraindicated_conditions: ["high_blood_pressure"], alternatives: ["overhead-press", "lateral-raise"], calories_per_set: 7 },
{ name: "Cable Lateral Raise", name_tr: "Kablo Lateral Raise", muscle_group: "shoulders", secondary_muscles: [], equipment: "cable", location: ["gym"], difficulty: "intermediate", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-0", gif: gifUrl("Cable Lateral Raise"), instructions: ["Stand sideways to cable machine", "Grip handle with far hand", "Raise arm to shoulder height", "Lower with control"], contraindicated_injuries: ["shoulder"], contraindicated_conditions: [], alternatives: ["dumbbell-lateral-raise", "resistance-band-lateral-raise"], calories_per_set: 5 },
{ name: "Machine Shoulder Press", name_tr: "Makine Omuz Presi", muscle_group: "shoulders", secondary_muscles: ["triceps"], equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 3, reps: "10-12", rest_seconds: 75, tempo: "2-0-2-0", gif: gifUrl("Machine Shoulder Press"), instructions: ["Sit with back against pad", "Grip handles at shoulder level", "Press up to full extension", "Lower with control"], contraindicated_injuries: ["shoulder"], contraindicated_conditions: ["high_blood_pressure"], alternatives: ["seated-dumbbell-press", "resistance-band-overhead-press"], calories_per_set: 7 },
{ name: "Upright Row", name_tr: "Dik Row", muscle_group: "shoulders", secondary_muscles: ["biceps"], equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 3, reps: "10-12", rest_seconds: 60, tempo: "2-0-2-0", gif: gifUrl("Upright Row"), instructions: ["Grip bar narrower than shoulder-width", "Pull bar up along body to chin level", "Lead with elbows", "Lower with control"], contraindicated_injuries: ["shoulder", "wrist", "neck"], contraindicated_conditions: [], alternatives: ["lateral-raise", "cable-upright-row"], calories_per_set: 6 },
{ name: "Band Pull Apart", name_tr: "Bant Pull Apart", muscle_group: "shoulders", secondary_muscles: ["back"], equipment: "resistance_band", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "15-20", rest_seconds: 30, tempo: "2-1-2-0", gif: gifUrl("Band Pull Apart"), instructions: ["Hold band at shoulder height with arms extended", "Pull band apart by squeezing shoulder blades", "Stretch band to chest level", "Return slowly"], contraindicated_injuries: [], contraindicated_conditions: [], alternatives: ["reverse-fly", "face-pull"], calories_per_set: 4 },
{ name: "Resistance Band Lateral Raise", name_tr: "Bantli Lateral Raise", muscle_group: "shoulders", secondary_muscles: [], equipment: "resistance_band", location: ["home", "none"], difficulty: "beginner", sets: 3, reps: "15-20", rest_seconds: 45, tempo: "2-1-2-0", gif: gifUrl("Resistance Band Lateral Raise"), instructions: ["Stand on band with feet together", "Hold handles at sides", "Raise arms to shoulder height", "Lower with control"], contraindicated_injuries: ["shoulder"], contraindicated_conditions: [], alternatives: ["dumbbell-lateral-raise", "band-pull-apart"], calories_per_set: 4 },
],
arms_biceps: [
{ name: "Barbell Curl", name_tr: "Barbell Curl", muscle_group: "arms_biceps", secondary_muscles: ["forearms"], equipment: "barbell", location: ["gym"], difficulty: "beginner", sets: 4, reps: "10-12", rest_seconds: 60, tempo: "2-0-2-1", gif: gifUrl("Barbell Curl"), instructions: ["Stand with bar at arm's length", "Curl bar to shoulder height", "Keep elbows pinned to sides", "Lower with control"], contraindicated_injuries: ["elbow", "wrist"], contraindicated_conditions: [], alternatives: ["dumbbell-curl", "resistance-band-curl"], calories_per_set: 5 },
{ name: "Hammer Curl", name_tr: "Hammer Curl", muscle_group: "arms_biceps", secondary_muscles: ["forearms"], equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "12", rest_seconds: 60, tempo: "2-0-2-1", gif: gifUrl("Hammer Curl"), instructions: ["Hold dumbbells with neutral grip", "Curl to shoulder height", "Keep elbows stationary", "Lower slowly"], contraindicated_injuries: ["elbow", "wrist"], contraindicated_conditions: [], alternatives: ["barbell-curl", "resistance-band-curl"], calories_per_set: 5 },
{ name: "Concentration Curl", name_tr: "Konsantrasyon Curl", muscle_group: "arms_biceps", secondary_muscles: [], equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "12 each arm", rest_seconds: 45, tempo: "2-1-2-1", gif: gifUrl("Concentration Curl"), instructions: ["Sit on bench leaning forward", "Brace elbow against inner thigh", "Curl dumbbell to shoulder", "Lower with full control"], contraindicated_injuries: ["elbow"], contraindicated_conditions: [], alternatives: ["hammer-curl", "cable-curl"], calories_per_set: 4 },
{ name: "Incline Dumbbell Curl", name_tr: "Egik Dumbbell Curl", muscle_group: "arms_biceps", secondary_muscles: [], equipment: "dumbbell", location: ["gym"], difficulty: "intermediate", sets: 3, reps: "10-12", rest_seconds: 60, tempo: "2-0-2-1", gif: gifUrl("Incline Dumbbell Curl"), instructions: ["Sit on incline bench at 45 degrees", "Let arms hang fully extended", "Curl dumbbells up", "Lower to full stretch"], contraindicated_injuries: ["elbow", "shoulder"], contraindicated_conditions: [], alternatives: ["barbell-curl", "cable-curl"], calories_per_set: 5 },
{ name: "Cable Curl", name_tr: "Kablo Curl", muscle_group: "arms_biceps", secondary_muscles: [], equipment: "cable", location: ["gym"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-0", gif: gifUrl("Cable Curl"), instructions: ["Stand facing cable machine", "Grip bar attachment with underhand grip", "Curl to shoulder height", "Lower with control"], contraindicated_injuries: ["elbow", "wrist"], contraindicated_conditions: [], alternatives: ["dumbbell-curl", "resistance-band-curl"], calories_per_set: 5 },
{ name: "Preacher Curl", name_tr: "Preacher Curl", muscle_group: "arms_biceps", secondary_muscles: [], equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 3, reps: "10-12", rest_seconds: 60, tempo: "2-0-3-0", gif: gifUrl("Preacher Curl"), instructions: ["Rest arms on preacher pad", "Grip EZ bar with underhand grip", "Curl bar to shoulder level", "Lower slowly with full stretch"], contraindicated_injuries: ["elbow", "wrist"], contraindicated_conditions: [], alternatives: ["concentration-curl", "cable-curl"], calories_per_set: 5 },
{ name: "Resistance Band Curl", name_tr: "Bantli Curl", muscle_group: "arms_biceps", secondary_muscles: [], equipment: "resistance_band", location: ["home", "none"], difficulty: "beginner", sets: 3, reps: "15-20", rest_seconds: 45, tempo: "2-1-2-0", gif: gifUrl("Resistance Band Curl"), instructions: ["Stand on band", "Grip handles with underhand grip", "Curl up to shoulders", "Lower with control"], contraindicated_injuries: ["elbow"], contraindicated_conditions: [], alternatives: ["dumbbell-curl", "bodyweight-curl"], calories_per_set: 4 },
{ name: "Spider Curl", name_tr: "Spider Curl", muscle_group: "arms_biceps", secondary_muscles: [], equipment: "dumbbell", location: ["gym"], difficulty: "intermediate", sets: 3, reps: "12", rest_seconds: 45, tempo: "2-1-2-0", gif: gifUrl("Spider Curl"), instructions: ["Lie face down on incline bench", "Let arms hang straight down", "Curl dumbbells up", "Squeeze biceps at top"], contraindicated_injuries: ["elbow"], contraindicated_conditions: [], alternatives: ["preacher-curl", "cable-curl"], calories_per_set: 5 },
],
arms_triceps: [
{ name: "Triceps Pushdown", name_tr: "Triceps Pushdown", muscle_group: "arms_triceps", secondary_muscles: [], equipment: "cable", location: ["gym"], difficulty: "beginner", sets: 4, reps: "10-12", rest_seconds: 60, tempo: "2-0-2-1", gif: gifUrl("Triceps Pushdown"), instructions: ["Stand facing cable machine", "Grip bar with overhand grip", "Press down to full extension", "Keep elbows at sides throughout"], contraindicated_injuries: ["elbow", "wrist"], contraindicated_conditions: [], alternatives: ["resistance-band-triceps-extension", "diamond-push-up"], calories_per_set: 5 },
{ name: "Overhead Triceps Extension", name_tr: "Overhead Triceps Extension", muscle_group: "arms_triceps", secondary_muscles: [], equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "12", rest_seconds: 60, tempo: "2-0-3-0", gif: gifUrl("Overhead Triceps Extension"), instructions: ["Hold dumbbell with both hands overhead", "Lower behind head by bending elbows", "Extend back to start", "Keep elbows pointing up"], contraindicated_injuries: ["elbow", "shoulder"], contraindicated_conditions: ["high_blood_pressure", "has_epilepsy"], alternatives: ["triceps-pushdown", "resistance-band-triceps-extension"], calories_per_set: 5 },
{ name: "Skull Crushers", name_tr: "Skull Crusher", muscle_group: "arms_triceps", secondary_muscles: [], equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 3, reps: "10-12", rest_seconds: 60, tempo: "2-0-3-0", gif: gifUrl("Skull Crushers"), instructions: ["Lie on bench holding EZ bar", "Lower bar toward forehead", "Extend arms back to start", "Keep elbows pointing at ceiling"], contraindicated_injuries: ["elbow", "wrist", "shoulder"], contraindicated_conditions: [], alternatives: ["overhead-triceps-extension", "triceps-pushdown"], calories_per_set: 6 },
{ name: "Close Grip Bench Press", name_tr: "Dar Tutus Bench Press", muscle_group: "arms_triceps", secondary_muscles: ["chest", "shoulders"], equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 3, reps: "8-10", rest_seconds: 75, tempo: "2-0-2-0", gif: gifUrl("Close Grip Bench Press"), instructions: ["Lie on bench", "Grip bar at shoulder-width or narrower", "Lower to lower chest", "Press up focusing on triceps"], contraindicated_injuries: ["elbow", "wrist", "shoulder"], contraindicated_conditions: ["heart_condition"], alternatives: ["diamond-push-up", "triceps-pushdown"], calories_per_set: 7 },
{ name: "Triceps Rope Pushdown", name_tr: "Ip ile Triceps Pushdown", muscle_group: "arms_triceps", secondary_muscles: [], equipment: "cable", location: ["gym"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 45, tempo: "2-1-2-0", gif: gifUrl("Triceps Rope Pushdown"), instructions: ["Grip rope attachment", "Press down separating ends at bottom", "Squeeze triceps at full extension", "Return slowly"], contraindicated_injuries: ["elbow"], contraindicated_conditions: [], alternatives: ["triceps-pushdown", "diamond-push-up"], calories_per_set: 5 },
{ name: "Diamond Push-Up", name_tr: "Elmas Sinav", muscle_group: "arms_triceps", secondary_muscles: ["chest", "shoulders"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "intermediate", sets: 3, reps: "12-15", rest_seconds: 45, tempo: "2-0-2-0", gif: gifUrl("Diamond Push-Up"), instructions: ["Place hands close together forming diamond shape", "Keep body in straight line", "Lower chest to hands", "Press up"], contraindicated_injuries: ["wrist", "elbow", "shoulder"], contraindicated_conditions: [], alternatives: ["push-up", "resistance-band-triceps-extension"], calories_per_set: 6 },
{ name: "Triceps Kickback", name_tr: "Triceps Kickback", muscle_group: "arms_triceps", secondary_muscles: [], equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "12 each arm", rest_seconds: 45, tempo: "2-1-2-0", gif: gifUrl("Triceps Kickback"), instructions: ["Hinge forward with one hand on bench", "Hold dumbbell with elbow at 90 degrees", "Extend arm straight back", "Squeeze tricep at top"], contraindicated_injuries: ["elbow"], contraindicated_conditions: [], alternatives: ["overhead-triceps-extension", "diamond-push-up"], calories_per_set: 4 },
{ name: "Bench Dips", name_tr: "Bench Dips", muscle_group: "arms_triceps", secondary_muscles: ["shoulders", "chest"], equipment: "bodyweight", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-0-2-0", gif: gifUrl("Bench Dips"), instructions: ["Place hands on bench edge behind you", "Extend legs forward", "Lower body by bending elbows", "Press back up"], contraindicated_injuries: ["shoulder", "wrist", "elbow"], contraindicated_conditions: [], alternatives: ["diamond-push-up", "triceps-kickback"], calories_per_set: 5 },
{ name: "Resistance Band Triceps Extension", name_tr: "Bantli Triceps Extension", muscle_group: "arms_triceps", secondary_muscles: [], equipment: "resistance_band", location: ["home", "none"], difficulty: "beginner", sets: 3, reps: "15-20", rest_seconds: 45, tempo: "2-1-2-0", gif: gifUrl("Resistance Band Triceps Extension"), instructions: ["Anchor band overhead or step on it", "Grip behind head", "Extend arms overhead", "Lower with control"], contraindicated_injuries: ["elbow", "shoulder"], contraindicated_conditions: [], alternatives: ["diamond-push-up", "bench-dips"], calories_per_set: 4 },
],
core: [
{ name: "Plank", name_tr: "Plank", muscle_group: "core", secondary_muscles: ["shoulders"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "30-45 seconds", rest_seconds: 30, tempo: "isometric", gif: gifUrl("Plank"), instructions: ["Support body on forearms and toes", "Keep body in straight line", "Engage core tightly", "Breathe steadily"], contraindicated_injuries: ["back", "shoulder", "wrist"], contraindicated_conditions: ["high_blood_pressure"], alternatives: ["dead-bug", "bird-dog"], calories_per_set: 5 },
{ name: "Russian Twist", name_tr: "Rus Twist", muscle_group: "core", secondary_muscles: [], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "20 each side", rest_seconds: 30, tempo: "1-0-1-0", gif: gifUrl("Russian Twist"), instructions: ["Sit with knees bent feet off floor", "Lean back slightly", "Rotate torso side to side", "Keep core engaged throughout"], contraindicated_injuries: ["back", "hip"], contraindicated_conditions: ["has_osteoporosis"], alternatives: ["pallof-press", "side-plank"], calories_per_set: 5 },
{ name: "Bicycle Crunch", name_tr: "Bisiklet Crunch", muscle_group: "core", secondary_muscles: [], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "20 each side", rest_seconds: 30, tempo: "1-0-1-0", gif: gifUrl("Bicycle Crunch"), instructions: ["Lie on back with hands behind head", "Bring opposite elbow to knee", "Alternate sides in cycling motion", "Keep lower back pressed to floor"], contraindicated_injuries: ["back", "neck", "hip"], contraindicated_conditions: ["has_osteoporosis"], alternatives: ["dead-bug", "plank"], calories_per_set: 5 },
{ name: "Leg Raise", name_tr: "Bacak Kaldirma", muscle_group: "core", secondary_muscles: ["hip_flexors"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "intermediate", sets: 3, reps: "15", rest_seconds: 30, tempo: "2-0-2-0", gif: gifUrl("Leg Raise"), instructions: ["Lie flat on back", "Keep legs straight", "Raise legs to 90 degrees", "Lower slowly without touching floor"], contraindicated_injuries: ["back", "hip"], contraindicated_conditions: ["has_osteoporosis"], alternatives: ["dead-bug", "knee-raise"], calories_per_set: 5 },
{ name: "Dead Bug", name_tr: "Dead Bug", muscle_group: "core", secondary_muscles: [], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "12 each side", rest_seconds: 30, tempo: "2-1-2-0", gif: gifUrl("Dead Bug"), instructions: ["Lie on back with arms up and knees at 90 degrees", "Lower opposite arm and leg", "Keep lower back pressed to floor", "Return and alternate"], contraindicated_injuries: [], contraindicated_conditions: [], alternatives: ["plank", "bird-dog"], calories_per_set: 4 },
{ name: "Side Plank", name_tr: "Yan Plank", muscle_group: "core", secondary_muscles: ["shoulders"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "intermediate", sets: 2, reps: "30 seconds each side", rest_seconds: 30, tempo: "isometric", gif: gifUrl("Side Plank"), instructions: ["Lie on side propped on forearm", "Stack feet or stagger them", "Lift hips creating straight line", "Hold and breathe steadily"], contraindicated_injuries: ["shoulder", "wrist"], contraindicated_conditions: [], alternatives: ["pallof-press", "plank"], calories_per_set: 4 },
{ name: "Ab Wheel Rollout", name_tr: "Ab Wheel Rollout", muscle_group: "core", secondary_muscles: ["shoulders", "back"], equipment: "bodyweight", location: ["gym", "home"], difficulty: "advanced", sets: 3, reps: "10-12", rest_seconds: 45, tempo: "3-0-2-0", gif: gifUrl("Ab Wheel Rollout"), instructions: ["Kneel holding ab wheel", "Roll forward extending body", "Keep core tight and back flat", "Roll back to start"], contraindicated_injuries: ["back", "shoulder", "wrist"], contraindicated_conditions: ["high_blood_pressure"], alternatives: ["plank", "dead-bug"], calories_per_set: 6 },
{ name: "Cable Crunch", name_tr: "Kablo Crunch", muscle_group: "core", secondary_muscles: [], equipment: "cable", location: ["gym"], difficulty: "intermediate", sets: 3, reps: "15", rest_seconds: 45, tempo: "2-1-2-0", gif: gifUrl("Cable Crunch"), instructions: ["Kneel facing cable machine", "Hold rope behind head", "Crunch down curling torso", "Return with control"], contraindicated_injuries: ["back", "neck"], contraindicated_conditions: ["has_osteoporosis"], alternatives: ["bicycle-crunch", "plank"], calories_per_set: 5 },
{ name: "Hanging Leg Raise", name_tr: "Asili Bacak Kaldirma", muscle_group: "core", secondary_muscles: ["hip_flexors"], equipment: "bodyweight", location: ["gym", "home"], difficulty: "advanced", sets: 3, reps: "12", rest_seconds: 45, tempo: "2-0-2-0", gif: gifUrl("Hanging Leg Raise"), instructions: ["Hang from pull-up bar", "Raise legs to parallel or higher", "Lower with control", "Avoid swinging"], contraindicated_injuries: ["shoulder", "back", "wrist", "hip"], contraindicated_conditions: ["high_blood_pressure"], alternatives: ["leg-raise", "knee-raise"], calories_per_set: 6 },
{ name: "Pallof Press", name_tr: "Pallof Press", muscle_group: "core", secondary_muscles: [], equipment: "cable", location: ["gym"], difficulty: "intermediate", sets: 3, reps: "12 each side", rest_seconds: 30, tempo: "2-1-2-0", gif: gifUrl("Pallof Press"), instructions: ["Stand sideways to cable machine", "Hold handle at chest", "Press arms straight out", "Resist rotation and return"], contraindicated_injuries: [], contraindicated_conditions: [], alternatives: ["side-plank", "russian-twist"], calories_per_set: 4 },
{ name: "Bird Dog", name_tr: "Bird Dog", muscle_group: "core", secondary_muscles: ["back", "glutes"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "12 each side", rest_seconds: 30, tempo: "2-1-2-0", gif: gifUrl("Bird Dog"), instructions: ["Start on hands and knees", "Extend opposite arm and leg", "Keep back flat and hips level", "Return and alternate"], contraindicated_injuries: ["wrist"], contraindicated_conditions: [], alternatives: ["dead-bug", "plank"], calories_per_set: 4 },
{ name: "Mountain Climber", name_tr: "Dagci", muscle_group: "core", secondary_muscles: ["shoulders", "hip_flexors"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "intermediate", sets: 3, reps: "20 each side", rest_seconds: 30, tempo: "1-0-1-0", gif: gifUrl("Mountain Climber"), instructions: ["Start in push-up position", "Drive one knee toward chest", "Quickly switch legs", "Keep core tight and hips level"], contraindicated_injuries: ["wrist", "shoulder"], contraindicated_conditions: ["heart_condition"], alternatives: ["plank", "dead-bug"], calories_per_set: 6 },
],
glutes: [
{ name: "Barbell Hip Thrust", name_tr: "Barbell Hip Thrust", muscle_group: "glutes", secondary_muscles: ["legs", "core"], equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 4, reps: "10-12", rest_seconds: 90, tempo: "2-1-2-0", gif: gifUrl("Barbell Hip Thrust"), instructions: ["Sit on floor with upper back on bench", "Roll barbell over hips", "Drive hips to ceiling squeezing glutes", "Lower with control"], contraindicated_injuries: ["back", "hip", "knee"], contraindicated_conditions: [], alternatives: ["glute-bridge", "dumbbell-hip-thrust"], calories_per_set: 8 },
{ name: "Cable Kickback", name_tr: "Kablo Kickback", muscle_group: "glutes", secondary_muscles: [], equipment: "cable", location: ["gym"], difficulty: "beginner", sets: 3, reps: "12-15 each leg", rest_seconds: 45, tempo: "2-1-2-0", gif: gifUrl("Cable Kickback"), instructions: ["Attach ankle strap to cable", "Face the machine", "Kick leg back and up", "Squeeze glute at top"], contraindicated_injuries: ["hip", "knee", "ankle"], contraindicated_conditions: [], alternatives: ["donkey-kick", "resistance-band-kickback"], calories_per_set: 5 },
{ name: "Glute Bridge", name_tr: "Glute Bridge", muscle_group: "glutes", secondary_muscles: ["core"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "15-20", rest_seconds: 30, tempo: "2-1-2-0", gif: gifUrl("Glute Bridge"), instructions: ["Lie on back with knees bent feet flat", "Drive hips up squeezing glutes", "Hold at top briefly", "Lower with control"], contraindicated_injuries: ["back"], contraindicated_conditions: [], alternatives: ["hip-thrust", "donkey-kick"], calories_per_set: 5 },
{ name: "Donkey Kick", name_tr: "Donkey Kick", muscle_group: "glutes", secondary_muscles: [], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "15 each leg", rest_seconds: 30, tempo: "2-1-2-0", gif: gifUrl("Donkey Kick"), instructions: ["Start on hands and knees", "Kick one leg up toward ceiling", "Keep knee bent at 90 degrees", "Squeeze glute at top"], contraindicated_injuries: ["wrist", "knee"], contraindicated_conditions: [], alternatives: ["glute-bridge", "fire-hydrant"], calories_per_set: 4 },
{ name: "Fire Hydrant", name_tr: "Fire Hydrant", muscle_group: "glutes", secondary_muscles: ["hip_flexors"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "15 each leg", rest_seconds: 30, tempo: "2-1-2-0", gif: gifUrl("Fire Hydrant"), instructions: ["Start on hands and knees", "Lift knee out to the side", "Keep 90-degree bend in knee", "Lower with control"], contraindicated_injuries: ["wrist", "knee", "hip"], contraindicated_conditions: [], alternatives: ["donkey-kick", "clamshell"], calories_per_set: 4 },
{ name: "Sumo Squat", name_tr: "Sumo Squat", muscle_group: "glutes", secondary_muscles: ["legs"], equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-0", gif: gifUrl("Sumo Squat"), instructions: ["Stand with wide stance toes pointed out", "Hold dumbbell in front", "Squat down keeping torso upright", "Drive through heels to stand"], contraindicated_injuries: ["knee", "hip", "ankle"], contraindicated_conditions: [], alternatives: ["goblet-squat", "glute-bridge"], calories_per_set: 7 },
{ name: "Banded Crab Walk", name_tr: "Bantli Yengec Yuruyusu", muscle_group: "glutes", secondary_muscles: [], equipment: "resistance_band", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "15 steps each direction", rest_seconds: 30, tempo: "controlled", gif: gifUrl("Banded Crab Walk"), instructions: ["Place band above knees", "Get in quarter squat position", "Step sideways maintaining tension", "Keep band taut throughout"], contraindicated_injuries: ["knee", "ankle", "hip"], contraindicated_conditions: [], alternatives: ["fire-hydrant", "clamshell"], calories_per_set: 5 },
{ name: "Clamshell", name_tr: "Clamshell", muscle_group: "glutes", secondary_muscles: ["hip_flexors"], equipment: "resistance_band", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "15 each side", rest_seconds: 30, tempo: "2-1-2-0", gif: gifUrl("Clamshell"), instructions: ["Lie on side with knees bent", "Place band above knees if available", "Open top knee like a clamshell", "Lower with control"], contraindicated_injuries: ["hip"], contraindicated_conditions: [], alternatives: ["fire-hydrant", "glute-bridge"], calories_per_set: 4 },
],
cardio: [
{ name: "Treadmill Running", name_tr: "Kosus Bandi", muscle_group: "cardio", secondary_muscles: ["legs", "core"], equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 1, reps: "25 minutes", rest_seconds: 0, tempo: "steady", gif: gifUrl("Treadmill Running"), instructions: ["Set moderate pace", "Keep heart rate at 65-75% max", "Maintain upright posture", "Land midfoot"], contraindicated_injuries: ["knee", "ankle", "hip"], contraindicated_conditions: ["heart_condition"], alternatives: ["elliptical", "stationary-bike"], calories_per_set: 45 },
{ name: "Stationary Bike", name_tr: "Bisiklet", muscle_group: "cardio", secondary_muscles: ["legs"], equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 1, reps: "20 minutes", rest_seconds: 0, tempo: "steady", gif: gifUrl("Stationary Bike"), instructions: ["Adjust seat height", "Set moderate resistance", "Maintain steady cadence", "Keep back straight"], contraindicated_injuries: ["knee"], contraindicated_conditions: [], alternatives: ["treadmill-running", "elliptical"], calories_per_set: 35 },
{ name: "Rowing Machine", name_tr: "Kurek Makinesi", muscle_group: "cardio", secondary_muscles: ["back", "legs", "core"], equipment: "machine", location: ["gym"], difficulty: "intermediate", sets: 1, reps: "15 minutes", rest_seconds: 0, tempo: "steady", gif: gifUrl("Rowing Machine"), instructions: ["Strap feet in footrests", "Drive with legs first", "Follow with back lean", "Pull handle to lower ribs"], contraindicated_injuries: ["back", "wrist"], contraindicated_conditions: [], alternatives: ["stationary-bike", "elliptical"], calories_per_set: 40 },
{ name: "Stair Climber", name_tr: "Merdiven Cikmaci", muscle_group: "cardio", secondary_muscles: ["legs", "glutes"], equipment: "machine", location: ["gym"], difficulty: "intermediate", sets: 1, reps: "15 minutes", rest_seconds: 0, tempo: "steady", gif: gifUrl("Stair Climber"), instructions: ["Start at moderate pace", "Keep upright posture", "Drive through whole foot", "Avoid leaning on handrails"], contraindicated_injuries: ["knee", "ankle", "hip"], contraindicated_conditions: ["heart_condition"], alternatives: ["stationary-bike", "elliptical"], calories_per_set: 40 },
{ name: "Elliptical", name_tr: "Eliptik", muscle_group: "cardio", secondary_muscles: ["legs", "core"], equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 1, reps: "20 minutes", rest_seconds: 0, tempo: "steady", gif: gifUrl("Elliptical"), instructions: ["Grip handles lightly", "Push and pull with arms", "Maintain smooth stride", "Keep moderate resistance"], contraindicated_injuries: [], contraindicated_conditions: [], alternatives: ["stationary-bike", "treadmill-running"], calories_per_set: 35 },
{ name: "Incline Walking", name_tr: "Egimli Yuruyus", muscle_group: "cardio", secondary_muscles: ["legs", "glutes"], equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 1, reps: "30 minutes", rest_seconds: 0, tempo: "steady", gif: gifUrl("Incline Walking"), instructions: ["Set treadmill to 10-15% incline", "Walk at brisk pace", "Keep hands off rails", "Maintain upright posture"], contraindicated_injuries: ["ankle"], contraindicated_conditions: [], alternatives: ["outdoor-walking", "stationary-bike"], calories_per_set: 40 },
{ name: "Jump Rope", name_tr: "Ip Atlama", muscle_group: "cardio", secondary_muscles: ["legs", "shoulders", "core"], equipment: "bodyweight", location: ["gym", "home"], difficulty: "intermediate", sets: 3, reps: "3 minutes", rest_seconds: 60, tempo: "steady", gif: gifUrl("Jump Rope"), instructions: ["Hold rope handles at hip height", "Jump with both feet slightly off ground", "Use wrist to turn rope", "Land softly on balls of feet"], contraindicated_injuries: ["knee", "ankle", "wrist"], contraindicated_conditions: ["heart_condition", "has_osteoporosis"], alternatives: ["mountain-climber", "marching-in-place"], calories_per_set: 15 },
],
hiit: [
{ name: "Burpee", name_tr: "Burpee", muscle_group: "hiit", secondary_muscles: ["chest", "legs", "core"], equipment: "bodyweight", location: ["gym", "home"], difficulty: "advanced", sets: 4, reps: "30 seconds", rest_seconds: 30, tempo: "explosive", gif: gifUrl("Burpee"), instructions: ["Start standing", "Drop to push-up position", "Perform push-up", "Jump feet to hands and jump up"], contraindicated_injuries: ["knee", "wrist", "shoulder", "back", "ankle"], contraindicated_conditions: ["heart_condition", "high_blood_pressure", "has_epilepsy", "has_arthritis"], alternatives: ["mountain-climber", "squat-thrust"], calories_per_set: 12 },
{ name: "Jump Squat", name_tr: "Sicramali Squat", muscle_group: "hiit", secondary_muscles: ["legs", "glutes"], equipment: "bodyweight", location: ["gym", "home"], difficulty: "intermediate", sets: 4, reps: "30 seconds", rest_seconds: 30, tempo: "explosive", gif: gifUrl("Jump Squat"), instructions: ["Squat down", "Explode up into jump", "Land softly with bent knees", "Immediately go into next squat"], contraindicated_injuries: ["knee", "ankle", "back", "hip"], contraindicated_conditions: ["heart_condition", "has_osteoporosis", "has_arthritis"], alternatives: ["bodyweight-squat", "wall-sit"], calories_per_set: 10 },
{ name: "High Knees", name_tr: "Yuksek Diz", muscle_group: "hiit", secondary_muscles: ["core", "legs"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "intermediate", sets: 4, reps: "30 seconds", rest_seconds: 30, tempo: "explosive", gif: gifUrl("High Knees"), instructions: ["Stand in place", "Drive knees up to chest alternately", "Pump arms", "Stay on balls of feet"], contraindicated_injuries: ["knee", "hip", "ankle"], contraindicated_conditions: ["heart_condition", "has_arthritis"], alternatives: ["marching-in-place", "step-touch"], calories_per_set: 10 },
{ name: "Box Jump", name_tr: "Box Jump", muscle_group: "hiit", secondary_muscles: ["legs", "glutes"], equipment: "bodyweight", location: ["gym"], difficulty: "advanced", sets: 4, reps: "30 seconds", rest_seconds: 30, tempo: "explosive", gif: gifUrl("Box Jump"), instructions: ["Stand facing box", "Swing arms and jump onto box", "Land softly with both feet", "Step down carefully"], contraindicated_injuries: ["knee", "ankle", "back", "hip"], contraindicated_conditions: ["heart_condition", "has_epilepsy", "has_osteoporosis"], alternatives: ["step-up", "bodyweight-squat"], calories_per_set: 10 },
{ name: "Battle Ropes", name_tr: "Savas Ipleri", muscle_group: "hiit", secondary_muscles: ["shoulders", "core"], equipment: "bodyweight", location: ["gym"], difficulty: "intermediate", sets: 4, reps: "30 seconds", rest_seconds: 30, tempo: "explosive", gif: gifUrl("Battle Ropes"), instructions: ["Grip rope ends", "Create waves with alternating arms", "Keep core engaged", "Maintain athletic stance"], contraindicated_injuries: ["shoulder", "wrist", "elbow", "back"], contraindicated_conditions: ["heart_condition", "high_blood_pressure"], alternatives: ["mountain-climber", "jump-rope"], calories_per_set: 12 },
{ name: "Kettlebell Swing", name_tr: "Kettlebell Swing", muscle_group: "hiit", secondary_muscles: ["glutes", "back", "core"], equipment: "kettlebell", location: ["gym", "home"], difficulty: "intermediate", sets: 4, reps: "30 seconds", rest_seconds: 30, tempo: "explosive", gif: gifUrl("Kettlebell Swing"), instructions: ["Hinge at hips with kettlebell between legs", "Drive hips forward swinging weight up", "Let gravity bring it back", "Maintain flat back throughout"], contraindicated_injuries: ["back", "wrist", "hip"], contraindicated_conditions: ["heart_condition", "high_blood_pressure"], alternatives: ["dumbbell-swing", "glute-bridge"], calories_per_set: 11 },
{ name: "Skating Lunges", name_tr: "Paten Hamle", muscle_group: "hiit", secondary_muscles: ["legs", "glutes"], equipment: "bodyweight", location: ["gym", "home"], difficulty: "intermediate", sets: 4, reps: "30 seconds", rest_seconds: 30, tempo: "explosive", gif: gifUrl("Skating Lunges"), instructions: ["Jump laterally from one foot to the other", "Land softly on outside foot", "Swing opposite leg behind", "Alternate continuously"], contraindicated_injuries: ["knee", "ankle", "hip"], contraindicated_conditions: ["has_arthritis", "has_osteoporosis"], alternatives: ["lateral-step-touch", "bodyweight-squat"], calories_per_set: 10 },
{ name: "Plyo Push-Up", name_tr: "Patlayici Sinav", muscle_group: "hiit", secondary_muscles: ["chest", "triceps", "shoulders"], equipment: "bodyweight", location: ["gym", "home"], difficulty: "advanced", sets: 4, reps: "30 seconds", rest_seconds: 30, tempo: "explosive", gif: gifUrl("Plyo Push-Up"), instructions: ["Perform a push-up", "Push off floor explosively", "Hands leave the ground at top", "Land softly and repeat"], contraindicated_injuries: ["wrist", "shoulder", "elbow"], contraindicated_conditions: ["heart_condition", "has_epilepsy"], alternatives: ["push-up", "incline-push-up"], calories_per_set: 9 },
{ name: "Marching In Place", name_tr: "Yerinde Yuruyus", muscle_group: "hiit", secondary_muscles: ["legs", "core"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "60 seconds", rest_seconds: 30, tempo: "moderate", gif: gifUrl("Marching In Place"), instructions: ["Stand tall", "Lift knees alternately to hip height", "Pump arms naturally", "Maintain steady rhythm"], contraindicated_injuries: [], contraindicated_conditions: [], alternatives: ["high-knees", "step-touch"], calories_per_set: 6 },
],
flexibility: [
{ name: "Cat-Cow Stretch", name_tr: "Kedi-Inek Germe", muscle_group: "flexibility", secondary_muscles: ["back", "core"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 1, reps: "10 reps", rest_seconds: 0, tempo: "slow", gif: gifUrl("Cat-Cow Stretch"), instructions: ["Start on hands and knees", "Arch back dropping belly (cow)", "Round back tucking chin (cat)", "Sync with breathing"], contraindicated_injuries: ["wrist"], contraindicated_conditions: [], alternatives: ["seated-spinal-twist"], calories_per_set: 2 },
{ name: "Hamstring Stretch", name_tr: "Hamstring Germe", muscle_group: "flexibility", secondary_muscles: ["back"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 1, reps: "30 seconds each leg", rest_seconds: 0, tempo: "slow", gif: gifUrl("Hamstring Stretch"), instructions: ["Sit with one leg extended", "Reach toward toes", "Hold gentle stretch", "Breathe deeply"], contraindicated_injuries: [], contraindicated_conditions: [], alternatives: ["standing-hamstring-stretch"], calories_per_set: 1 },
{ name: "Quad Stretch", name_tr: "Quadriceps Germe", muscle_group: "flexibility", secondary_muscles: [], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 1, reps: "30 seconds each leg", rest_seconds: 0, tempo: "slow", gif: gifUrl("Quad Stretch"), instructions: ["Stand on one leg", "Grab ankle behind you", "Pull heel toward glute", "Keep knees together"], contraindicated_injuries: ["knee"], contraindicated_conditions: [], alternatives: ["lying-quad-stretch"], calories_per_set: 1 },
{ name: "Pigeon Pose", name_tr: "Guvercin Pozu", muscle_group: "flexibility", secondary_muscles: ["glutes", "hip_flexors"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "intermediate", sets: 1, reps: "30 seconds each side", rest_seconds: 0, tempo: "slow", gif: gifUrl("Pigeon Pose"), instructions: ["From all fours bring one knee forward", "Extend back leg behind", "Sink hips toward floor", "Hold and breathe deeply"], contraindicated_injuries: ["hip", "knee"], contraindicated_conditions: [], alternatives: ["figure-four-stretch"], calories_per_set: 1 },
{ name: "Child's Pose", name_tr: "Cocuk Pozu", muscle_group: "flexibility", secondary_muscles: ["back", "shoulders"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 1, reps: "45 seconds", rest_seconds: 0, tempo: "slow", gif: gifUrl("Child's Pose"), instructions: ["Kneel on floor", "Sit back on heels", "Reach arms forward on floor", "Rest forehead on ground"], contraindicated_injuries: ["knee"], contraindicated_conditions: [], alternatives: ["seated-forward-fold"], calories_per_set: 1 },
{ name: "Butterfly Stretch", name_tr: "Kelebek Germe", muscle_group: "flexibility", secondary_muscles: ["hip_flexors"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 1, reps: "30 seconds", rest_seconds: 0, tempo: "slow", gif: gifUrl("Butterfly Stretch"), instructions: ["Sit with soles of feet together", "Let knees fall open", "Hold feet and lean forward gently", "Breathe into the stretch"], contraindicated_injuries: ["hip"], contraindicated_conditions: [], alternatives: ["seated-straddle-stretch"], calories_per_set: 1 },
{ name: "Shoulder Cross Stretch", name_tr: "Omuz Capraz Germe", muscle_group: "flexibility", secondary_muscles: ["shoulders"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 1, reps: "30 seconds each arm", rest_seconds: 0, tempo: "slow", gif: gifUrl("Shoulder Cross Stretch"), instructions: ["Bring one arm across chest", "Hold with opposite hand", "Keep shoulder down", "Feel stretch in rear delt"], contraindicated_injuries: [], contraindicated_conditions: [], alternatives: ["doorway-chest-stretch"], calories_per_set: 1 },
{ name: "Downward Dog", name_tr: "Asagi Bakan Kopek", muscle_group: "flexibility", secondary_muscles: ["back", "shoulders", "legs"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 1, reps: "45 seconds", rest_seconds: 0, tempo: "slow", gif: gifUrl("Downward Dog"), instructions: ["Start on hands and knees", "Push hips up and back", "Straighten legs and arms", "Press heels toward floor"], contraindicated_injuries: ["wrist", "shoulder"], contraindicated_conditions: ["high_blood_pressure"], alternatives: ["standing-forward-fold"], calories_per_set: 2 },
{ name: "World's Greatest Stretch", name_tr: "Dunyanin En Iyi Germesi", muscle_group: "flexibility", secondary_muscles: ["hip_flexors", "back", "shoulders"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "intermediate", sets: 1, reps: "5 each side", rest_seconds: 0, tempo: "slow", gif: gifUrl("World's Greatest Stretch"), instructions: ["Step into lunge position", "Place same-side hand on floor", "Rotate opposite arm to ceiling", "Hold briefly and switch"], contraindicated_injuries: [], contraindicated_conditions: [], alternatives: ["hip-flexor-stretch"], calories_per_set: 2 },
{ name: "Foam Roll Back", name_tr: "Foam Roller Sirt", muscle_group: "flexibility", secondary_muscles: ["back"], equipment: "bodyweight", location: ["gym", "home"], difficulty: "beginner", sets: 1, reps: "60 seconds", rest_seconds: 0, tempo: "slow", gif: gifUrl("Foam Roll Back"), instructions: ["Lie on foam roller under upper back", "Cross arms over chest", "Roll slowly up and down", "Pause on tender spots"], contraindicated_injuries: [], contraindicated_conditions: [], alternatives: ["cat-cow-stretch"], calories_per_set: 1 },
{ name: "Foam Roll Legs", name_tr: "Foam Roller Bacak", muscle_group: "flexibility", secondary_muscles: ["legs"], equipment: "bodyweight", location: ["gym", "home"], difficulty: "beginner", sets: 1, reps: "60 seconds each leg", rest_seconds: 0, tempo: "slow", gif: gifUrl("Foam Roll Legs"), instructions: ["Place roller under thigh", "Support body with arms", "Roll slowly from hip to knee", "Spend extra time on tight spots"], contraindicated_injuries: [], contraindicated_conditions: [], alternatives: ["hamstring-stretch"], calories_per_set: 1 },
{ name: "Neck Stretch", name_tr: "Boyun Germe", muscle_group: "flexibility", secondary_muscles: [], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 1, reps: "30 seconds each direction", rest_seconds: 0, tempo: "slow", gif: gifUrl("Neck Stretch"), instructions: ["Tilt ear toward shoulder", "Hold gently with hand", "Keep opposite shoulder down", "Repeat each side"], contraindicated_injuries: ["neck"], contraindicated_conditions: [], alternatives: ["chin-tuck"], calories_per_set: 1 },
{ name: "Thoracic Spine Rotation", name_tr: "Torasik Omurga Rotasyonu", muscle_group: "flexibility", secondary_muscles: ["back", "core"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 1, reps: "10 each side", rest_seconds: 0, tempo: "slow", gif: gifUrl("Thoracic Spine Rotation"), instructions: ["Lie on side with knees bent", "Extend top arm across body", "Rotate open toward ceiling", "Return slowly"], contraindicated_injuries: [], contraindicated_conditions: [], alternatives: ["cat-cow-stretch"], calories_per_set: 1 },
{ name: "Hip Flexor Stretch", name_tr: "Kalca Fleksor Germe", muscle_group: "flexibility", secondary_muscles: ["hip_flexors", "legs"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 1, reps: "30 seconds each side", rest_seconds: 0, tempo: "slow", gif: gifUrl("Hip Flexor Stretch"), instructions: ["Kneel on one knee", "Push hips forward", "Keep torso upright", "Feel stretch in front of hip"], contraindicated_injuries: ["knee", "hip"], contraindicated_conditions: [], alternatives: ["standing-hip-flexor-stretch"], calories_per_set: 1 },
{ name: "Chest Doorway Stretch", name_tr: "Gogus Germe", muscle_group: "flexibility", secondary_muscles: ["chest", "shoulders"], equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 1, reps: "30 seconds", rest_seconds: 0, tempo: "slow", gif: gifUrl("Chest Doorway Stretch"), instructions: ["Stand in doorway", "Place forearms on frame", "Lean forward gently", "Feel stretch across chest"], contraindicated_injuries: ["shoulder"], contraindicated_conditions: [], alternatives: ["shoulder-cross-stretch"], calories_per_set: 1 },
],
};
// ─────────────────────────────────────────────────────────────────────────────
// Turkish day names
// ─────────────────────────────────────────────────────────────────────────────
const DAYS_TR = ["Pazartesi", "Sali", "Carsamba", "Persembe", "Cuma", "Cumartesi", "Pazar"];
// ─────────────────────────────────────────────────────────────────────────────
// Mesocycle configuration (4-week progression)
// ─────────────────────────────────────────────────────────────────────────────
const MESOCYCLE = {
1: { phase: "Foundation", intensity_multiplier: 1.0, volume_multiplier: 1.0, description: "Foundation week - focus on form and technique" },
2: { phase: "Progression", intensity_multiplier: 1.05, volume_multiplier: 1.0, description: "+5% intensity increase" },
3: { phase: "Overreach", intensity_multiplier: 1.10, volume_multiplier: 1.0, description: "+10% intensity increase" },
4: { phase: "Deload", intensity_multiplier: 0.85, volume_multiplier: 0.6, description: "Deload week - volume reduced 40%, recovery focus" },
};
// ─────────────────────────────────────────────────────────────────────────────
// Injury-specific warm-up routines
// ─────────────────────────────────────────────────────────────────────────────
const INJURY_WARMUPS = {
knee: [
{ name: "Knee Area Foam Rolling", duration: "2 min", notes: "Roll slowly along quads and IT band" },
{ name: "Terminal Knee Extension (Banded)", duration: "2 min", notes: "Band-assisted knee extension, 15 reps each leg" },
{ name: "Wall Slide Squat", duration: "2 min", notes: "Lean against wall and slide down slowly with controlled knee angle" },
{ name: "Light Heel Raises", duration: "1 min", notes: "Calf and knee stabilization, 20 reps" },
],
back: [
{ name: "Cat-Cow Mobility", duration: "2 min", notes: "Slow and controlled, sync with breathing" },
{ name: "Pelvic Tilt", duration: "2 min", notes: "Lying supine, press lower back into floor" },
{ name: "Light Bird Dog", duration: "2 min", notes: "Opposite arm-leg extension, 10 reps each side" },
{ name: "Child's Pose Hold", duration: "1 min", notes: "Back relaxation with deep breathing" },
],
shoulder: [
{ name: "Shoulder Pendulum", duration: "2 min", notes: "Lean forward and swing arm freely, 30 seconds each direction" },
{ name: "Banded External Rotation", duration: "2 min", notes: "Elbow at 90 degrees, light band, 15 reps" },
{ name: "Banded Internal Rotation", duration: "2 min", notes: "Elbow at 90 degrees, light band, 15 reps" },
{ name: "Wall Slide", duration: "1 min", notes: "Back against wall, slide arms up and down, 10 reps" },
],
elbow: [
{ name: "Wrist and Forearm Stretch", duration: "2 min", notes: "Extend arm, push wrist up and down" },
{ name: "Elbow Flexion/Extension", duration: "1 min", notes: "No weight, full range of motion, 15 reps" },
{ name: "Forearm Pronation/Supination", duration: "2 min", notes: "Light weight wrist rotations, 15 reps" },
],
wrist: [
{ name: "Wrist Circles", duration: "2 min", notes: "Clockwise and counter-clockwise, 15 reps each" },
{ name: "Finger Open/Close", duration: "1 min", notes: "With stress ball or band, 20 reps" },
{ name: "Wrist Flexor/Extensor Stretch", duration: "2 min", notes: "30 seconds each position" },
],
ankle: [
{ name: "Ankle Circles", duration: "2 min", notes: "Each direction 15 reps, slow and controlled" },
{ name: "Calf Stretch (Wall)", duration: "2 min", notes: "Lean into wall, heel on ground, 30 seconds each leg" },
{ name: "Single Leg Balance", duration: "2 min", notes: "30 seconds each foot, stability work" },
],
hip: [
{ name: "Hip Circles", duration: "2 min", notes: "Standing large circles, 15 reps each direction" },
{ name: "Clamshell", duration: "2 min", notes: "Side lying, with band, 15 reps each side" },
{ name: "90/90 Hip Stretch", duration: "2 min", notes: "Seated on floor, internal and external rotation" },
{ name: "Hip Flexor Stretch", duration: "1 min", notes: "Half kneeling, 30 seconds each side" },
],
neck: [
{ name: "Neck Lateral Flexion", duration: "1 min", notes: "Each side 30 seconds, slow movement" },
{ name: "Neck Rotation", duration: "1 min", notes: "Turn left and right, 10 reps each" },
{ name: "Chin Tuck", duration: "1 min", notes: "Posture correction, 15 reps" },
{ name: "Upper Trap Stretch", duration: "1 min", notes: "Tilt head to side with gentle hand pressure, 30 seconds" },
],
none: [],
};
// ─────────────────────────────────────────────────────────────────────────────
// Alternative exercises for injured areas
// ─────────────────────────────────────────────────────────────────────────────
const INJURY_ALTERNATIVES = {
knee: [
{ name: "Leg Press (Limited ROM)", name_tr: "Bacak Presi (Sinirli ROM)", muscle_group: "legs", equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 75, tempo: "3-1-2-0", gif: gifUrl("Leg Press Limited ROM"), instructions: ["Do not let knee bend past 90 degrees"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 6 },
{ name: "Glute Bridge", name_tr: "Glute Bridge", muscle_group: "glutes", equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "15-20", rest_seconds: 30, tempo: "2-1-2-0", gif: gifUrl("Glute Bridge"), instructions: ["No knee stress, glute focused"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 5 },
{ name: "Seated Leg Curl (Light)", name_tr: "Oturarak Bacak Curl (Hafif)", muscle_group: "legs", equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 3, reps: "15", rest_seconds: 60, tempo: "2-1-3-0", gif: gifUrl("Seated Leg Curl Light"), instructions: ["Light weight, controlled movement"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 5 },
],
back: [
{ name: "Chest Supported Row", name_tr: "Gogus Destekli Row", muscle_group: "back", equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-1", gif: gifUrl("Chest Supported Row"), instructions: ["Chest against incline bench, no spinal load"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 6 },
{ name: "Lat Pulldown (Light)", name_tr: "Lat Pulldown (Hafif)", muscle_group: "back", equipment: "cable", location: ["gym"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-1", gif: gifUrl("Lat Pulldown Light"), instructions: ["Light weight, upright seated posture"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 5 },
{ name: "Band Pull Apart", name_tr: "Bant Pull Apart", muscle_group: "shoulders", equipment: "resistance_band", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "15-20", rest_seconds: 30, tempo: "2-1-2-0", gif: gifUrl("Band Pull Apart"), instructions: ["Rear delt and upper back, no spinal load"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 3 },
],
shoulder: [
{ name: "Landmine Press (Shoulder-Friendly)", name_tr: "Landmine Press", muscle_group: "chest", equipment: "barbell", location: ["gym"], difficulty: "intermediate", sets: 3, reps: "10-12", rest_seconds: 75, tempo: "2-0-2-0", gif: gifUrl("Landmine Press"), instructions: ["Shoulder-friendly angle, less stress"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 7 },
{ name: "Floor Press", name_tr: "Yer Presi", muscle_group: "chest", equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "10-12", rest_seconds: 75, tempo: "2-1-2-0", gif: gifUrl("Floor Press"), instructions: ["Limited ROM protects shoulder"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 7 },
{ name: "Banded External Rotation", name_tr: "Bantli Dis Rotasyon", muscle_group: "shoulders", equipment: "resistance_band", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "15", rest_seconds: 30, tempo: "2-1-2-0", gif: gifUrl("Banded External Rotation"), instructions: ["Rotator cuff strengthening"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 3 },
],
elbow: [
{ name: "Resistance Band Curl (Light)", name_tr: "Bantli Curl (Hafif)", muscle_group: "arms_biceps", equipment: "resistance_band", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "15-20", rest_seconds: 45, tempo: "2-1-3-0", gif: gifUrl("Resistance Band Curl Light"), instructions: ["Light band biceps work"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 3 },
{ name: "Isometric Biceps Hold", name_tr: "Izometrik Biceps Tutma", muscle_group: "arms_biceps", equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "20 seconds", rest_seconds: 30, tempo: "isometric", gif: gifUrl("Isometric Biceps Hold"), instructions: ["Hold position, minimal joint stress"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 2 },
],
wrist: [
{ name: "Hammer Grip Row", name_tr: "Hammer Grip Row", muscle_group: "back", equipment: "dumbbell", location: ["gym", "home"], difficulty: "beginner", sets: 3, reps: "12", rest_seconds: 60, tempo: "2-0-2-1", gif: gifUrl("Hammer Grip Row"), instructions: ["Neutral grip keeps wrist in safe position"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 6 },
{ name: "Machine Chest Press (Palm Grip)", name_tr: "Makine Gogus Presi", muscle_group: "chest", equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 3, reps: "12", rest_seconds: 60, tempo: "2-0-2-0", gif: gifUrl("Machine Chest Press"), instructions: ["Machine reduces wrist stress"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 7 },
],
ankle: [
{ name: "Seated Leg Press", name_tr: "Oturarak Bacak Presi", muscle_group: "legs", equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 3, reps: "12", rest_seconds: 75, tempo: "2-0-2-0", gif: gifUrl("Seated Leg Press"), instructions: ["Minimal ankle stress"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 8 },
{ name: "Leg Extension", name_tr: "Bacak Extension", muscle_group: "legs", equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-0", gif: gifUrl("Leg Extension"), instructions: ["No ankle load"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 6 },
],
hip: [
{ name: "Leg Extension (Isolated)", name_tr: "Bacak Extension (Izole)", muscle_group: "legs", equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-0", gif: gifUrl("Leg Extension Isolated"), instructions: ["Minimal hip stress"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 6 },
{ name: "Seated Leg Curl", name_tr: "Oturarak Bacak Curl", muscle_group: "legs", equipment: "machine", location: ["gym"], difficulty: "beginner", sets: 3, reps: "12-15", rest_seconds: 60, tempo: "2-1-2-0", gif: gifUrl("Seated Leg Curl"), instructions: ["Seated position keeps hip stable"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 5 },
],
neck: [
{ name: "Isometric Neck Exercise", name_tr: "Izometrik Boyun Egzersizi", muscle_group: "core", equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 3, reps: "10 seconds each direction", rest_seconds: 15, tempo: "isometric", gif: gifUrl("Isometric Neck Exercise"), instructions: ["Apply hand resistance while holding neck still"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 2 },
],
none: [],
};
// ─────────────────────────────────────────────────────────────────────────────
// Desk worker mobility exercises
// ─────────────────────────────────────────────────────────────────────────────
const DESK_MOBILITY = [
{ name: "Thoracic Extension", name_tr: "Torasik Ekstansiyon", muscle_group: "flexibility", equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 2, reps: "10", rest_seconds: 30, tempo: "slow", gif: gifUrl("Thoracic Extension"), instructions: ["Foam roller under upper back, extend over it"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 2 },
{ name: "Band Pull Apart (Posture)", name_tr: "Bant Pull Apart (Durus)", muscle_group: "shoulders", equipment: "resistance_band", location: ["gym", "home", "none"], difficulty: "beginner", sets: 2, reps: "15", rest_seconds: 30, tempo: "2-1-2-0", gif: gifUrl("Band Pull Apart Posture"), instructions: ["Squeeze shoulder blades, pull shoulders back"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 2 },
{ name: "Hip Flexor Stretch (Desk)", name_tr: "Kalca Fleksor Germe", muscle_group: "flexibility", equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 2, reps: "30 seconds each side", rest_seconds: 0, tempo: "slow", gif: gifUrl("Hip Flexor Stretch"), instructions: ["Open hip flexors shortened from sitting"], contraindicated_injuries: ["hip", "knee"], contraindicated_conditions: [], calories_per_set: 1 },
{ name: "Chin Tuck", name_tr: "Cene Cekme", muscle_group: "flexibility", equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 2, reps: "15", rest_seconds: 15, tempo: "slow", gif: gifUrl("Chin Tuck"), instructions: ["Correct forward head posture, retract chin"], contraindicated_injuries: [], contraindicated_conditions: [], calories_per_set: 1 },
{ name: "Cat-Cow (Spinal Mobility)", name_tr: "Kedi-Inek", muscle_group: "flexibility", equipment: "bodyweight", location: ["gym", "home", "none"], difficulty: "beginner", sets: 2, reps: "10", rest_seconds: 0, tempo: "slow", gif: gifUrl("Cat-Cow"), instructions: ["Spine mobility, sync with breathing"], contraindicated_injuries: ["wrist"], contraindicated_conditions: [], calories_per_set: 2 },
];
// ─────────────────────────────────────────────────────────────────────────────
// Light activity plans for workout_location: "none"
// ─────────────────────────────────────────────────────────────────────────────
const LIGHT_ACTIVITY_PLANS = {
standard: [
{ day: 1, name: "Day 1 - Walking & Breathing", type: "light_activity", focus: "Cardiovascular & Stress Relief", estimated_duration: 30, estimated_calories: 80, activities: [
{ name: "Brisk Walking", name_tr: "Tempolu Yuruyus", duration: "20 minutes", gif: gifUrl("Brisk Walking"), instructions: ["Walk at comfortable but brisk pace", "Swing arms naturally", "Breathe rhythmically"], notes: "Target 3000-4000 steps" },
{ name: "Diaphragmatic Breathing", name_tr: "Diyafram Nefesi", duration: "5 minutes", gif: gifUrl("Diaphragmatic Breathing"), instructions: ["Sit or lie comfortably", "Breathe in through nose 4 seconds", "Hold 4 seconds", "Exhale through mouth 6 seconds"], notes: "Stress relief and relaxation" },
{ name: "Gentle Full Body Stretch", name_tr: "Hafif Tum Vucut Germe", duration: "5 minutes", gif: gifUrl("Gentle Full Body Stretch"), instructions: ["Stretch neck, shoulders, arms, back, legs", "Hold each stretch 15-20 seconds", "No bouncing"], notes: "Improve flexibility" },
] },
{ day: 2, name: "Day 2 - Mobility & Stretching", type: "light_activity", focus: "Flexibility & Joint Health", estimated_duration: 25, estimated_calories: 50, activities: [
{ name: "Joint Circles", name_tr: "Eklem Civirleri", duration: "5 minutes", gif: gifUrl("Joint Circles"), instructions: ["Circle ankles, knees, hips, shoulders, wrists", "10 circles each direction", "Gentle and controlled"], notes: "Warm up all joints" },
{ name: "Yoga-Inspired Stretching", name_tr: "Yoga Tarzinda Germe", duration: "15 minutes", gif: gifUrl("Yoga Stretching"), instructions: ["Cat-cow stretch", "Child's pose", "Downward dog or modified version", "Seated forward fold", "Gentle twist"], notes: "Focus on breathing and relaxation" },
{ name: "Box Breathing", name_tr: "Kutu Nefesi", duration: "5 minutes", gif: gifUrl("Box Breathing"), instructions: ["Breathe in 4 seconds", "Hold 4 seconds", "Breathe out 4 seconds", "Hold 4 seconds"], notes: "Calming technique" },
] },
{ day: 3, name: "Day 3 - Light Walk & Core", type: "light_activity", focus: "Walking & Core Stability", estimated_duration: 30, estimated_calories: 70, activities: [
{ name: "Outdoor or Indoor Walking", name_tr: "Yuruyus", duration: "15 minutes", gif: gifUrl("Walking"), instructions: ["Moderate pace", "Focus on posture", "Keep shoulders back"], notes: "Target 2000-3000 steps" },
{ name: "Gentle Core Work", name_tr: "Hafif Core Calismasi", duration: "10 minutes", gif: gifUrl("Gentle Core Work"), instructions: ["Dead bugs 10 each side", "Bird dog 10 each side", "Gentle pelvic tilts 15 reps", "Modified plank 15-20 seconds"], notes: "Low intensity core activation" },
{ name: "Progressive Muscle Relaxation", name_tr: "Kademeli Kas Gevsetme", duration: "5 minutes", gif: gifUrl("Progressive Muscle Relaxation"), instructions: ["Tense each muscle group 5 seconds", "Release and relax 10 seconds", "Work from toes to head"], notes: "Stress and tension relief" },
] },
{ day: 4, name: "Day 4 - Rest & Breathing", type: "light_activity", focus: "Recovery & Mental Wellness", estimated_duration: 20, estimated_calories: 30, activities: [
{ name: "Gentle Walking", name_tr: "Hafif Yuruyus", duration: "10 minutes", gif: gifUrl("Gentle Walking"), instructions: ["Very easy pace", "Focus on environment", "Practice mindful walking"], notes: "Light movement only" },
{ name: "4-7-8 Breathing", name_tr: "4-7-8 Nefes", duration: "5 minutes", gif: gifUrl("4-7-8 Breathing"), instructions: ["Inhale through nose 4 seconds", "Hold breath 7 seconds", "Exhale through mouth 8 seconds", "Repeat 4-8 cycles"], notes: "Promotes relaxation and sleep quality" },
{ name: "Gentle Neck & Shoulder Release", name_tr: "Boyun ve Omuz Gevsetme", duration: "5 minutes", gif: gifUrl("Neck Shoulder Release"), instructions: ["Neck tilts each direction", "Shoulder rolls forward and back", "Shoulder shrugs and release"], notes: "Release common tension areas" },
] },
{ day: 5, name: "Day 5 - Walking & Flexibility", type: "light_activity", focus: "Cardiovascular & Stretching", estimated_duration: 30, estimated_calories: 75, activities: [
{ name: "Brisk Walking", name_tr: "Tempolu Yuruyus", duration: "20 minutes", gif: gifUrl("Brisk Walking"), instructions: ["Moderate to brisk pace", "Include some hills or inclines if possible", "Maintain good posture"], notes: "Target 3000-4000 steps" },
{ name: "Standing Stretches", name_tr: "Ayakta Germe", duration: "10 minutes", gif: gifUrl("Standing Stretches"), instructions: ["Calf stretch against wall", "Quad stretch holding chair", "Hamstring stretch on step", "Side bend stretch", "Chest opener stretch"], notes: "Focus on areas that feel tight" },
] },
{ day: 6, name: "Day 6 - Mobility & Balance", type: "light_activity", focus: "Balance & Joint Mobility", estimated_duration: 25, estimated_calories: 50, activities: [
{ name: "Balance Exercises", name_tr: "Denge Egzersizleri", duration: "10 minutes", gif: gifUrl("Balance Exercises"), instructions: ["Single leg stand 30 seconds each", "Heel-to-toe walk", "Standing weight shifts", "Tandem stance"], notes: "Improve stability and proprioception" },
{ name: "Seated Mobility Flow", name_tr: "Oturarak Mobilite", duration: "10 minutes", gif: gifUrl("Seated Mobility Flow"), instructions: ["Seated spinal twist", "Seated hip circles", "Ankle circles", "Wrist circles", "Shoulder rolls"], notes: "Full body joint mobility from chair" },
{ name: "Deep Breathing Cool-Down", name_tr: "Derin Nefes Soguma", duration: "5 minutes", gif: gifUrl("Deep Breathing"), instructions: ["Belly breathing", "Long slow exhales", "Close eyes if comfortable"], notes: "End with relaxation" },
] },
{ day: 7, name: "Day 7 - Rest & Recovery", type: "light_activity", focus: "Complete Rest & Self-Care", estimated_duration: 15, estimated_calories: 20, activities: [
{ name: "Gentle Walk", name_tr: "Hafif Yuruyus", duration: "10 minutes", gif: gifUrl("Gentle Walk"), instructions: ["Very easy pace", "Enjoy the environment", "No intensity targets"], notes: "Optional - only if you feel up to it" },
{ name: "Body Scan Meditation", name_tr: "Vucut Tarama Meditasyonu", duration: "5 minutes", gif: gifUrl("Body Scan Meditation"), instructions: ["Lie down or sit comfortably", "Mentally scan from toes to head", "Notice sensations without judgment", "Breathe into any tense areas"], notes: "Mindfulness and recovery" },
] },
],
wheelchair: [
{ day: 1, name: "Day 1 - Upper Body Seated", type: "light_activity", focus: "Seated Upper Body Movement", estimated_duration: 25, estimated_calories: 50, activities: [
{ name: "Seated Arm Circles", name_tr: "Oturarak Kol Civirme", duration: "5 minutes", gif: gifUrl("Seated Arm Circles"), instructions: ["Small circles forward 20 reps", "Small circles backward 20 reps", "Large circles forward 10 reps", "Large circles backward 10 reps"], notes: "Warm up shoulders" },
{ name: "Seated Chest Press Motion", name_tr: "Oturarak Gogus Press", duration: "10 minutes", gif: gifUrl("Seated Chest Press Motion"), instructions: ["Push hands forward from chest", "Light resistance band if available", "15-20 reps, 2-3 sets", "Rest 30 seconds between sets"], notes: "Upper body strengthening" },
{ name: "Seated Deep Breathing", name_tr: "Oturarak Derin Nefes", duration: "5 minutes", gif: gifUrl("Seated Deep Breathing"), instructions: ["Sit tall", "Breathe deeply into belly", "Exhale slowly", "Focus on posture"], notes: "Respiratory health" },
{ name: "Upper Body Stretch", name_tr: "Ust Vucut Germe", duration: "5 minutes", gif: gifUrl("Upper Body Stretch"), instructions: ["Overhead reach", "Cross-body shoulder stretch", "Triceps stretch", "Chest opener"], notes: "Flexibility maintenance" },
] },
{ day: 2, name: "Day 2 - Breathing & Mobility", type: "light_activity", focus: "Respiratory & Joint Health", estimated_duration: 20, estimated_calories: 30, activities: [
{ name: "Breathing Exercises", name_tr: "Nefes Egzersizleri", duration: "10 minutes", gif: gifUrl("Breathing Exercises"), instructions: ["Pursed lip breathing 2 min", "Diaphragmatic breathing 3 min", "Box breathing 5 min"], notes: "Lung capacity and relaxation" },
{ name: "Seated Joint Mobility", name_tr: "Oturarak Eklem Mobilitesi", duration: "10 minutes", gif: gifUrl("Seated Joint Mobility"), instructions: ["Wrist circles", "Elbow flexion/extension", "Shoulder rolls", "Neck rotations", "Trunk rotations"], notes: "Maintain joint range of motion" },
] },
{ day: 3, name: "Day 3 - Light Resistance", type: "light_activity", focus: "Seated Resistance Training", estimated_duration: 25, estimated_calories: 45, activities: [
{ name: "Seated Band Rows", name_tr: "Oturarak Bantli Row", duration: "8 minutes", gif: gifUrl("Seated Band Rows"), instructions: ["Anchor band at chest height", "Pull toward torso", "Squeeze shoulder blades", "12-15 reps, 2 sets"], notes: "Back strengthening" },
{ name: "Seated Band Press", name_tr: "Oturarak Bantli Press", duration: "8 minutes", gif: gifUrl("Seated Band Press"), instructions: ["Band behind back", "Press forward", "12-15 reps, 2 sets"], notes: "Chest and arm strengthening" },
{ name: "Seated Core Activation", name_tr: "Oturarak Core Aktivasyonu", duration: "5 minutes", gif: gifUrl("Seated Core Activation"), instructions: ["Seated pelvic tilts", "Seated trunk rotation", "Seated side bends"], notes: "Core stability" },
{ name: "Cool-Down Stretching", name_tr: "Soguma Germe", duration: "4 minutes", gif: gifUrl("Seated Stretching"), instructions: ["Stretch all worked muscle groups", "Hold 20-30 seconds each"], notes: "Recovery" },
] },
{ day: 4, name: "Day 4 - Rest & Recovery", type: "light_activity", focus: "Mental Wellness", estimated_duration: 15, estimated_calories: 15, activities: [
{ name: "Guided Breathing", name_tr: "Rehberli Nefes", duration: "10 minutes", gif: gifUrl("Guided Breathing"), instructions: ["Follow 4-7-8 pattern", "Focus on complete relaxation"], notes: "Stress management" },
{ name: "Gentle Stretching", name_tr: "Hafif Germe", duration: "5 minutes", gif: gifUrl("Gentle Stretching"), instructions: ["Only stretch what feels comfortable", "No pushing into pain"], notes: "Light recovery" },
] },
{ day: 5, name: "Day 5 - Seated Cardio", type: "light_activity", focus: "Cardiovascular Health", estimated_duration: 25, estimated_calories: 55, activities: [
{ name: "Seated Arm Ergometer / Air Punches", name_tr: "Oturarak Kol Kardiyosu", duration: "15 minutes", gif: gifUrl("Seated Arm Cardio"), instructions: ["Alternating arm punches", "Arm cranking motion", "Overhead reaches", "Keep moderate pace"], notes: "Elevate heart rate safely" },
{ name: "Seated Torso Twists", name_tr: "Oturarak Govde Dondurmesi", duration: "5 minutes", gif: gifUrl("Seated Torso Twists"), instructions: ["Rotate torso left and right", "Arms at chest level", "Controlled movement"], notes: "Core engagement" },
{ name: "Cool-Down", name_tr: "Soguma", duration: "5 minutes", gif: gifUrl("Seated Cool Down"), instructions: ["Slow arm movements", "Deep breathing", "Gentle stretching"], notes: "Gradual recovery" },
] },
{ day: 6, name: "Day 6 - Flexibility Focus", type: "light_activity", focus: "Stretching & Relaxation", estimated_duration: 20, estimated_calories: 25, activities: [
{ name: "Comprehensive Seated Stretch", name_tr: "Kapsamli Oturarak Germe", duration: "15 minutes", gif: gifUrl("Comprehensive Seated Stretch"), instructions: ["Neck stretches all directions", "Shoulder stretches", "Chest opener", "Trunk side bends", "Wrist stretches", "Hip flexor stretch if possible"], notes: "Full body flexibility" },
{ name: "Meditation", name_tr: "Meditasyon", duration: "5 minutes", gif: gifUrl("Seated Meditation"), instructions: ["Close eyes", "Focus on breathing", "Let thoughts pass without engagement"], notes: "Mental wellness" },
] },
{ day: 7, name: "Day 7 - Complete Rest", type: "light_activity", focus: "Full Recovery", estimated_duration: 10, estimated_calories: 10, activities: [
{ name: "Optional Light Movement", name_tr: "Istege Bagli Hafif Hareket", duration: "5 minutes", gif: gifUrl("Optional Light Movement"), instructions: ["Only if you feel like it", "Gentle arm swings", "Shoulder rolls"], notes: "Completely optional" },
{ name: "Relaxation Breathing", name_tr: "Rahatlama Nefesi", duration: "5 minutes", gif: gifUrl("Relaxation Breathing"), instructions: ["Long slow breaths", "Focus on letting go of tension"], notes: "End the week relaxed" },
] },
],
limited_both: [
{ day: 1, name: "Day 1 - Gentle Mobility", type: "light_activity", focus: "Gentle Movement", estimated_duration: 15, estimated_calories: 20, activities: [
{ name: "Seated Breathing Exercise", name_tr: "Oturarak Nefes", duration: "5 minutes", gif: gifUrl("Seated Breathing"), instructions: ["Deep belly breaths", "Slow and rhythmic"], notes: "Foundation exercise" },
{ name: "Gentle Range of Motion", name_tr: "Hafif Hareket Acikligi", duration: "10 minutes", gif: gifUrl("Gentle ROM"), instructions: ["Move whatever joints feel comfortable", "Very gentle circles and movements", "Stop if any discomfort"], notes: "Maintain what mobility you have" },
] },
{ day: 2, name: "Day 2 - Breathing Focus", type: "light_activity", focus: "Respiratory Health", estimated_duration: 15, estimated_calories: 15, activities: [
{ name: "Progressive Breathing", name_tr: "Kademeli Nefes", duration: "10 minutes", gif: gifUrl("Progressive Breathing"), instructions: ["Start with normal breaths", "Gradually deepen inhales", "Gradually lengthen exhales", "4-7-8 pattern if comfortable"], notes: "Improve lung capacity" },
{ name: "Body Awareness Scan", name_tr: "Vucut Farkindalik", duration: "5 minutes", gif: gifUrl("Body Awareness"), instructions: ["Notice each body part", "Release tension where found", "Accept current state"], notes: "Mind-body connection" },
] },
{ day: 3, name: "Day 3 - Light Stretch", type: "light_activity", focus: "Gentle Flexibility", estimated_duration: 15, estimated_calories: 15, activities: [
{ name: "Supported Stretching", name_tr: "Destekli Germe", duration: "10 minutes", gif: gifUrl("Supported Stretching"), instructions: ["Use pillows or supports as needed", "Very gentle holds 10-15 seconds", "Focus on comfortable range only"], notes: "Gentle flexibility work" },
{ name: "Relaxation", name_tr: "Rahatlama", duration: "5 minutes", gif: gifUrl("Relaxation"), instructions: ["Close eyes", "Deep breathing", "Progressive muscle relaxation where possible"], notes: "Recovery" },
] },
{ day: 4, name: "Day 4 - Rest", type: "light_activity", focus: "Complete Rest", estimated_duration: 10, estimated_calories: 10, activities: [
{ name: "Breathing Only", name_tr: "Sadece Nefes", duration: "10 minutes", gif: gifUrl("Breathing Only"), instructions: ["Comfortable position", "Gentle natural breathing", "Mindfulness focus"], notes: "Active rest through breathing" },
] },
{ day: 5, name: "Day 5 - Gentle Mobility", type: "light_activity", focus: "Joint Care", estimated_duration: 15, estimated_calories: 20, activities: [
{ name: "Assisted Range of Motion", name_tr: "Yardimli Hareket Acikligi", duration: "10 minutes", gif: gifUrl("Assisted ROM"), instructions: ["Use one limb to help the other if needed", "Gentle passive stretching", "Stay within comfort zone"], notes: "Maintain joint health" },
{ name: "Visualization Exercise", name_tr: "Gorsellestirme", duration: "5 minutes", gif: gifUrl("Visualization"), instructions: ["Imagine performing movements", "Mental rehearsal activates neural pathways", "Relaxing and beneficial"], notes: "Mind-body exercise" },
] },
{ day: 6, name: "Day 6 - Breathing & Relaxation", type: "light_activity", focus: "Stress Relief", estimated_duration: 15, estimated_calories: 10, activities: [
{ name: "Extended Breathing Session", name_tr: "Uzun Nefes Seansi", duration: "10 minutes", gif: gifUrl("Extended Breathing"), instructions: ["Alternate nostril breathing", "Box breathing", "4-7-8 breathing"], notes: "Multiple techniques" },
{ name: "Gentle Self-Massage", name_tr: "Hafif Masaj", duration: "5 minutes", gif: gifUrl("Self Massage"), instructions: ["Gently massage accessible areas", "Focus on hands, arms, neck", "Use gentle circular motions"], notes: "Relaxation and circulation" },
] },
{ day: 7, name: "Day 7 - Full Rest", type: "light_activity", focus: "Recovery", estimated_duration: 5, estimated_calories: 5, activities: [
{ name: "Mindful Rest", name_tr: "Bilinc Dinlenmesi", duration: "5 minutes", gif: gifUrl("Mindful Rest"), instructions: ["Simply rest", "Breathe naturally", "Be present"], notes: "Complete rest day" },
] },
],
};
// ─────────────────────────────────────────────────────────────────────────────
// Helper functions
// ─────────────────────────────────────────────────────────────────────────────
function pickRandom(arr, count) {
const shuffled = [...arr].sort(() => 0.5 - Math.random());
return shuffled.slice(0, Math.min(count, arr.length));
}
function hasGoal(profile, goalValue) {
const goal = profile.goal || "maintain";
return goal.split(",").map((s) => s.trim()).includes(goalValue);
}
function filterByInjury(exercises, injuryArea) {
if (!injuryArea || injuryArea === "none") return exercises;
const areas = String(injuryArea).split(",").map((s) => s.trim()).filter((s) => s && s !== "none");
if (areas.length === 0) return exercises;
return exercises.filter((e) => !areas.some((area) => e.contraindicated_injuries.includes(area)));
}
function filterByConditions(exercises, profile) {
const conditions = [];
if (profile.heart_condition) conditions.push("heart_condition");
if (profile.blood_pressure === "high" || profile.high_blood_pressure) conditions.push("high_blood_pressure");
if (profile.has_asthma) conditions.push("has_asthma");
if (profile.has_epilepsy) conditions.push("has_epilepsy");
if (profile.has_arthritis) conditions.push("has_arthritis");
if (profile.has_osteoporosis) conditions.push("has_osteoporosis");
if (profile.has_fibromyalgia) conditions.push("has_fibromyalgia");
if (profile.has_diabetes) conditions.push("has_diabetes");
if (conditions.length === 0) return exercises;
return exercises.filter((e) => {
const contra = e.contraindicated_conditions || [];
return !contra.some((c) => conditions.includes(c));
});
}
function filterByLocation(exercises, location) {
if (!location || location === "gym") return exercises;
return exercises.filter((e) => e.location && e.location.includes(location));
}
function filterByDifficulty(exercises, experience) {
if (experience === "beginner") {
return exercises.filter((e) => e.difficulty !== "advanced");
}
return exercises;
}
function filterByEquipment(exercises, profile) {
const location = profile.workout_location || "gym";
if (location === "gym") return exercises;
if (location === "home") {
const availableEquipment = new Set(["bodyweight", "none"]);
if (profile.has_equipment !== false) {
const equip = profile.available_equipment || ["dumbbell", "resistance_band", "pull_up_bar", "yoga_mat"];
equip.forEach((e) => availableEquipment.add(e.replace("_", " ").replace("pull up bar", "bodyweight")));
if (equip.includes("dumbbell") || equip.includes("dumbbells")) availableEquipment.add("dumbbell");
if (equip.includes("resistance_band") || equip.includes("resistance_bands") || equip.includes("band")) availableEquipment.add("resistance_band");
if (equip.includes("kettlebell") || equip.includes("kettlebells")) availableEquipment.add("kettlebell");
}
return exercises.filter((e) => availableEquipment.has(e.equipment) || e.equipment === "bodyweight" || e.equipment === "none");
}
// location "none" - bodyweight and no-equipment only
return exercises.filter((e) => e.equipment === "bodyweight" || e.equipment === "none" || e.equipment === "resistance_band");
}
function filterByDisability(exercises, profile) {
if (!profile.has_disability) return exercises;
const mobilityLevel = profile.mobility_level || "full";
const disabilityType = profile.disability_type || "";
if (profile.uses_wheelchair || mobilityLevel === "limited_lower" || disabilityType === "lower_body") {
// Upper body only - remove all leg, glute, and lower-body-dependent exercises
return exercises.filter((e) => {
const lowerGroups = ["legs", "glutes", "cardio"];
if (lowerGroups.includes(e.muscle_group)) return false;
// Also filter out exercises requiring standing/legs
if (e.equipment === "bodyweight" && ["hiit"].includes(e.muscle_group)) return false;
return true;
});
}
if (mobilityLevel === "limited_upper" || disabilityType === "upper_body") {
// Lower body + cardio focus
return exercises.filter((e) => {
const upperGroups = ["chest", "back", "shoulders", "arms_biceps", "arms_triceps"];
return !upperGroups.includes(e.muscle_group);
});
}
if (mobilityLevel === "limited_both") {
// Only gentle movements - will use light activity plan
return exercises.filter((e) => e.muscle_group === "flexibility" || e.muscle_group === "core");
}
return exercises;
}
function adjustForAge(exercises, age) {
if (age > 55) {
return exercises.map((e) => ({
...e,
sets: Math.max(2, e.sets - 1),
}));
}
return exercises;
}
function applyWeekProgression(exercises, week) {
const config = MESOCYCLE[week] || MESOCYCLE[1];
return exercises.map((e) => {
const modified = { ...e };
if (config.volume_multiplier < 1) {
modified.sets = Math.max(1, Math.round(e.sets * config.volume_multiplier));
}
return modified;
});
}
function adjustForRecovery(exercises, profile) {
const sleepHours = profile.sleep_hours || 7;
const stressLevel = profile.stress_level || "medium";
let volumeReduction = 1.0;
if (sleepHours < 6) volumeReduction *= 0.8;
if (stressLevel === "high") volumeReduction *= 0.85;
if (volumeReduction < 1.0) {
return exercises.map((e) => ({
...e,
sets: Math.max(1, Math.round(e.sets * volumeReduction)),
}));
}
return exercises;
}
function adjustForSevereInjury(exercises) {
return exercises.map((e) => ({
...e,
sets: Math.max(1, Math.round(e.sets * 0.6)),
rest_seconds: Math.round(e.rest_seconds * 1.3),
}));
}
function adjustForModerateInjury(exercises) {
return exercises.map((e) => ({
...e,
sets: Math.max(1, Math.round(e.sets * 0.85)),
}));
}
function adjustForConditions(exercises, profile) {
let modified = [...exercises];
// Fibromyalgia: reduce intensity significantly
if (profile.has_fibromyalgia) {
modified = modified.map((e) => ({
...e,
sets: Math.max(1, Math.round(e.sets * 0.7)),
rest_seconds: Math.round(e.rest_seconds * 1.5),
}));
}
// Arthritis: favor lower reps range and more rest
if (profile.has_arthritis) {
modified = modified.map((e) => ({
...e,
rest_seconds: Math.round(e.rest_seconds * 1.2),
}));
}
// Osteoporosis: reduce sets slightly
if (profile.has_osteoporosis) {
modified = modified.map((e) => ({
...e,
sets: Math.max(1, Math.round(e.sets * 0.85)),
}));
}
return modified;
}
function processExercises(exercises, profile, week) {
const injuryArea = profile.has_injury ? (profile.injury_area || "none") : "none";
const injurySeverity = profile.has_injury ? (profile.injury_severity || "mild") : "mild";
let processed = filterByInjury(exercises, injuryArea);
processed = filterByConditions(processed, profile);
processed = filterByLocation(processed, profile.workout_location || "gym");
processed = filterByEquipment(processed, profile);
processed = filterByDisability(processed, profile);
processed = filterByDifficulty(processed, profile.workout_experience || "beginner");
processed = adjustForAge(processed, profile.age || 30);
processed = applyWeekProgression(processed, week);
processed = adjustForRecovery(processed, profile);
processed = adjustForConditions(processed, profile);
if (profile.has_injury && injurySeverity === "severe") {
processed = adjustForSevereInjury(processed);
} else if (profile.has_injury && injurySeverity === "moderate") {
processed = adjustForModerateInjury(processed);
}
return processed;
}
function getAlternativeExercises(injuryArea, count) {
if (!injuryArea || injuryArea === "none") return [];
const alternatives = INJURY_ALTERNATIVES[injuryArea] || [];
return pickRandom(alternatives, count);
}
// ─────────────────────────────────────────────────────────────────────────────
// Warmup / Cooldown builders
// ─────────────────────────────────────────────────────────────────────────────
function buildWarmupRoutine(profile) {
const injuryArea = profile.has_injury ? (profile.injury_area || "none") : "none";
const warmup = [
{ name: "General Warm-Up (Light Cardio)", duration: "5 min", notes: "Treadmill, bike, or jumping jacks to raise heart rate" },
{ name: "Dynamic Stretching", duration: "3 min", notes: "Arm circles, leg swings, torso rotations" },
];
if (profile.has_asthma) {
warmup[0].notes += " - Extend to 8-10 min for asthma; gradual intensity increase is important";
}
if (profile.has_diabetes) {
warmup.push({ name: "Blood Sugar Check", duration: "1 min", notes: "Check blood sugar before exercise. Ensure it is between 100-250 mg/dL" });
}
if (injuryArea !== "none" && INJURY_WARMUPS[injuryArea]) {
INJURY_WARMUPS[injuryArea].forEach((w) => warmup.push(w));
}
const jobType = profile.job_type || "";
if (jobType === "desk" || jobType === "office" || jobType === "masa_basi") {
warmup.push({ name: "Posture Correction Mobility", duration: "3 min", notes: "Shoulder and hip opening for desk workers" });
}
return warmup;
}
function buildCooldown(profile) {
const injuryArea = profile.has_injury ? (profile.injury_area || "none") : "none";
const cooldown = [
{ name: "General Stretching", duration: "5 min", notes: "Stretch all worked muscle groups" },
];
if (injuryArea !== "none") {
const areaName = injuryArea.charAt(0).toUpperCase() + injuryArea.slice(1);
cooldown.push({ name: `${areaName} Area Specific Stretching`, duration: "3 min", notes: "Targeted stretching for injury area" });
}
if (profile.has_diabetes) {
cooldown.push({ name: "Post-Exercise Blood Sugar Check", duration: "1 min", notes: "Monitor blood sugar after exercise" });
}
cooldown.push({ name: "Deep Breathing & Relaxation", duration: "2 min", notes: "Breathe in 4 seconds, hold 4 seconds, breathe out 4 seconds" });
return cooldown;
}
// ─────────────────────────────────────────────────────────────────────────────
// Notes & Tips builders
// ─────────────────────────────────────────────────────────────────────────────
function buildGeneralTips(profile) {
const tips = [
"Warm up 5-10 minutes before every workout",
"Cool down and stretch 5-10 minutes after every workout",
"Drink at least 2-3 liters of water daily",
"Prioritize sleep (7-9 hours per night)",
"Stop any exercise immediately if you feel pain",
"Take at least 1 full rest day per week",
];
const experience = profile.workout_experience || "beginner";
if (experience === "beginner") {
tips.push("Beginner level: Prioritize form and technique over weight. Increase weights gradually.");
} else if (experience === "advanced") {
tips.push("Advanced level: Apply progressive overload. Consider super-sets and drop-sets for intensity.");
}
const bodyType = profile.body_type || "mesomorph";
if (bodyType === "ectomorph") {
tips.push("Ectomorph body type: Focus on compound movements, limit excess cardio, maintain calorie surplus.");
} else if (bodyType === "endomorph") {
tips.push("Endomorph body type: Add post-workout cardio, watch portion sizes, prefer HIIT cardio.");
}
if ((profile.sleep_hours || 7) < 6) {
tips.push("Your sleep is insufficient: Avoid overtraining, prioritize recovery.");
}
if (profile.stress_level === "high") {
tips.push("High stress level: Add meditation and breathing exercises. Training volume has been reduced.");
}
const jobType = profile.job_type || "";
if (jobType === "desk" || jobType === "office" || jobType === "masa_basi") {
tips.push("Desk worker: Stand up and move every hour. Include posture correction exercises.");
}
return tips;
}
function buildMedicalNotes(profile) {
const notes = [];
if (profile.heart_condition) {
notes.push("Heart condition: Low intensity only. No HIIT. Monitor heart rate and stay in safe zones (50-65% max HR). Stop if dizzy or chest pain.");
}
if (profile.blood_pressure === "high" || profile.high_blood_pressure) {
notes.push("High blood pressure: No heavy lifting or breath holding (Valsalva). Avoid overhead pressing. Keep intensity moderate. Monitor blood pressure regularly.");
}
if (profile.has_asthma) {
notes.push("Asthma: Extended warm-up is important. Keep inhaler nearby. Avoid cold environments. Moderate cardio intensity.");
}
if (profile.has_diabetes) {
notes.push("Diabetes: Check blood sugar before and after exercise. Include warm-up and cool-down. Avoid fasted training. Carry fast-acting sugar.");
}
if (profile.has_arthritis) {
notes.push("Arthritis: Low impact exercises only. Joint-friendly movements. Consider swimming/water exercises if available. Longer warm-ups help.");
}
if (profile.has_osteoporosis) {
notes.push("Osteoporosis: Weight-bearing exercises are beneficial but avoid high impact. No trunk flexion exercises. Focus on balance to prevent falls.");
}
if (profile.has_fibromyalgia) {
notes.push("Fibromyalgia: Gentle, low-intensity exercises only. Focus on stretching and yoga-based movements. Listen to your body. Volume has been reduced.");
}
if (profile.has_epilepsy) {
notes.push("Epilepsy: Avoid exercises where falling could be dangerous (no heavy overhead lifts, no climbing). Train with a partner when possible.");
}
return notes;
}
function buildInjuryNote(profile) {
if (!profile.has_injury || !profile.injury_area || profile.injury_area === "none") return null;
const areaNames = {
knee: "Knee", back: "Back/Lower Back", shoulder: "Shoulder", elbow: "Elbow",
wrist: "Wrist", ankle: "Ankle", hip: "Hip", neck: "Neck",
};
const severityNames = {
mild: "mild", moderate: "moderate", severe: "severe",
};
const areas = String(profile.injury_area).split(",").map((s) => s.trim()).filter((s) => s && s !== "none");
const areaName = areas.map((a) => areaNames[a] || a).join(", ");
const severityName = severityNames[profile.injury_severity] || "mild";
let note = `Program adapted for ${severityName} ${areaName} injury.`;
if (profile.injury_notes) {
note += ` Note: ${profile.injury_notes}`;
}
if (profile.injury_severity === "severe") {
note += " Intensity significantly reduced due to severe injury. Do not train heavy without doctor approval.";
} else if (profile.injury_severity === "moderate") {
note += " Exercise with caution and control. Stop if pain increases.";
}
return note;
}
// ─────────────────────────────────────────────────────────────────────────────
// Exercise formatting for output
// ─────────────────────────────────────────────────────────────────────────────
function formatExercise(e) {
return {
name: e.name,
name_tr: e.name_tr || e.name,
muscle_group: e.muscle_group,
equipment: e.equipment,
sets: e.sets,
reps: e.reps,
rest_seconds: e.rest_seconds,
tempo: e.tempo,
gif: e.gif || gifUrl(e.name),
instructions: e.instructions || [],
alternatives: e.alternatives || [],
calories_per_set: e.calories_per_set || 5,
};
}
function estimateDayCalories(exercises) {
return exercises.reduce((total, e) => total + ((e.calories_per_set || 5) * (e.sets || 3)), 0);
}
function estimateDayDuration(exercises) {
// Rough estimate: each set ~1.5 min (including rest), plus warmup (10 min) and cooldown (7 min)
const setTime = exercises.reduce((total, e) => {
const sets = e.sets || 3;
const restMin = (e.rest_seconds || 60) / 60;
return total + sets * (0.75 + restMin);
}, 0);
return Math.round(17 + setTime); // 10 warmup + 7 cooldown + exercise time
}
// ─────────────────────────────────────────────────────────────────────────────
// Day builders
// ─────────────────────────────────────────────────────────────────────────────
function getPoolForGroup(group) {
return EXERCISES[group] || [];
}
function buildStrengthDay(dayNumber, dayName, focus, muscleGroups, profile, week, exerciseCountPerGroup) {
let exercises = [];
const injuryArea = profile.has_injury ? (profile.injury_area || "none") : "none";
const location = profile.workout_location || "gym";
for (const group of muscleGroups) {
let pool = getPoolForGroup(group);
pool = filterByInjury(pool, injuryArea);
pool = filterByConditions(pool, profile);
pool = filterByLocation(pool, location);
pool = filterByEquipment(pool, profile);
pool = filterByDisability(pool, profile);
pool = filterByDifficulty(pool, profile.workout_experience || "beginner");
const count = exerciseCountPerGroup[group] || 3;
const picked = pickRandom(pool, count);
exercises = exercises.concat(picked);
}
// Add alternatives if injury removed too many exercises
if (profile.has_injury && injuryArea !== "none") {
const totalExpected = Object.values(exerciseCountPerGroup).reduce((a, b) => a + b, 0);
if (exercises.length < totalExpected * 0.6) {
const alts = getAlternativeExercises(injuryArea, totalExpected - exercises.length);
const filteredAlts = filterByLocation(filterByEquipment(alts, profile), location);
exercises = exercises.concat(filteredAlts);
}
}
// Add desk mobility if applicable
const jobType = profile.job_type || "";
if (jobType === "desk" || jobType === "office" || jobType === "masa_basi") {
const mobility = pickRandom(DESK_MOBILITY.filter((e) => !e.contraindicated_injuries.includes(injuryArea)), 1);
exercises = exercises.concat(mobility);
}
exercises = adjustForAge(exercises, profile.age || 30);
exercises = applyWeekProgression(exercises, week);
exercises = adjustForRecovery(exercises, profile);
exercises = adjustForConditions(exercises, profile);
const injurySeverity = profile.has_injury ? (profile.injury_severity || "mild") : "mild";
if (profile.has_injury && injurySeverity === "severe") {
exercises = adjustForSevereInjury(exercises);
} else if (profile.has_injury && injurySeverity === "moderate") {
exercises = adjustForModerateInjury(exercises);
}
const formattedExercises = exercises.map(formatExercise);
return {
day: dayNumber,
name: `Day ${dayNumber} - ${dayName}`,
type: "strength",
focus: focus,
estimated_duration: estimateDayDuration(exercises),
estimated_calories: estimateDayCalories(exercises),
warmup: buildWarmupRoutine(profile),
exercises: formattedExercises,
cooldown: buildCooldown(profile),
notes: [],
};
}
function buildCardioDay(dayNumber, dayName, focus, profile, week) {
const injuryArea = profile.has_injury ? (profile.injury_area || "none") : "none";
const location = profile.workout_location || "gym";
const bodyType = profile.body_type || "mesomorph";
let exercises = [];
if ((bodyType === "endomorph" || hasGoal(profile, "lose_weight")) && !profile.heart_condition) {
const safeHiit = filterByLocation(filterByEquipment(filterByConditions(filterByInjury(EXERCISES.hiit, injuryArea), profile), profile), location);
const safeCardio = filterByLocation(filterByEquipment(filterByConditions(filterByInjury(EXERCISES.cardio, injuryArea), profile), profile), location);
exercises = [...pickRandom(safeHiit, 4), ...pickRandom(safeCardio, 1)];
} else {
const safeCardio = filterByLocation(filterByEquipment(filterByConditions(filterByInjury(EXERCISES.cardio, injuryArea), profile), profile), location);
exercises = pickRandom(safeCardio, 3);
}
const safeCore = filterByLocation(filterByEquipment(filterByConditions(filterByInjury(EXERCISES.core, injuryArea), profile), profile), location);
exercises = exercises.concat(pickRandom(safeCore, 3));
exercises = adjustForAge(exercises, profile.age || 30);
exercises = applyWeekProgression(exercises, week);
exercises = adjustForRecovery(exercises, profile);
exercises = adjustForConditions(exercises, profile);
const formattedExercises = exercises.map(formatExercise);
return {
day: dayNumber,
name: `Day ${dayNumber} - ${dayName}`,
type: "cardio",
focus: focus,
estimated_duration: estimateDayDuration(exercises),
estimated_calories: estimateDayCalories(exercises),
warmup: buildWarmupRoutine(profile),
exercises: formattedExercises,
cooldown: buildCooldown(profile),
notes: [],
};
}
function buildFlexibilityDay(dayNumber, dayName, profile, week) {
const injuryArea = profile.has_injury ? (profile.injury_area || "none") : "none";
const location = profile.workout_location || "gym";
let exercises = filterByLocation(filterByEquipment(filterByInjury(EXERCISES.flexibility, injuryArea), profile), location);
exercises = pickRandom(exercises, 8);
exercises = applyWeekProgression(exercises, week);
const formattedExercises = exercises.map(formatExercise);
return {
day: dayNumber,
name: `Day ${dayNumber} - ${dayName}`,
type: "active_recovery",
focus: "Flexibility & Recovery",
estimated_duration: 25,
estimated_calories: 40,
warmup: [{ name: "Light Movement", duration: "3 min", notes: "Easy walking or gentle arm swings" }],
exercises: formattedExercises,
cooldown: [{ name: "Deep Breathing & Meditation", duration: "5 min", notes: "Full relaxation for recovery" }],
notes: ["Active recovery day - focus on mobility and flexibility", "Keep all movements gentle and controlled"],
};
}
function buildRestDay(dayNumber, dayName, profile, week) {
const injuryArea = profile.has_injury ? (profile.injury_area || "none") : "none";
const location = profile.workout_location || "gym";
let safeFlex = filterByLocation(filterByEquipment(filterByInjury(EXERCISES.flexibility, injuryArea), profile), location);
let exercises = pickRandom(safeFlex, 5);
exercises = applyWeekProgression(exercises, week);
const formattedExercises = exercises.map(formatExercise);
return {
day: dayNumber,
name: `Day ${dayNumber} - Rest`,
type: "rest",
focus: "Active Rest & Flexibility",
estimated_duration: 20,
estimated_calories: 30,
warmup: [],
exercises: formattedExercises,
cooldown: [{ name: "Deep Breathing & Meditation", duration: "5 min", notes: "Focus on recovery and relaxation" }],
notes: ["Rest day - listen to your body", "Light stretching and walking are encouraged"],
};
}
// ─────────────────────────────────────────────────────────────────────────────
// Program generators based on experience level
// ─────────────────────────────────────────────────────────────────────────────
function generateBeginnerProgram(profile, week) {
const daysPerWeek = Math.min(profile.workout_days_per_week || 3, 4);
const days = [];
let dayIndex = 0;
const fullBodyConfigs = [
{ name: "Full Body A", focus: "Chest, Back, Legs, Core", groups: { chest: 2, back: 2, legs: 2, shoulders: 1, core: 2 } },
{ name: "Full Body B", focus: "Back, Legs, Glutes, Arms", groups: { chest: 1, back: 2, legs: 2, glutes: 1, arms_biceps: 1, core: 2 } },
{ name: "Full Body C", focus: "Chest, Shoulders, Legs, Core", groups: { chest: 2, back: 1, legs: 2, shoulders: 2, arms_triceps: 1, core: 1 } },
{ name: "Full Body D", focus: "Back, Legs, Glutes, Shoulders", groups: { back: 2, legs: 2, glutes: 2, shoulders: 1, core: 2 } },
];
const trainingDays = [0, 2, 4, 5]; // Mon, Wed, Fri, Sat
for (let i = 0; i < 7; i++) {
if (dayIndex < daysPerWeek && trainingDays.includes(i) && dayIndex < daysPerWeek) {
const config = fullBodyConfigs[dayIndex % fullBodyConfigs.length];
days.push(buildStrengthDay(i + 1, config.name, config.focus, Object.keys(config.groups), profile, week, config.groups));
dayIndex++;
} else {
days.push(buildRestDay(i + 1, DAYS_TR[i], profile, week));
}
}
return days;
}
function generateIntermediateProgram(profile, week) {
const daysPerWeek = profile.workout_days_per_week || 4;
const days = [];
if (daysPerWeek <= 4) {
// Upper/Lower split
const configs = [
{ name: "Upper Push", focus: "Chest, Shoulders, Triceps", groups: { chest: 3, shoulders: 2, arms_triceps: 2, core: 1 } },
{ name: "Lower Quad", focus: "Quads, Glutes, Core", groups: { legs: 4, glutes: 2, core: 2 } },
{ name: "Upper Pull", focus: "Back, Biceps, Core", groups: { back: 3, shoulders: 1, arms_biceps: 2, core: 1 } },
{ name: "Lower Hip", focus: "Hamstrings, Glutes, Core", groups: { legs: 3, glutes: 3, core: 2 } },
];
let configIndex = 0;
const trainingDays = [0, 1, 3, 4, 5];
for (let i = 0; i < 7; i++) {
if (configIndex < daysPerWeek && trainingDays.includes(i) && configIndex < daysPerWeek) {
const config = configs[configIndex % configs.length];
days.push(buildStrengthDay(i + 1, config.name, config.focus, Object.keys(config.groups), profile, week, config.groups));
configIndex++;
} else {
days.push(buildRestDay(i + 1, DAYS_TR[i], profile, week));
}
}
} else {
// PPL for 5-6 days
const pplConfigs = [
{ name: "Push", focus: "Chest, Shoulders, Triceps", groups: { chest: 3, shoulders: 2, arms_triceps: 2 } },
{ name: "Pull", focus: "Back, Biceps", groups: { back: 4, arms_biceps: 2, core: 1 } },
{ name: "Legs", focus: "Legs, Glutes, Core", groups: { legs: 4, glutes: 2, core: 2 } },
{ name: "Push B", focus: "Shoulders, Chest, Triceps", groups: { chest: 2, shoulders: 3, arms_triceps: 2 } },
{ name: "Pull B", focus: "Back, Biceps, Core", groups: { back: 3, arms_biceps: 3, core: 1 } },
{ name: "Legs & Cardio", focus: "Legs, Glutes, Conditioning", groups: { legs: 3, glutes: 2, core: 2 } },
];
let configIndex = 0;
for (let i = 0; i < 7; i++) {
if (configIndex < daysPerWeek && configIndex < pplConfigs.length) {
if (i === 6 && daysPerWeek < 7) {
days.push(buildRestDay(i + 1, DAYS_TR[i], profile, week));
} else {
const config = pplConfigs[configIndex];
days.push(buildStrengthDay(i + 1, config.name, config.focus, Object.keys(config.groups), profile, week, config.groups));
configIndex++;
}
} else {
days.push(buildRestDay(i + 1, DAYS_TR[i], profile, week));
}
}
}
return days;
}
function generateAdvancedProgram(profile, week) {
const daysPerWeek = profile.workout_days_per_week || 5;
const days = [];
if (daysPerWeek >= 5) {
const configs = [
{ name: "Chest & Triceps", focus: "Chest, Triceps", groups: { chest: 4, arms_triceps: 3 } },
{ name: "Back & Biceps", focus: "Back, Biceps", groups: { back: 4, arms_biceps: 3 } },
{ name: "Legs (Quad)", focus: "Quads, Calves, Core", groups: { legs: 5, core: 2 } },
{ name: "Shoulders & Traps", focus: "Shoulders, Traps, Core", groups: { shoulders: 4, core: 2 } },
{ name: "Legs (Hip) & Glutes", focus: "Hamstrings, Glutes, Core", groups: { legs: 3, glutes: 3, core: 2 } },
{ name: "Arms & Abs", focus: "Biceps, Triceps, Core", groups: { arms_biceps: 3, arms_triceps: 3, core: 3 } },
];
let configIndex = 0;
for (let i = 0; i < 7; i++) {
if (configIndex < daysPerWeek && configIndex < configs.length) {
const config = configs[configIndex];
days.push(buildStrengthDay(i + 1, config.name, config.focus, Object.keys(config.groups), profile, week, config.groups));
configIndex++;
} else {
days.push(buildRestDay(i + 1, DAYS_TR[i], profile, week));
}
}
} else {
// 4-day advanced: Upper/Lower power/hypertrophy
const configs = [
{ name: "Upper Strength", focus: "Chest, Back, Shoulders (Strength)", groups: { chest: 3, back: 3, shoulders: 2 } },
{ name: "Lower Strength", focus: "Legs, Glutes (Strength)", groups: { legs: 4, glutes: 2, core: 2 } },
{ name: "Upper Hypertrophy", focus: "Full Upper Body (Volume)", groups: { chest: 2, back: 2, shoulders: 2, arms_biceps: 2, arms_triceps: 2 } },
{ name: "Lower Hypertrophy", focus: "Legs, Glutes (Volume)", groups: { legs: 3, glutes: 3, core: 3 } },
];
let configIndex = 0;
const trainingDays = [0, 1, 3, 4];
for (let i = 0; i < 7; i++) {
if (configIndex < daysPerWeek && trainingDays.includes(i) && configIndex < daysPerWeek) {
const config = configs[configIndex];
days.push(buildStrengthDay(i + 1, config.name, config.focus, Object.keys(config.groups), profile, week, config.groups));
configIndex++;
} else {
days.push(buildRestDay(i + 1, DAYS_TR[i], profile, week));
}
}
}
return days;
}
// ─────────────────────────────────────────────────────────────────────────────
// Wheelchair / disability-specific program
// ─────────────────────────────────────────────────────────────────────────────
function generateWheelchairProgram(profile, week) {
const daysPerWeek = Math.min(profile.workout_days_per_week || 3, 5);
const days = [];
const configs = [
{ name: "Upper Push", focus: "Chest, Shoulders, Triceps", groups: { chest: 3, shoulders: 2, arms_triceps: 2, core: 2 } },
{ name: "Upper Pull", focus: "Back, Biceps, Core", groups: { back: 3, arms_biceps: 2, core: 3 } },
{ name: "Shoulders & Arms", focus: "Shoulders, Arms, Core", groups: { shoulders: 3, arms_biceps: 2, arms_triceps: 2, core: 2 } },
{ name: "Upper Strength", focus: "Chest, Back Compound", groups: { chest: 2, back: 3, shoulders: 2 } },
{ name: "Upper Volume", focus: "Full Upper Body Volume", groups: { chest: 2, back: 2, shoulders: 2, arms_biceps: 1, arms_triceps: 1, core: 2 } },
];
let configIndex = 0;
for (let i = 0; i < 7; i++) {
if (configIndex < daysPerWeek) {
const config = configs[configIndex % configs.length];
days.push(buildStrengthDay(i + 1, config.name, config.focus, Object.keys(config.groups), profile, week, config.groups));
configIndex++;
} else {
days.push(buildRestDay(i + 1, DAYS_TR[i], profile, week));
}
}
return days;
}
// ─────────────────────────────────────────────────────────────────────────────
// Goal-specific adjustments
// ─────────────────────────────────────────────────────────────────────────────
function applyGoalAdjustments(days, profile, week) {
const bodyType = profile.body_type || "mesomorph";
const location = profile.workout_location || "gym";
return days.map((day) => {
if (day.type === "rest" || day.type === "active_recovery" || day.type === "light_activity") return day;
let modified = { ...day, exercises: [...day.exercises] };
// For lose_weight: add cardio to strength days
if (hasGoal(profile, "lose_weight") && day.type === "strength" && !profile.heart_condition) {
const injuryArea = profile.has_injury ? (profile.injury_area || "none") : "none";
let safeCardio = filterByLocation(filterByEquipment(filterByConditions(filterByInjury(EXERCISES.cardio, injuryArea), profile), profile), location);
if (safeCardio.length > 0) {
const cardio = pickRandom(safeCardio, 1);
modified.exercises = modified.exercises.concat(cardio.map(formatExercise));
modified.estimated_calories += 35;
modified.estimated_duration += 10;
}
}
// Endomorph: add extra finisher
if (bodyType === "endomorph" && day.type === "strength" && !profile.heart_condition) {
const injuryArea = profile.has_injury ? (profile.injury_area || "none") : "none";
let safeHiit = filterByLocation(filterByEquipment(filterByConditions(filterByInjury(EXERCISES.hiit, injuryArea), profile), profile), location);
if (safeHiit.length > 0) {
const hiitFinisher = pickRandom(safeHiit, 1);
modified.exercises = modified.exercises.concat(hiitFinisher.map(formatExercise));
modified.estimated_calories += 30;
modified.estimated_duration += 5;
}
}
// Gain weight: remove excess cardio from strength days
if (hasGoal(profile, "gain_weight")) {
modified.exercises = modified.exercises.filter((e) => {
return !EXERCISES.cardio.some((c) => c.name === e.name);
});
}
return modified;
});
}
function adjustCardioRestDays(days, profile, week) {
const bodyType = profile.body_type || "mesomorph";
let cardioDaysNeeded = 0;
if (hasGoal(profile, "lose_weight") && !profile.heart_condition) cardioDaysNeeded = 2;
else if (bodyType === "endomorph" && !profile.heart_condition) cardioDaysNeeded = 1;
let converted = 0;
let restCount = days.filter((d) => d.type === "rest").length;
return days.map((day) => {
if (day.type === "rest" && converted < cardioDaysNeeded && restCount > 1) {
converted++;
restCount--;
return buildCardioDay(day.day, "Cardio", "Cardio & Core", profile, week);
}
return day;
});
}
// ─────────────────────────────────────────────────────────────────────────────
// Light activity plan generator (for workout_location: "none")
// ─────────────────────────────────────────────────────────────────────────────
function generateLightActivityPlan(profile, week) {
let planKey = "standard";
if (profile.uses_wheelchair) {
planKey = "wheelchair";
} else if (profile.has_disability && profile.mobility_level === "limited_both") {
planKey = "limited_both";
}
const plan = LIGHT_ACTIVITY_PLANS[planKey] || LIGHT_ACTIVITY_PLANS.standard;
const weekConfig = MESOCYCLE[week] || MESOCYCLE[1];
// Adjust durations for deload week
return plan.map((day) => {
const adjustedDay = { ...day };
if (weekConfig.volume_multiplier < 1) {
adjustedDay.estimated_duration = Math.round(day.estimated_duration * weekConfig.volume_multiplier);
adjustedDay.estimated_calories = Math.round(day.estimated_calories * weekConfig.volume_multiplier);
}
adjustedDay.warmup = [];
adjustedDay.exercises = [];
adjustedDay.cooldown = [];
adjustedDay.notes = [`Week ${week}: ${weekConfig.description}`];
return adjustedDay;
});
}
// ─────────────────────────────────────────────────────────────────────────────
// Main entry point
// ─────────────────────────────────────────────────────────────────────────────
function generateWorkoutProgram(profile, week = 1) {
const normalizedWeek = Math.max(1, Math.min(4, week));
const experience = profile.workout_experience || "beginner";
const workoutLocation = profile.workout_location || "gym";
const mesocycleConfig = MESOCYCLE[normalizedWeek];
// For "none" location: generate light activity plan
if (workoutLocation === "none") {
const lightDays = generateLightActivityPlan(profile, normalizedWeek);
return {
title: "Personal Light Activity Plan",
description: "A gentle daily activity plan designed for your current situation. Focus on movement quality, breathing, and gradual improvement.",
week: normalizedWeek,
workout_location: "none",
experience_level: experience,
notes: [
"This is a light activity plan, not a workout program",
"Listen to your body and rest when needed",
"Consistency matters more than intensity",
"Consult your doctor before starting any new exercise routine",
],
general_tips: buildGeneralTips(profile),
injury_note: buildInjuryNote(profile),
medical_notes: buildMedicalNotes(profile),
days: lightDays,
};
}
// Check for wheelchair or severe disability
if (profile.uses_wheelchair || (profile.has_disability && profile.mobility_level === "limited_both")) {
if (profile.uses_wheelchair) {
const days = generateWheelchairProgram(profile, normalizedWeek);
const adjustedDays = applyGoalAdjustments(days, profile, normalizedWeek);
return {
title: "Personal Wheelchair-Adapted Training Program",
description: "Upper body focused program adapted for wheelchair users. All exercises are seated or upper body only.",
week: normalizedWeek,
workout_location: workoutLocation,
experience_level: experience,
notes: [
"All exercises adapted for seated position",
"Focus on upper body strength and core stability",
"Include shoulder health and posture exercises",
],
general_tips: buildGeneralTips(profile),
injury_note: buildInjuryNote(profile),
medical_notes: buildMedicalNotes(profile),
days: adjustedDays,
};
}
// Limited both - generate light activity even if location is gym/home
const lightDays = generateLightActivityPlan(profile, normalizedWeek);
return {
title: "Personal Gentle Movement Plan",
description: "A gentle movement plan adapted for your mobility level. Focus on what you can do comfortably.",
week: normalizedWeek,
workout_location: workoutLocation,
experience_level: experience,
notes: [
"Gentle movements only - stay within your comfort zone",
"Focus on breathing and mobility",
"Any movement is beneficial",
],
general_tips: buildGeneralTips(profile),
injury_note: buildInjuryNote(profile),
medical_notes: buildMedicalNotes(profile),
days: lightDays,
};
}
// Standard program generation
let days;
switch (experience) {
case "advanced":
days = generateAdvancedProgram(profile, normalizedWeek);
break;
case "intermediate":
days = generateIntermediateProgram(profile, normalizedWeek);
break;
case "beginner":
default:
days = generateBeginnerProgram(profile, normalizedWeek);
break;
}
// Apply goal-specific adjustments
days = applyGoalAdjustments(days, profile, normalizedWeek);
days = adjustCardioRestDays(days, profile, normalizedWeek);
const title = workoutLocation === "home"
? "Personal Home Training Program"
: "Personal Training Program";
const description = `${experience.charAt(0).toUpperCase() + experience.slice(1)} level ${workoutLocation} training program. Week ${normalizedWeek} of 4 (${mesocycleConfig.phase}).`;
return {
title: title,
description: description,
week: normalizedWeek,
workout_location: workoutLocation,
experience_level: experience,
notes: [
`Mesocycle phase: ${mesocycleConfig.phase} - ${mesocycleConfig.description}`,
],
general_tips: buildGeneralTips(profile),
injury_note: buildInjuryNote(profile),
medical_notes: buildMedicalNotes(profile),
days: days,
};
}
module.exports = { generateWorkoutProgram };