Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -3,195 +3,233 @@ import joblib
|
|
| 3 |
import pandas as pd
|
| 4 |
import random
|
| 5 |
|
| 6 |
-
# 1. Load Model
|
| 7 |
model = joblib.load('fitness_model.joblib')
|
| 8 |
|
| 9 |
-
# 2.
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
-
#
|
| 15 |
-
|
| 16 |
-
if experience == "Beginner": strength_base *= 0.6
|
| 17 |
-
if experience == "Advanced": strength_base *= 1.4
|
| 18 |
|
| 19 |
-
|
| 20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
| 26 |
else:
|
| 27 |
-
|
| 28 |
|
| 29 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
if goal == "Muscle Gain":
|
| 31 |
-
|
| 32 |
-
rest = "
|
| 33 |
-
focus = "Hypertrophy (Focus on the squeeze)"
|
| 34 |
elif goal == "Strength":
|
| 35 |
-
|
| 36 |
-
rest = "3
|
| 37 |
-
focus = "Max Force (Lift heavy safely)"
|
| 38 |
elif goal == "Weight Loss":
|
| 39 |
-
|
| 40 |
-
rest = "
|
| 41 |
-
focus = "High Heart Rate (Keep moving)"
|
| 42 |
-
else: # General Health / Endurance
|
| 43 |
-
protocol = "3 sets x 12 reps"
|
| 44 |
-
rest = "60 sec rest"
|
| 45 |
-
focus = "Consistency & Form"
|
| 46 |
-
|
| 47 |
-
# 3. Adjust for Age
|
| 48 |
-
warmup_duration = "5 mins"
|
| 49 |
-
if age > 50:
|
| 50 |
-
warmup_duration = "10-12 mins (Joint mobilization focus)"
|
| 51 |
-
rest += " + 30 sec extra for recovery"
|
| 52 |
-
|
| 53 |
-
# --- B. Build the Routine Components ---
|
| 54 |
-
|
| 55 |
-
# 1. Warmup
|
| 56 |
-
warmup = f"""
|
| 57 |
-
⏱️ DURATION: {warmup_duration}
|
| 58 |
-
1. Joint Rotations (Neck, Shoulders, Hips, Ankles)
|
| 59 |
-
2. 3 min Light Cardio ({'Jumping Jacks' if injury != 'Knee' else 'March in place'})
|
| 60 |
-
3. Dynamic Stretch: {'Arm Circles' if 'Upper' in plan_category else 'Leg Swings'}
|
| 61 |
-
"""
|
| 62 |
|
| 63 |
-
#
|
| 64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
|
| 66 |
-
|
| 67 |
-
if injury == "Knee":
|
| 68 |
-
exercises = [
|
| 69 |
-
f"1. Glute Bridges (Floor): {protocol} (Safe for knees)",
|
| 70 |
-
f"2. Seated Overhead Press: {protocol} ({weight_text})",
|
| 71 |
-
f"3. Lat Pulldowns or Pull-ups: {protocol}",
|
| 72 |
-
f"4. Plank Hold: 3 sets x 45 sec"
|
| 73 |
-
]
|
| 74 |
-
elif injury == "Back":
|
| 75 |
-
exercises = [
|
| 76 |
-
f"1. Wall Sits: 3 sets x 45 sec (Spine neutral)",
|
| 77 |
-
f"2. Supported Single-Arm Row: {protocol} ({weight_text})",
|
| 78 |
-
f"3. Seated Chest Press/Pushups (Incline): {protocol}",
|
| 79 |
-
f"4. Bird-Dog: 3 sets x 12 reps (Stability)"
|
| 80 |
-
]
|
| 81 |
-
elif injury == "Shoulder":
|
| 82 |
-
exercises = [
|
| 83 |
-
f"1. Leg Press or Goblet Squat (Hands low): {protocol}",
|
| 84 |
-
f"2. Lunges: {protocol} (Bodyweight)",
|
| 85 |
-
f"3. Bicep Curls: {protocol} ({weight_text})",
|
| 86 |
-
f"4. Tricep Pushdowns (Elbows tucked): {protocol}"
|
| 87 |
-
]
|
| 88 |
-
|
| 89 |
-
# -- IF HEALTHY (Goal & Equipment Priority) --
|
| 90 |
-
else:
|
| 91 |
-
# Leg Exercise
|
| 92 |
-
if equipment == "Bodyweight Only": leg_ex = "Air Squats"
|
| 93 |
-
elif equipment == "Home Dumbbells": leg_ex = "Dumbbell Goblet Squats"
|
| 94 |
-
else: leg_ex = "Barbell Back Squats"
|
| 95 |
-
|
| 96 |
-
# Push Exercise
|
| 97 |
-
if equipment == "Bodyweight Only": push_ex = "Push-ups"
|
| 98 |
-
elif equipment == "Home Dumbbells": push_ex = "Dumbbell Bench Press"
|
| 99 |
-
else: push_ex = "Barbell Bench Press"
|
| 100 |
-
|
| 101 |
-
# Pull Exercise
|
| 102 |
-
if equipment == "Bodyweight Only": pull_ex = "Inverted Rows (using table)"
|
| 103 |
-
elif equipment == "Home Dumbbells": pull_ex = "Dumbbell Rows"
|
| 104 |
-
else: pull_ex = "Barbell Bent Over Row"
|
| 105 |
-
|
| 106 |
-
exercises = [
|
| 107 |
-
f"1. {leg_ex}: {protocol} using {weight_text}",
|
| 108 |
-
f"2. {push_ex}: {protocol}",
|
| 109 |
-
f"3. {pull_ex}: {protocol}",
|
| 110 |
-
f"4. {'Shoulder Press' if goal != 'Weight Loss' else 'Burpees'}: {protocol}"
|
| 111 |
-
]
|
| 112 |
-
|
| 113 |
-
# 3. Finisher (Core/Cardio)
|
| 114 |
-
if goal in ["Weight Loss", "Athletic Performance", "Endurance"]:
|
| 115 |
-
finisher = """
|
| 116 |
-
🔥 CARDIO FINISHER:
|
| 117 |
-
- 30 sec High Knees / Mountain Climbers
|
| 118 |
-
- 30 sec Rest
|
| 119 |
-
- Repeat 5 times
|
| 120 |
-
"""
|
| 121 |
-
else: # Muscle/Strength/Health
|
| 122 |
-
finisher = """
|
| 123 |
-
🧱 CORE & STABILITY FINISHER:
|
| 124 |
-
- Plank: 3 sets x failure
|
| 125 |
-
- Russian Twists: 3 sets x 20 reps
|
| 126 |
-
"""
|
| 127 |
-
|
| 128 |
-
# 4. Cooldown
|
| 129 |
-
cooldown = """
|
| 130 |
-
🧘 COOLDOWN (Don't skip!):
|
| 131 |
-
1. Hamstring Stretch (30 sec per leg)
|
| 132 |
-
2. Chest Opener (Doorway stretch)
|
| 133 |
-
3. Child's Pose (Relieve back tension)
|
| 134 |
-
"""
|
| 135 |
|
| 136 |
-
#
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
---------------------------------------------------
|
| 140 |
-
👤 PROFILE: {age}y/o {gender} | Goal: {goal} | Exp: {experience}
|
| 141 |
-
⚖️ REC. WEIGHTS: {weight_text}
|
| 142 |
-
🎯 FOCUS: {focus}
|
| 143 |
-
----------------------------------------------------
|
| 144 |
|
| 145 |
-
|
| 146 |
-
|
|
|
|
|
|
|
|
|
|
| 147 |
|
| 148 |
-
💪 MAIN WORKOUT (Rest: {rest}):
|
| 149 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 150 |
|
| 151 |
-
|
|
|
|
|
|
|
| 152 |
|
| 153 |
-
{
|
| 154 |
-
"""
|
| 155 |
|
| 156 |
-
return
|
| 157 |
|
| 158 |
-
#
|
| 159 |
-
def
|
| 160 |
-
#
|
| 161 |
-
|
| 162 |
'Age': [age], 'Gender': [gender], 'Weight_kg': [weight],
|
| 163 |
'Height_cm': [height], 'Goal': [goal], 'Equipment': [equipment],
|
| 164 |
'Injury': [injury], 'Experience': [experience]
|
| 165 |
})
|
| 166 |
-
|
| 167 |
|
| 168 |
-
#
|
| 169 |
-
|
| 170 |
|
| 171 |
-
#
|
| 172 |
-
|
| 173 |
|
| 174 |
-
return
|
| 175 |
|
| 176 |
-
#
|
| 177 |
iface = gr.Interface(
|
| 178 |
-
fn=
|
| 179 |
inputs=[
|
| 180 |
gr.Slider(18, 80, value=25, label="Age"),
|
| 181 |
gr.Radio(["Male", "Female"], label="Gender", value="Male"),
|
| 182 |
gr.Number(label="Weight (kg)", value=75),
|
| 183 |
gr.Number(label="Height (cm)", value=175),
|
| 184 |
-
gr.Dropdown(['Weight Loss', 'Muscle Gain', 'Endurance', 'General Health', 'Strength'], label="Goal", value="
|
| 185 |
gr.Dropdown(['Gym Membership', 'Home Dumbbells', 'Bodyweight Only', 'Full Home Gym (Rack+Barbell)'], label="Equipment", value="Gym Membership"),
|
| 186 |
gr.Dropdown(['None', 'Knee', 'Back', 'Shoulder', 'Ankle'], label="Injury", value="None"),
|
| 187 |
gr.Radio(['Beginner', 'Intermediate', 'Advanced'], label="Experience", value="Intermediate")
|
| 188 |
],
|
| 189 |
outputs=[
|
| 190 |
-
gr.Textbox(label="Your
|
| 191 |
-
gr.Textbox(label="
|
| 192 |
],
|
| 193 |
-
title="SmartFit AI Ultimate
|
| 194 |
-
description="
|
| 195 |
theme="soft"
|
| 196 |
)
|
| 197 |
|
|
|
|
| 3 |
import pandas as pd
|
| 4 |
import random
|
| 5 |
|
| 6 |
+
# 1. Load Model (The "Brain" trained on Synthetic Data)
|
| 7 |
model = joblib.load('fitness_model.joblib')
|
| 8 |
|
| 9 |
+
# --- 2. MASSIVE EXERCISE LIBRARY ---
|
| 10 |
+
# Format: "Name": (Target, [Bad For], Min_Age, Max_BMI, Equipment_Needed)
|
| 11 |
+
# BMI > 30 means obese, Age > 60 means senior.
|
| 12 |
+
|
| 13 |
+
exercise_db = {
|
| 14 |
+
"Legs": [
|
| 15 |
+
("Barbell Squat", ["Quads"], ["Back", "Knee"], 0, 30, "Rack"),
|
| 16 |
+
("Leg Press", ["Quads"], [], 0, 40, "Machine"),
|
| 17 |
+
("Goblet Squat", ["Quads"], ["Knee"], 0, 35, "Dumbbells"),
|
| 18 |
+
("Bodyweight Squat", ["Quads"], [], 0, 50, "Bodyweight"),
|
| 19 |
+
("Box Squat", ["Quads"], [], 50, 40, "Bodyweight"), # Good for seniors
|
| 20 |
+
("Romanian Deadlift", ["Hamstrings"], ["Back"], 0, 30, "Barbell"),
|
| 21 |
+
("Dumbbell RDL", ["Hamstrings"], ["Back"], 0, 35, "Dumbbells"),
|
| 22 |
+
("Lying Leg Curl", ["Hamstrings"], [], 0, 45, "Machine"),
|
| 23 |
+
("Glute Bridge", ["Glutes"], [], 0, 50, "Bodyweight"), # Safe for everyone
|
| 24 |
+
("Walking Lunges", ["Glutes"], ["Knee", "Ankle"], 0, 30, "Bodyweight"),
|
| 25 |
+
("Bulgarian Split Squat", ["Quads"], ["Knee", "Ankle"], 0, 28, "Dumbbells") # Hard!
|
| 26 |
+
],
|
| 27 |
+
"Push": [
|
| 28 |
+
("Barbell Bench Press", ["Chest"], ["Shoulder"], 0, 35, "Rack"),
|
| 29 |
+
("Dumbbell Floor Press", ["Chest"], [], 0, 40, "Dumbbells"), # Shoulder safe
|
| 30 |
+
("Push-ups", ["Chest"], ["Shoulder"], 0, 32, "Bodyweight"),
|
| 31 |
+
("Knee Push-ups", ["Chest"], [], 0, 50, "Bodyweight"),
|
| 32 |
+
("Overhead Press (Barbell)", ["Shoulders"], ["Shoulder", "Back"], 0, 30, "Barbell"),
|
| 33 |
+
("Seated Dumbbell Press", ["Shoulders"], [], 0, 40, "Dumbbells"),
|
| 34 |
+
("Lateral Raises", ["Shoulders"], [], 0, 45, "Dumbbells"),
|
| 35 |
+
("Tricep Dips", ["Triceps"], ["Shoulder"], 0, 28, "Bodyweight"),
|
| 36 |
+
("Tricep Cable Pushdown", ["Triceps"], [], 0, 45, "Machine")
|
| 37 |
+
],
|
| 38 |
+
"Pull": [
|
| 39 |
+
("Pull-ups", ["Back"], ["Shoulder"], 0, 28, "Bodyweight"), # Hard for heavy users
|
| 40 |
+
("Lat Pulldowns", ["Back"], [], 0, 50, "Machine"),
|
| 41 |
+
("Barbell Row", ["Back"], ["Back"], 0, 30, "Barbell"),
|
| 42 |
+
("Chest Supported Row", ["Back"], [], 0, 45, "Machine"), # Back safe
|
| 43 |
+
("Single Arm Dumbbell Row", ["Back"], [], 0, 40, "Dumbbells"),
|
| 44 |
+
("Face Pulls", ["Rear Delts"], [], 0, 50, "Machine"),
|
| 45 |
+
("Bicep Curls", ["Biceps"], [], 0, 50, "Dumbbells")
|
| 46 |
+
],
|
| 47 |
+
"Core": [
|
| 48 |
+
("Plank", ["Abs"], [], 0, 40, "Bodyweight"),
|
| 49 |
+
("Hanging Leg Raises", ["Abs"], ["Shoulder"], 0, 28, "Barbell"),
|
| 50 |
+
("Dead Bug", ["Abs"], [], 0, 50, "Bodyweight"), # Back safe
|
| 51 |
+
("Russian Twists", ["Abs"], ["Back"], 0, 35, "Bodyweight"),
|
| 52 |
+
("Bird-Dog", ["Abs"], [], 0, 60, "Bodyweight")
|
| 53 |
+
],
|
| 54 |
+
"Cardio": [
|
| 55 |
+
("Sprints", ["Cardio"], ["Knee", "Back", "Ankle"], 0, 28, "Bodyweight"),
|
| 56 |
+
("Treadmill Jog", ["Cardio"], ["Knee", "Ankle"], 0, 32, "Machine"),
|
| 57 |
+
("Elliptical", ["Cardio"], [], 0, 50, "Machine"), # Low impact
|
| 58 |
+
("Stationary Bike", ["Cardio"], [], 0, 60, "Machine"), # Very safe
|
| 59 |
+
("Swimming", ["Cardio"], [], 0, 60, "Pool"),
|
| 60 |
+
("Battle Ropes", ["Cardio"], ["Shoulder"], 0, 40, "Gym"),
|
| 61 |
+
("Burpees", ["Cardio"], ["Back", "Knee", "Shoulder"], 0, 28, "Bodyweight")
|
| 62 |
+
]
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
# --- 3. SMART LOGIC FUNCTIONS ---
|
| 66 |
+
|
| 67 |
+
def calculate_bmi(weight, height_cm):
|
| 68 |
+
height_m = height_cm / 100
|
| 69 |
+
return weight / (height_m ** 2)
|
| 70 |
+
|
| 71 |
+
def filter_exercises(category, injury, age, bmi, equipment):
|
| 72 |
+
"""
|
| 73 |
+
Selects valid exercises based on constraints.
|
| 74 |
+
Returns a random selection to ensure variety every time.
|
| 75 |
+
"""
|
| 76 |
+
valid = []
|
| 77 |
|
| 78 |
+
# Map user equipment choice to database keys
|
| 79 |
+
equip_map = []
|
| 80 |
+
if equipment == "Bodyweight Only": equip_map = ["Bodyweight"]
|
| 81 |
+
elif equipment == "Home Dumbbells": equip_map = ["Bodyweight", "Dumbbells"]
|
| 82 |
+
elif equipment == "Gym Membership": equip_map = ["Bodyweight", "Dumbbells", "Barbell", "Machine", "Rack", "Gym"]
|
| 83 |
+
else: equip_map = ["Bodyweight", "Dumbbells", "Barbell", "Rack"] # Full Home Gym
|
| 84 |
+
|
| 85 |
+
for name, targets, bad_for, min_age_limit, max_bmi_limit, req_equip in exercise_db[category]:
|
| 86 |
+
# 1. Injury Filter
|
| 87 |
+
if injury in bad_for: continue
|
| 88 |
+
# 2. Age Filter (e.g., Box squats for seniors)
|
| 89 |
+
if age > 60 and min_age_limit > 0 and age < min_age_limit: continue
|
| 90 |
+
# 3. BMI Filter (No burpees for obese users)
|
| 91 |
+
if bmi > max_bmi_limit: continue
|
| 92 |
+
# 4. Equipment Filter
|
| 93 |
+
if req_equip not in equip_map: continue
|
| 94 |
+
|
| 95 |
+
valid.append(name)
|
| 96 |
|
| 97 |
+
# If list is empty (strict constraints), give a generic fallback
|
| 98 |
+
if not valid: return [f"Standard {category} Movement (Low Impact)"]
|
|
|
|
|
|
|
| 99 |
|
| 100 |
+
# Return 2-3 random exercises for variety
|
| 101 |
+
count = 3 if len(valid) >= 3 else len(valid)
|
| 102 |
+
return random.sample(valid, count)
|
| 103 |
+
|
| 104 |
+
def generate_finisher(goal, injury, equipment):
|
| 105 |
+
"""
|
| 106 |
+
Generates a specialized finisher: Foam Rolling, Stretching, or Burnout.
|
| 107 |
+
"""
|
| 108 |
+
options = []
|
| 109 |
|
| 110 |
+
# Option A: Foam Rolling (Recovery)
|
| 111 |
+
if injury == "Knee":
|
| 112 |
+
options.append("🌀 FOAM ROLL: Quads & IT Band (2 mins each leg)")
|
| 113 |
+
elif injury == "Back":
|
| 114 |
+
options.append("🌀 FOAM ROLL: Glutes & Hamstrings (Avoid lower back directly!)")
|
| 115 |
+
elif injury == "Shoulder":
|
| 116 |
+
options.append("🌀 LACROSSE BALL: Roll Pecs & Upper Traps")
|
| 117 |
else:
|
| 118 |
+
options.append("🌀 FOAM ROLL: Full body flush (Calves, Quads, Upper Back)")
|
| 119 |
|
| 120 |
+
# Option B: Burnout (Metabolic) - Only if healthy
|
| 121 |
+
if goal in ["Weight Loss", "Athletic Performance"] and injury == "None":
|
| 122 |
+
if equipment == "Bodyweight Only":
|
| 123 |
+
options.append("🔥 BURNOUT: 50 Air Squats for time!")
|
| 124 |
+
else:
|
| 125 |
+
options.append("🔥 BURNOUT: 'Farmer Carry' max distance walking")
|
| 126 |
+
|
| 127 |
+
# Option C: Static Stretch (Flexibility)
|
| 128 |
+
if goal == "General Health" or injury != "None":
|
| 129 |
+
options.append("🧘 STRETCH: Deep Pigeon Pose (3 min hold total)")
|
| 130 |
+
options.append("🧘 STRETCH: Doorway Chest Stretch + Hang from bar")
|
| 131 |
+
|
| 132 |
+
return random.choice(options)
|
| 133 |
+
|
| 134 |
+
# --- 4. MAIN GENERATOR ---
|
| 135 |
+
|
| 136 |
+
def create_full_plan(plan_name, age, gender, weight, height, goal, equipment, injury, experience):
|
| 137 |
+
|
| 138 |
+
# A. Calculate Stats
|
| 139 |
+
bmi = calculate_bmi(weight, height)
|
| 140 |
+
bmi_status = "Normal"
|
| 141 |
+
if bmi > 25: bmi_status = "Overweight"
|
| 142 |
+
if bmi > 30: bmi_status = "Obese (Low Impact Priority)"
|
| 143 |
+
|
| 144 |
+
# B. Define Protocol (Sets/Reps) based on Goal & Age
|
| 145 |
+
warmup_time = "5-7 mins"
|
| 146 |
+
if age > 50: warmup_time = "10-12 mins (Joint Focus)"
|
| 147 |
+
|
| 148 |
+
main_scheme = "3 sets x 12 reps"
|
| 149 |
+
rest = "60s"
|
| 150 |
+
|
| 151 |
if goal == "Muscle Gain":
|
| 152 |
+
main_scheme = "4 sets x 8-10 reps (Slow Eccentric)"
|
| 153 |
+
rest = "90s"
|
|
|
|
| 154 |
elif goal == "Strength":
|
| 155 |
+
main_scheme = "5 sets x 5 reps (Heavy)"
|
| 156 |
+
rest = "3 mins"
|
|
|
|
| 157 |
elif goal == "Weight Loss":
|
| 158 |
+
main_scheme = "3 sets x 15-20 reps (Circuit Style)"
|
| 159 |
+
rest = "30s"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 160 |
|
| 161 |
+
# C. Select Exercises
|
| 162 |
+
legs = filter_exercises("Legs", injury, age, bmi, equipment)
|
| 163 |
+
push = filter_exercises("Push", injury, age, bmi, equipment)
|
| 164 |
+
pull = filter_exercises("Pull", injury, age, bmi, equipment)
|
| 165 |
+
core = filter_exercises("Core", injury, age, bmi, equipment)
|
| 166 |
+
cardio = filter_exercises("Cardio", injury, age, bmi, equipment)
|
| 167 |
|
| 168 |
+
finisher = generate_finisher(goal, injury, equipment)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
|
| 170 |
+
# D. Construct the Text
|
| 171 |
+
plan = f"📋 YOUR AI CUSTOM PLAN: {plan_name}\n"
|
| 172 |
+
plan += f"👤 Profile: {age}y | BMI: {bmi:.1f} ({bmi_status}) | Goal: {goal}\n"
|
| 173 |
+
plan += "---------------------------------------------------\n\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
|
| 175 |
+
plan += f"🌡️ WARM-UP ({warmup_time}):\n"
|
| 176 |
+
plan += "1. Joint Rotations (Neck, Shoulders, Wrists, Ankles)\n"
|
| 177 |
+
if injury != "Knee": plan += "2. Light Jumping Jacks or Skipping (2 mins)\n"
|
| 178 |
+
else: plan += "2. March in Place (High Knees) (2 mins)\n"
|
| 179 |
+
plan += "3. Dynamic Stretch: Arm Swings & Leg Swings\n\n"
|
| 180 |
|
| 181 |
+
plan += f"💪 MAIN WORKOUT (Protocol: {main_scheme} | Rest: {rest}):\n"
|
| 182 |
+
plan += f"1. LEG FOCUS: {legs[0]}\n"
|
| 183 |
+
plan += f"2. PUSH FOCUS: {push[0]}\n"
|
| 184 |
+
plan += f"3. PULL FOCUS: {pull[0]}\n"
|
| 185 |
+
if len(legs) > 1: plan += f"4. SECONDARY LEGS: {legs[1]}\n"
|
| 186 |
+
if len(push) > 1: plan += f"5. SECONDARY UPPER: {push[1]}\n"
|
| 187 |
|
| 188 |
+
plan += "\n🛡️ CORE & STABILITY:\n"
|
| 189 |
+
plan += f"1. {core[0]}: 3 sets\n"
|
| 190 |
+
if len(core) > 1: plan += f"2. {core[1]}: 3 sets\n"
|
| 191 |
|
| 192 |
+
plan += f"\n🏁 THE FINISHER (One Click Bonus):\n{finisher}\n"
|
|
|
|
| 193 |
|
| 194 |
+
return plan
|
| 195 |
|
| 196 |
+
# 5. GRADIO WRAPPER
|
| 197 |
+
def predict_wrapper(age, gender, weight, height, goal, equipment, injury, experience):
|
| 198 |
+
# 1. AI Logic (The CSV Model)
|
| 199 |
+
input_df = pd.DataFrame({
|
| 200 |
'Age': [age], 'Gender': [gender], 'Weight_kg': [weight],
|
| 201 |
'Height_cm': [height], 'Goal': [goal], 'Equipment': [equipment],
|
| 202 |
'Injury': [injury], 'Experience': [experience]
|
| 203 |
})
|
| 204 |
+
plan_category = model.predict(input_df)[0]
|
| 205 |
|
| 206 |
+
# 2. Rule Logic (The Python Generator)
|
| 207 |
+
detailed_plan = create_full_plan(plan_category, age, gender, weight, height, goal, equipment, injury, experience)
|
| 208 |
|
| 209 |
+
# 3. Strategy Note
|
| 210 |
+
note = f"🧠 AI Logic: Model detected '{plan_category}'. We adjusted volume for {goal} and removed dangerous exercises for {injury}."
|
| 211 |
|
| 212 |
+
return detailed_plan, note
|
| 213 |
|
| 214 |
+
# 6. UI LAUNCH
|
| 215 |
iface = gr.Interface(
|
| 216 |
+
fn=predict_wrapper,
|
| 217 |
inputs=[
|
| 218 |
gr.Slider(18, 80, value=25, label="Age"),
|
| 219 |
gr.Radio(["Male", "Female"], label="Gender", value="Male"),
|
| 220 |
gr.Number(label="Weight (kg)", value=75),
|
| 221 |
gr.Number(label="Height (cm)", value=175),
|
| 222 |
+
gr.Dropdown(['Weight Loss', 'Muscle Gain', 'Endurance', 'General Health', 'Strength'], label="Goal", value="General Health"),
|
| 223 |
gr.Dropdown(['Gym Membership', 'Home Dumbbells', 'Bodyweight Only', 'Full Home Gym (Rack+Barbell)'], label="Equipment", value="Gym Membership"),
|
| 224 |
gr.Dropdown(['None', 'Knee', 'Back', 'Shoulder', 'Ankle'], label="Injury", value="None"),
|
| 225 |
gr.Radio(['Beginner', 'Intermediate', 'Advanced'], label="Experience", value="Intermediate")
|
| 226 |
],
|
| 227 |
outputs=[
|
| 228 |
+
gr.Textbox(label="Your Ultimate Plan", lines=25),
|
| 229 |
+
gr.Textbox(label="Behind the Scenes")
|
| 230 |
],
|
| 231 |
+
title="SmartFit AI Ultimate ⚡",
|
| 232 |
+
description="One-Click Personalized Workout Generator. Adapts to BMI, Injuries, and Equipment instantly.",
|
| 233 |
theme="soft"
|
| 234 |
)
|
| 235 |
|