| def calculate_bmi(weight, height): |
| h = height / 100 |
| return weight / (h * h) |
|
|
| def bmi_category(bmi): |
| if bmi < 18.5: return "Underweight" |
| elif bmi < 25: return "Normal Weight" |
| elif bmi < 30: return "Overweight" |
| else: return "Obese" |
|
|
| def bmi_advice(category): |
| return { |
| "Underweight": "focus on caloric surplus, compound lifts, and muscle building. Avoid excessive cardio.", |
| "Normal Weight": "maintain current weight while building lean muscle and improving cardiovascular fitness.", |
| "Overweight": "incorporate cardio-strength circuits to burn fat while preserving muscle mass.", |
| "Obese": "prioritise low-impact cardio, mobility work, and progressive resistance training.", |
| }.get(category, "train consistently and progressively.") |
|
|
|
|
| |
| |
| INJURY_RESTRICTIONS = { |
| "knee": { |
| "avoid": [ |
| "squats", "lunges", "leg press", "jump", "plyometric", |
| "running", "step-ups", "leg extension", "deep knee bend" |
| ], |
| "replace_with": [ |
| "seated leg curl", "hip thrust", "glute bridge", "upper body focus", |
| "swimming", "seated calf raise", "lying leg curl" |
| ], |
| "note": "Avoid all deep knee flexion and high-impact lower body movements. " |
| "Focus on hamstrings, glutes, and upper body. No jumping or running." |
| }, |
| "shoulder": { |
| "avoid": [ |
| "overhead press", "military press", "shoulder press", "lateral raise", |
| "upright row", "behind neck press", "dips", "push press", |
| "handstand", "overhead squat" |
| ], |
| "replace_with": [ |
| "face pull", "external rotation", "low cable row", "chest-supported row", |
| "front raise (light)", "reverse fly", "lower body focus" |
| ], |
| "note": "Avoid all overhead pressing and upright rows. " |
| "Focus on lower body, core, and horizontal pulling movements." |
| }, |
| "back": { |
| "avoid": [ |
| "deadlift", "barbell row", "good morning", "back squat", |
| "hyperextension", "heavy carry", "jefferson curl", "stiff-leg deadlift" |
| ], |
| "replace_with": [ |
| "lat pulldown", "seated cable row", "leg press", "goblet squat", |
| "plank", "bird dog", "cat-cow", "pallof press" |
| ], |
| "note": "Avoid all heavy spinal loading. Use braced core on every movement. " |
| "Prefer machines over free weights for lower body." |
| }, |
| "wrist": { |
| "avoid": [ |
| "push-up", "barbell curl", "front rack", "handstand", |
| "wrist curl", "clean", "snatch", "dumbbell press (grip-heavy)" |
| ], |
| "replace_with": [ |
| "cable curl", "hammer curl with neutral grip", "machine press", |
| "tricep pushdown", "leg press", "lower body focus" |
| ], |
| "note": "Avoid any exercise that loads the wrist in extension or flexion. " |
| "Use neutral grip or machine alternatives throughout." |
| }, |
| "ankle": { |
| "avoid": [ |
| "jump", "box jump", "running", "sprint", "calf raise", |
| "agility drill", "lunge (walking)", "step-up" |
| ], |
| "replace_with": [ |
| "seated leg curl", "leg press", "hip thrust", "glute bridge", |
| "upper body focus", "seated calf raise (light)" |
| ], |
| "note": "Avoid all weight-bearing dynamic lower body movements. " |
| "Focus on seated and supine lower body exercises and upper body." |
| }, |
| "elbow": { |
| "avoid": [ |
| "tricep dip", "skull crusher", "close-grip bench", "preacher curl", |
| "pull-up (if painful)", "push-up (if painful)", "barbell curl" |
| ], |
| "replace_with": [ |
| "cable tricep pushdown", "cable curl", "neutral grip row", |
| "machine press", "leg press", "lower body focus" |
| ], |
| "note": "Avoid full elbow extension under load and deep elbow flexion. " |
| "Use cables over free weights to reduce joint stress." |
| }, |
| "hip": { |
| "avoid": [ |
| "deep squat", "leg press (full range)", "hip flexor stretch", |
| "lunge", "step-up", "running", "sprint", "jump" |
| ], |
| "replace_with": [ |
| "glute bridge", "clamshell", "side-lying abduction", |
| "upper body focus", "seated leg curl", "light walking" |
| ], |
| "note": "Avoid deep hip flexion and high-impact movements. " |
| "Focus on gentle hip strengthening and upper body work." |
| }, |
| "neck": { |
| "avoid": [ |
| "neck extension", "shrug", "overhead press", "behind-neck press", |
| "upright row", "any exercise causing neck strain" |
| ], |
| "replace_with": [ |
| "face pull", "chest-supported row", "lower body focus", |
| "plank", "dead bug", "pallof press" |
| ], |
| "note": "Avoid all cervical loading and overhead work. " |
| "Keep head neutral on every exercise. No shrugs or overhead pressing." |
| }, |
| "hamstring": { |
| "avoid": [ |
| "deadlift", "stiff-leg deadlift", "leg curl (full range, high load)", |
| "sprint", "running", "jump", "good morning" |
| ], |
| "replace_with": [ |
| "leg press", "goblet squat", "hip thrust", "glute bridge", |
| "upper body focus", "light walking" |
| ], |
| "note": "Avoid high hamstring tension under load. " |
| "Focus on quad-dominant lower body movements and upper body." |
| }, |
| "calf": { |
| "avoid": [ |
| "calf raise (heavy)", "jump", "box jump", "sprint", |
| "running", "agility drill" |
| ], |
| "replace_with": [ |
| "leg press", "hip thrust", "upper body focus", |
| "seated calf raise (very light)", "swimming" |
| ], |
| "note": "Avoid all explosive and heavy plantarflexion. " |
| "Focus on upper body and non-impact lower body movements." |
| }, |
| "rotator cuff": { |
| "avoid": [ |
| "overhead press", "lateral raise (heavy)", "internal rotation under load", |
| "behind-neck pull-down", "upright row", "dip", "bench press (wide grip)" |
| ], |
| "replace_with": [ |
| "external rotation (band/cable)", "face pull", "chest-supported row", |
| "neutral grip row", "lower body focus", "light front raise" |
| ], |
| "note": "Avoid overhead and impingement-risk positions. " |
| "Strengthen rotator cuff with low-load external rotation drills. " |
| "No heavy pressing until cleared." |
| }, |
| "achilles": { |
| "avoid": [ |
| "calf raise", "jump", "box jump", "sprint", "running", |
| "agility drill", "walking lunge", "step-up" |
| ], |
| "replace_with": [ |
| "seated leg curl", "leg press", "hip thrust", |
| "upper body focus", "light cycling (seated)" |
| ], |
| "note": "Avoid all Achilles loading. Strictly no jumping, running, or calf work. " |
| "Focus on seated/supine lower body and upper body movements." |
| }, |
| } |
|
|
|
|
| def build_injury_block(injuries): |
| """ |
| Build the injury restriction block for the AI prompt. |
| Returns empty string if no injuries. |
| """ |
| if not injuries: |
| return "" |
|
|
| lines = ["βββ INJURY & LIMITATION RESTRICTIONS βββ"] |
| lines.append( |
| f"β οΈ The client has the following injuries/limitations: " |
| f"{', '.join(i.upper() for i in injuries)}" |
| ) |
| lines.append( |
| "You MUST apply ALL of the rules below. This is non-negotiable for client safety.\n" |
| ) |
|
|
| all_avoid = [] |
| all_replace = [] |
|
|
| for injury in injuries: |
| key = injury.lower().strip() |
| if key in INJURY_RESTRICTIONS: |
| r = INJURY_RESTRICTIONS[key] |
| lines.append(f"β’ {injury.upper()} injury:") |
| lines.append(f" - NEVER include: {', '.join(r['avoid'])}") |
| lines.append(f" - Safe alternatives: {', '.join(r['replace_with'])}") |
| lines.append(f" - Rule: {r['note']}") |
| all_avoid.extend(r["avoid"]) |
| all_replace.extend(r["replace_with"]) |
|
|
| lines.append( |
| f"\nβ GLOBAL FORBIDDEN EXERCISES (across ALL {len(injuries)} injuries): " |
| + ", ".join(sorted(set(all_avoid))) |
| ) |
| lines.append( |
| "β
Preferred safe alternatives pool: " |
| + ", ".join(sorted(set(all_replace))) |
| ) |
| lines.append( |
| "\nπ INJURY COMPLIANCE RULES:" |
| "\n 1. Scan every exercise in your plan against the forbidden list above before including it." |
| "\n 2. If an exercise even partially loads the injured area, replace it." |
| "\n 3. Never suggest the user 'try' or 'attempt' a forbidden movement." |
| "\n 4. For warm-up and cool-down, also avoid stretches that stress the injured area." |
| "\n 5. Label injury-adapted exercises with '(injury-safe)' so the user knows." |
| ) |
|
|
| return "\n".join(lines) |
|
|
|
|
| def build_diet_block(diet_type, cuisine_preference, cuisine_label, |
| cuisine_icon, cuisine_notes): |
| """ |
| Build the diet/cuisine/allergy block for the AI prompt. |
| """ |
| diet_display = "Vegetarian (no meat, no fish, no eggs)" if diet_type == "veg" \ |
| else "Non-Vegetarian (chicken, egg, and fish only β NO red meat, NO pork)" |
|
|
| cuisine_str = f"{cuisine_icon} {cuisine_label}" if cuisine_label else "Standard" |
|
|
| lines = [ |
| "βββ DIET & MEAL PLAN REQUIREMENTS βββ", |
| f"Diet Type : {diet_display}", |
| f"Cuisine Style : {cuisine_str}", |
| ] |
|
|
| if cuisine_notes and cuisine_notes.strip(): |
| lines.append(f"Allergies/Notes : {cuisine_notes.strip()}") |
| lines.append( |
| "\nβ οΈ ALLERGY & PREFERENCE RULES (STRICT):" |
| "\n 1. Read the Allergies/Notes above carefully." |
| "\n 2. NEVER include any ingredient the user has flagged as an allergy or exclusion." |
| "\n 3. If the user says 'no eggs' β zero egg-containing meals across all days." |
| "\n 4. If the user says 'lactose intolerant' β no dairy in any meal." |
| "\n 5. Treat every restriction as a hard medical requirement, not a preference." |
| "\n 6. When in doubt, substitute with a safe alternative and note it." |
| ) |
|
|
| lines += [ |
| "\nMEAL PLAN RULES:", |
| " β’ Every training day must include: Breakfast, Pre-Workout Snack, " |
| "Lunch, Post-Workout Meal, Dinner.", |
| " β’ Every rest day must include: Breakfast, Mid-Morning Snack, " |
| "Lunch, Afternoon Snack, Dinner.", |
| f" β’ All meals must match the {cuisine_str} cuisine style.", |
| " β’ Include approximate macros (protein / carbs / fat) for each meal.", |
| " β’ Include total daily calories.", |
| " β’ Meals must support the client's fitness goal (see CLIENT PROFILE).", |
| " β’ Do NOT suggest any ingredient excluded in Allergies/Notes above.", |
| ] |
|
|
| return "\n".join(lines) |
|
|
|
|
| def build_prompt(name, gender, height, weight, goal, fitness_level, equipment, |
| days_per_week=5, months=1, |
| injuries=None, diet_type="nonveg", |
| cuisine_preference="", cuisine_label="", |
| cuisine_icon="", cuisine_notes=""): |
| """ |
| Build the full AI prompt for workout + diet plan generation. |
| |
| New parameters vs old version: |
| injuries : list of injury strings e.g. ["knee", "shoulder"] |
| diet_type : "veg" or "nonveg" |
| cuisine_preference : cuisine id string e.g. "indian_nonveg" |
| cuisine_label : human-readable label e.g. "Indian" |
| cuisine_icon : emoji icon e.g. "π" |
| cuisine_notes : free-text allergies/preferences e.g. "no eggs, lactose intolerant" |
| """ |
| if injuries is None: |
| injuries = [] |
|
|
| bmi = calculate_bmi(weight, height) |
| bmi_cat = bmi_category(bmi) |
| eq_list = ", ".join(equipment) if equipment else "Bodyweight only (no equipment)" |
| advice = bmi_advice(bmi_cat) |
| total_days = days_per_week * 4 * months |
| total_days = min(total_days, 30) |
|
|
| intensity_map = { |
| "Beginner": "2β3 working sets, moderate weight, longer rest (90s). Prioritise form over load.", |
| "Intermediate": "3β4 working sets, progressive overload, 60β75s rest.", |
| "Advanced": "4β5 working sets, heavy compound movements, 45β60s rest, supersets where appropriate.", |
| } |
| intensity = intensity_map.get(fitness_level, "3 sets, 60s rest.") |
|
|
| |
| injury_block = build_injury_block(injuries) |
| diet_block = build_diet_block(diet_type, cuisine_preference, |
| cuisine_label, cuisine_icon, cuisine_notes) |
|
|
| |
| injury_rule = "" |
| if injuries: |
| injury_rule = ( |
| f"\n8. INJURIES: The client has {', '.join(injuries)} injuries. " |
| f"STRICTLY follow the injury restrictions block above. " |
| f"Mark every adapted exercise with '(injury-safe)'." |
| ) |
|
|
| allergy_rule = "" |
| if cuisine_notes and cuisine_notes.strip(): |
| allergy_rule = ( |
| f"\n9. ALLERGIES: '{cuisine_notes.strip()}' β " |
| f"zero tolerance. Never include any flagged ingredient in any meal." |
| ) |
|
|
| prompt = f"""You are an elite certified personal trainer, sports scientist, and registered nutritionist. |
| Create a complete, professional {total_days}-day personalised workout AND diet plan |
| ({days_per_week} training days per week Γ {months} month{'s' if months > 1 else ''}). |
| |
| βββ CLIENT PROFILE βββ |
| Name : {name} |
| Gender : {gender} |
| Height / Weight: {height} cm / {weight} kg |
| BMI : {bmi:.1f} ({bmi_cat}) |
| Primary Goal : {goal} |
| Fitness Level : {fitness_level} |
| Equipment : {eq_list} |
| Plan Duration : {days_per_week} days/week for {months} month{'s' if months > 1 else ''} = {total_days} workout days total |
| |
| βββ PROGRAMMING NOTES βββ |
| β’ BMI guidance : {advice} |
| β’ Intensity : {intensity} |
| β’ Equipment : Only use the equipment listed above. Substitute with bodyweight if needed. |
| β’ Progression : Each week should slightly increase intensity, volume or complexity. |
| β’ Rest days : Build rest days into the weekly cycle naturally ({days_per_week} days/week training). |
| |
| {injury_block} |
| |
| {diet_block} |
| |
| βββ REQUIRED OUTPUT FORMAT βββ |
| Use EXACTLY this structure for ALL {total_days} days: |
| |
| ## Day 1 - [Muscle Group / Focus] |
| |
| **Warm-Up (5 min)** |
| - Exercise 1: sets x reps |
| - Exercise 2: sets x reps |
| |
| **Main Workout** |
| - Exercise 1 β sets x reps (rest 60s) |
| - Exercise 2 β sets x reps (rest 60s) |
| - Exercise 3 β sets x reps (rest 60s) |
| - Exercise 4 β sets x reps (rest 60s) |
| - Exercise 5 β sets x reps (rest 60s) |
| |
| **Cool-Down (3 min)** |
| - Stretch 1 |
| - Stretch 2 |
| |
| **Meals for the Day** |
| - Breakfast: [meal name] β [brief description] | Protein: Xg | Carbs: Xg | Fat: Xg |
| - Pre-Workout Snack: [meal] | Protein: Xg | Carbs: Xg | Fat: Xg |
| - Lunch: [meal] β [brief description] | Protein: Xg | Carbs: Xg | Fat: Xg |
| - Post-Workout Meal: [meal] | Protein: Xg | Carbs: Xg | Fat: Xg |
| - Dinner: [meal] β [brief description] | Protein: Xg | Carbs: Xg | Fat: Xg |
| - Daily Total: ~XXXX kcal | Protein: Xg | Carbs: Xg | Fat: Xg |
| |
| [Continue this exact structure for Day 2 through Day {total_days}] |
| |
| βββ FINAL SECTION βββ |
| End with ONE personalised motivational paragraph addressed directly to {name}. |
| |
| βββ RULES βββ |
| 1. Day headers must start with "## Day N -" |
| 2. Include sets Γ reps for every exercise (e.g. 3 x 12 reps) |
| 3. Rest periods in parentheses after each exercise |
| 4. No exercises unsafe for {fitness_level} level |
| 5. Ensure variety across all days β don't repeat same muscle groups back-to-back |
| 6. Be specific β no vague instructions |
| 7. Generate ALL {total_days} days β do not stop early{injury_rule}{allergy_rule} |
| """ |
| return prompt, bmi, bmi_cat |