Tomertg commited on
Commit
d34c2ef
·
verified ·
1 Parent(s): 0d5a2b5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +106 -118
app.py CHANGED
@@ -2,22 +2,38 @@ import gradio as gr
2
  import joblib
3
  import pandas as pd
4
  import random
5
-
6
- # 1. Load Model
7
- # loading the specific file name you uploaded
8
- model = joblib.load('fitness_model (1).joblib')
9
-
10
- # ==========================================
11
- # CONFIG DICTIONARIES
12
- # ==========================================
13
-
 
 
 
 
 
 
 
 
 
 
14
  GOAL_CONFIG = {
15
  "Strength": {"sets": 5, "reps": "3-5", "rest": "3 min", "intensity": "Heavy"},
16
  "Muscle Gain": {"sets": 3, "reps": "8-12", "rest": "90 sec", "intensity": "Moderate"},
17
  "Weight Loss": {"sets": 4, "reps": "15-20", "rest": "45 sec", "intensity": "High Tempo"},
18
  "Endurance": {"sets": 2, "reps": "20-25", "rest": "30 sec", "intensity": "Light"},
19
  "General Health": {"sets": 3, "reps": "12-15", "rest": "60 sec", "intensity": "Moderate"},
20
- "Athletic Performance": {"sets": 4, "reps": "6-10", "rest": "2 min", "intensity": "Explosive"}
 
 
 
 
 
 
21
  }
22
 
23
  LEVEL_CONFIG = {
@@ -26,92 +42,65 @@ LEVEL_CONFIG = {
26
  "Advanced": {"tier": 2}
27
  }
28
 
 
29
  EXERCISE_DB = {
30
  "Chest": [
31
  {"name": "Barbell Bench Press", "equip": ["Barbell", "Gym"], "bad": ["Shoulder"], "level": 1, "ratio": 0.9},
32
  {"name": "Dumbbell Chest Press", "equip": ["Dumbbells", "Gym"], "bad": [], "level": 0, "ratio": 0.35},
33
- {"name": "Incline Dumbbell Press", "equip": ["Dumbbells", "Gym"], "bad": ["Shoulder"], "level": 1, "ratio": 0.3},
34
- {"name": "Machine Chest Press", "equip": ["Gym"], "bad": [], "level": 0, "ratio": 0.6},
35
  {"name": "Push-ups", "equip": ["Bodyweight"], "bad": ["Wrist"], "level": 0, "ratio": 0},
36
- {"name": "Cable Flys", "equip": ["Gym"], "bad": [], "level": 1, "ratio": 0.15},
37
- {"name": "Dumbbell Flys", "equip": ["Dumbbells"], "bad": ["Shoulder"], "level": 0, "ratio": 0.12},
38
- {"name": "Weighted Dips", "equip": ["Gym"], "bad": ["Shoulder"], "level": 2, "ratio": 0},
39
  ],
40
  "Back": [
41
  {"name": "Deadlift", "equip": ["Barbell", "Gym"], "bad": ["Back"], "level": 2, "ratio": 1.4},
42
  {"name": "Lat Pulldown", "equip": ["Gym"], "bad": [], "level": 0, "ratio": 0.6},
43
- {"name": "Seated Cable Row", "equip": ["Gym"], "bad": ["Back"], "level": 0, "ratio": 0.6},
44
- {"name": "Barbell Bent Over Row", "equip": ["Barbell", "Gym"], "bad": ["Back"], "level": 1, "ratio": 0.7},
45
- {"name": "Single Arm Dumbbell Row", "equip": ["Dumbbells", "Gym"], "bad": [], "level": 0, "ratio": 0.3},
46
  {"name": "Pull-ups", "equip": ["Bodyweight", "Gym"], "bad": ["Shoulder"], "level": 1, "ratio": 0},
47
- {"name": "Chest Supported Row", "equip": ["Gym"], "bad": [], "level": 0, "ratio": 0.5},
48
- {"name": "Inverted Row", "equip": ["Bodyweight"], "bad": [], "level": 0, "ratio": 0},
49
  ],
50
  "Legs": [
51
  {"name": "Barbell Squat", "equip": ["Barbell", "Gym"], "bad": ["Back", "Knee"], "level": 2, "ratio": 1.1},
52
  {"name": "Leg Press", "equip": ["Gym"], "bad": [], "level": 0, "ratio": 1.8},
53
  {"name": "Goblet Squat", "equip": ["Dumbbells", "Gym"], "bad": ["Knee"], "level": 0, "ratio": 0.4},
54
- {"name": "Walking Lunges", "equip": ["Dumbbells", "Bodyweight"], "bad": ["Knee"], "level": 1, "ratio": 0.15},
55
- {"name": "Romanian Deadlift", "equip": ["Barbell", "Dumbbells"], "bad": ["Back"], "level": 1, "ratio": 0.8},
56
- {"name": "Lying Leg Curl", "equip": ["Gym"], "bad": [], "level": 0, "ratio": 0.35},
57
- {"name": "Leg Extensions", "equip": ["Gym"], "bad": ["Knee"], "level": 0, "ratio": 0.35},
58
- {"name": "Bulgarian Split Squat", "equip": ["Dumbbells"], "bad": ["Knee"], "level": 2, "ratio": 0.2},
59
- {"name": "Glute Bridges", "equip": ["Bodyweight"], "bad": [], "level": 0, "ratio": 0},
60
  ],
61
  "Shoulders": [
62
- {"name": "Overhead Barbell Press", "equip": ["Barbell", "Gym"], "bad": ["Shoulder", "Back"], "level": 2, "ratio": 0.5},
63
- {"name": "Seated Dumbbell Press", "equip": ["Dumbbells", "Gym"], "bad": ["Shoulder"], "level": 0, "ratio": 0.25},
64
  {"name": "Lateral Raises", "equip": ["Dumbbells", "Gym"], "bad": [], "level": 0, "ratio": 0.08},
65
- {"name": "Face Pulls", "equip": ["Gym"], "bad": [], "level": 0, "ratio": 0.2},
66
- {"name": "Front Raises", "equip": ["Dumbbells"], "bad": [], "level": 0, "ratio": 0.08},
67
- ],
68
- "Arms": [
69
- {"name": "Barbell Curls", "equip": ["Barbell", "Gym"], "bad": ["Wrist"], "level": 0, "ratio": 0.25},
70
- {"name": "Dumbbell Hammer Curls", "equip": ["Dumbbells", "Gym"], "bad": [], "level": 0, "ratio": 0.12},
71
- {"name": "Tricep Rope Pushdown", "equip": ["Gym"], "bad": [], "level": 0, "ratio": 0.25},
72
- {"name": "Skullcrushers", "equip": ["Barbell", "Dumbbells"], "bad": ["Elbow"], "level": 1, "ratio": 0.2},
73
- {"name": "Dips", "equip": ["Bodyweight"], "bad": ["Shoulder"], "level": 1, "ratio": 0},
74
  ],
75
  "Core": [
76
  {"name": "Plank", "equip": ["Bodyweight"], "bad": [], "level": 0, "ratio": 0},
77
- {"name": "Cable Woodchoppers", "equip": ["Gym"], "bad": ["Back"], "level": 1, "ratio": 0.3},
78
- {"name": "Russian Twists", "equip": ["Bodyweight"], "bad": ["Back"], "level": 0, "ratio": 0},
79
  {"name": "Hanging Leg Raises", "equip": ["Gym"], "bad": ["Shoulder"], "level": 2, "ratio": 0},
 
 
 
 
 
 
80
  ],
81
  "Cardio": [
82
- {"name": "Treadmill Run", "equip": ["Gym"], "bad": ["Knee"], "level": 0, "ratio": 0},
83
- {"name": "Elliptical", "equip": ["Gym"], "bad": [], "level": 0, "ratio": 0},
84
- {"name": "Burpees", "equip": ["Bodyweight"], "bad": ["Back", "Knee"], "level": 2, "ratio": 0},
85
- {"name": "Jump Rope", "equip": ["Bodyweight"], "bad": ["Knee", "Ankle"], "level": 1, "ratio": 0},
86
  ]
87
  }
88
 
89
- # ==========================================
90
  # LOGIC ENGINE
91
- # ==========================================
92
-
93
  def calculate_weight(base_ratio, user_weight, gender, level_tier, muscle_group):
94
- if base_ratio == 0: return "Bodyweight"
95
-
96
  load = user_weight * base_ratio
97
-
98
  # Gender Logic
99
  if gender == "Female":
100
- if muscle_group in ["Legs", "Core"]:
101
- load *= 0.75
102
- else:
103
- load *= 0.55
104
-
105
  # Level Logic
106
  if level_tier == 0: load *= 0.6
107
  if level_tier == 2: load *= 1.3
108
-
109
- # Rounding
110
- if load < 10:
111
- final_load = round(load)
112
- else:
113
- final_load = 2.5 * round(load / 2.5)
114
-
115
  return f"{int(final_load)} kg"
116
 
117
  def get_exercises(muscle, equipment, injury, level_tier, count=1):
@@ -119,95 +108,105 @@ def get_exercises(muscle, equipment, injury, level_tier, count=1):
119
  if equipment == "Gym Membership": my_gear = ["Gym", "Barbell", "Dumbbells", "Bodyweight"]
120
  elif equipment == "Full Home Gym (Rack+Barbell)": my_gear = ["Barbell", "Dumbbells", "Bodyweight"]
121
  elif equipment == "Home Dumbbells": my_gear = ["Dumbbells", "Bodyweight"]
122
- else: my_gear = ["Bodyweight"]
123
 
124
  pool = EXERCISE_DB.get(muscle, [])
125
  valid = []
126
-
127
  for ex in pool:
 
128
  if not any(g in my_gear for g in ex["equip"]): continue
 
129
  if injury in ex["bad"]: continue
 
130
  if level_tier < ex["level"]: continue
131
  valid.append(ex)
132
-
133
  random.shuffle(valid)
134
-
135
- if not valid: return [{"name": f"Standard {muscle} Move", "ratio": 0}]
136
  return valid[:count]
137
 
138
  def generate_routine(plan_name, age, gender, weight, goal, equipment, injury, experience):
139
-
140
  goal_settings = GOAL_CONFIG.get(goal, GOAL_CONFIG["General Health"])
141
  level_tier = LEVEL_CONFIG.get(experience, {"tier": 1})["tier"]
142
-
143
- slots = []
144
- if "Upper" in plan_name or "Push" in plan_name:
145
- slots = ["Chest", "Back", "Shoulders", "Arms", "Core"]
146
- title = "Upper Body Focus"
 
 
 
 
 
 
 
 
 
 
 
147
  elif "Lower" in plan_name or "Legs" in plan_name:
148
- slots = ["Legs", "Legs", "Legs", "Core", "Cardio"]
149
- title = "Lower Body Focus"
150
  else:
 
151
  slots = ["Legs", "Chest", "Back", "Shoulders", "Core"]
152
  title = "Full Body Mix"
153
 
154
- text = f"WORKOUT PLAN: {title}\n"
 
 
155
  text += f"User: {age}y | {gender} | {weight}kg | {experience}\n"
156
- text += f"Goal: {goal} | Equip: {equipment}\n"
157
  text += "="*40 + "\n\n"
158
-
159
- text += f"WARM-UP (5-8 mins):\n"
160
- if injury == "Knee": text += "- Arm Circles & Torso Twists\n- Glute Bridges\n\n"
161
- else: text += "- Jumping Jacks\n- Dynamic Stretching\n\n"
162
-
163
- text += f"MAIN WORKOUT:\n"
164
- text += f"Sets: {goal_settings['sets']} | Reps: {goal_settings['reps']} | Rest: {goal_settings['rest']}\n\n"
165
-
166
  used_names = []
167
-
168
  for i, muscle in enumerate(slots):
169
  candidates = get_exercises(muscle, equipment, injury, level_tier, count=3)
170
  selected = candidates[0]
 
171
  for cand in candidates:
172
  if cand['name'] not in used_names:
173
  selected = cand
174
  break
175
  used_names.append(selected['name'])
176
-
177
  load = calculate_weight(selected['ratio'], weight, gender, level_tier, muscle)
178
 
179
  text += f"{i+1}. {selected['name']} ({muscle})\n"
180
- text += f" Rec. Load: {load}\n\n"
181
-
182
- text += f"FINISHER:\n"
183
- if goal in ["Weight Loss", "Endurance"]:
184
- text += "HIIT: 30s Work / 30s Rest (5 Rounds)"
185
- else:
186
- text += "Core Stability: 3 Sets to Failure"
187
 
188
  return text
189
 
190
- # ==========================================
191
  # MAIN PREDICTOR
192
- # ==========================================
193
 
194
  def predict_wrapper(age, gender, weight, height, goal, equipment, injury, experience):
195
  input_df = pd.DataFrame({
196
- 'Age': [age], 'Gender': [gender], 'Weight_kg': [weight],
197
- 'Height_cm': [height], 'Goal': [goal], 'Equipment': [equipment],
198
  'Injury': [injury], 'Experience': [experience]
199
  })
200
-
201
- # Use the trained Random Forest model
202
  plan_name = model.predict(input_df)[0]
203
 
 
204
  routine = generate_routine(plan_name, age, gender, weight, goal, equipment, injury, experience)
205
 
206
- return routine, f"AI Strategy: {plan_name}"
207
 
208
- # ==========================================
209
  # UI LAUNCH (GRADIO)
210
- # ==========================================
 
 
211
 
212
  iface = gr.Interface(
213
  fn=predict_wrapper,
@@ -216,27 +215,16 @@ iface = gr.Interface(
216
  gr.Radio(["Male", "Female"], label="Gender", value="Male"),
217
  gr.Number(label="Weight (kg)", value=75),
218
  gr.Number(label="Height (cm)", value=175),
219
- gr.Dropdown(list(GOAL_CONFIG.keys()), label="Goal", value="Muscle Gain"),
220
- gr.Dropdown(['Gym Membership', 'Home Dumbbells', 'Bodyweight Only', 'Full Home Gym (Rack+Barbell)'], label="Equipment", value="Gym Membership"),
221
  gr.Dropdown(['None', 'Knee', 'Back', 'Shoulder', 'Ankle'], label="Injury", value="None"),
222
  gr.Dropdown(list(LEVEL_CONFIG.keys()), label="Experience", value="Intermediate")
223
  ],
224
  outputs=[
225
- gr.Textbox(label="Generated Workout", lines=20),
226
- gr.Textbox(label="AI Note")
227
- ],
228
- title="SmartFit AI - Biological Engine",
229
- description="Advanced generator with gender-specific strength standards.",
230
- examples=[
231
- # Example 1: The Bodybuilder (Young Male, Gym, No Injury)
232
- [24, "Male", 80, 180, "Muscle Gain", "Gym Membership", "None", "Advanced"],
233
-
234
- # Example 2: The Rehab/Home User (Female, Knee Injury, Home)
235
- [35, "Female", 65, 165, "Weight Loss", "Home Dumbbells", "Knee", "Beginner"],
236
-
237
- # Example 3: The Senior Health (Older Male, Bodyweight, Back safe)
238
- [60, "Male", 85, 175, "General Health", "Bodyweight Only", "Back", "Beginner"]
239
  ],
 
 
240
  theme="soft"
241
  )
242
 
 
2
  import joblib
3
  import pandas as pd
4
  import random
5
+ import os
6
+
7
+ # 1. Load Model with the CORRECT filename
8
+ # We check if the file exists just to be safe
9
+ model_filename = 'fitness_model (2).joblib'
10
+
11
+ if os.path.exists(model_filename):
12
+ model = joblib.load(model_filename)
13
+ print(f"Successfully loaded: {model_filename}")
14
+ else:
15
+ # Fallback in case the name changed during upload
16
+ try:
17
+ model = joblib.load('fitness_model.joblib')
18
+ print("Loaded standard 'fitness_model.joblib' instead.")
19
+ except:
20
+ raise FileNotFoundError(f"Could not find {model_filename} or fitness_model.joblib")
21
+
22
+ # CONFIG DICTIONARIES (UPDATED)
23
+ # Added new goals from the dataset
24
  GOAL_CONFIG = {
25
  "Strength": {"sets": 5, "reps": "3-5", "rest": "3 min", "intensity": "Heavy"},
26
  "Muscle Gain": {"sets": 3, "reps": "8-12", "rest": "90 sec", "intensity": "Moderate"},
27
  "Weight Loss": {"sets": 4, "reps": "15-20", "rest": "45 sec", "intensity": "High Tempo"},
28
  "Endurance": {"sets": 2, "reps": "20-25", "rest": "30 sec", "intensity": "Light"},
29
  "General Health": {"sets": 3, "reps": "12-15", "rest": "60 sec", "intensity": "Moderate"},
30
+ "Athletic Performance": {"sets": 4, "reps": "6-10", "rest": "2 min", "intensity": "Explosive"},
31
+ # NEW GOALS
32
+ "Flexibility": {"sets": 2, "reps": "Hold 30s", "rest": "None", "intensity": "Low Impact"},
33
+ "Tone Up": {"sets": 3, "reps": "15-20", "rest": "45 sec", "intensity": "Burnout"},
34
+ "Powerlifting": {"sets": 5, "reps": "1-3", "rest": "3-5 min", "intensity": "Max Effort"},
35
+ "CrossFit": {"sets": "AMRAP", "reps": "High", "rest": "Minimal", "intensity": "Very High"},
36
+ "Marathon Training": {"sets": "Distance", "reps": "Km", "rest": "Pacing", "intensity": "Steady State"}
37
  }
38
 
39
  LEVEL_CONFIG = {
 
42
  "Advanced": {"tier": 2}
43
  }
44
 
45
+ # Expanded Exercise Database
46
  EXERCISE_DB = {
47
  "Chest": [
48
  {"name": "Barbell Bench Press", "equip": ["Barbell", "Gym"], "bad": ["Shoulder"], "level": 1, "ratio": 0.9},
49
  {"name": "Dumbbell Chest Press", "equip": ["Dumbbells", "Gym"], "bad": [], "level": 0, "ratio": 0.35},
 
 
50
  {"name": "Push-ups", "equip": ["Bodyweight"], "bad": ["Wrist"], "level": 0, "ratio": 0},
51
+ {"name": "Burpees", "equip": ["Bodyweight"], "bad": ["Knee"], "level": 1, "ratio": 0},
 
 
52
  ],
53
  "Back": [
54
  {"name": "Deadlift", "equip": ["Barbell", "Gym"], "bad": ["Back"], "level": 2, "ratio": 1.4},
55
  {"name": "Lat Pulldown", "equip": ["Gym"], "bad": [], "level": 0, "ratio": 0.6},
56
+ {"name": "Dumbbell Row", "equip": ["Dumbbells", "Gym"], "bad": [], "level": 0, "ratio": 0.3},
 
 
57
  {"name": "Pull-ups", "equip": ["Bodyweight", "Gym"], "bad": ["Shoulder"], "level": 1, "ratio": 0},
 
 
58
  ],
59
  "Legs": [
60
  {"name": "Barbell Squat", "equip": ["Barbell", "Gym"], "bad": ["Back", "Knee"], "level": 2, "ratio": 1.1},
61
  {"name": "Leg Press", "equip": ["Gym"], "bad": [], "level": 0, "ratio": 1.8},
62
  {"name": "Goblet Squat", "equip": ["Dumbbells", "Gym"], "bad": ["Knee"], "level": 0, "ratio": 0.4},
63
+ {"name": "Box Jumps", "equip": ["Bodyweight", "Gym"], "bad": ["Knee", "Ankle"], "level": 1, "ratio": 0},
64
+ {"name": "Lunges", "equip": ["Dumbbells", "Bodyweight"], "bad": ["Knee"], "level": 0, "ratio": 0.2},
 
 
 
 
65
  ],
66
  "Shoulders": [
67
+ {"name": "Overhead Press", "equip": ["Barbell", "Gym"], "bad": ["Shoulder", "Back"], "level": 2, "ratio": 0.5},
 
68
  {"name": "Lateral Raises", "equip": ["Dumbbells", "Gym"], "bad": [], "level": 0, "ratio": 0.08},
69
+ {"name": "Handstand Pushups", "equip": ["Bodyweight"], "bad": ["Shoulder", "Wrist"], "level": 2, "ratio": 0},
 
 
 
 
 
 
 
 
70
  ],
71
  "Core": [
72
  {"name": "Plank", "equip": ["Bodyweight"], "bad": [], "level": 0, "ratio": 0},
 
 
73
  {"name": "Hanging Leg Raises", "equip": ["Gym"], "bad": ["Shoulder"], "level": 2, "ratio": 0},
74
+ {"name": "Crunches", "equip": ["Bodyweight"], "bad": ["Back"], "level": 0, "ratio": 0},
75
+ ],
76
+ "Mobility": [
77
+ {"name": "Downward Dog", "equip": ["Bodyweight", "Yoga Mat"], "bad": ["Wrist"], "level": 0, "ratio": 0},
78
+ {"name": "Cat-Cow Stretch", "equip": ["Bodyweight"], "bad": [], "level": 0, "ratio": 0},
79
+ {"name": "Pigeon Pose", "equip": ["Bodyweight"], "bad": ["Knee"], "level": 1, "ratio": 0},
80
  ],
81
  "Cardio": [
82
+ {"name": "5km Run", "equip": ["Bodyweight", "Gym"], "bad": ["Knee"], "level": 1, "ratio": 0},
83
+ {"name": "Rowing Machine", "equip": ["Gym"], "bad": ["Back"], "level": 0, "ratio": 0},
84
+ {"name": "Cycling", "equip": ["Gym", "Stationary"], "bad": [], "level": 0, "ratio": 0},
 
85
  ]
86
  }
87
 
 
88
  # LOGIC ENGINE
 
 
89
  def calculate_weight(base_ratio, user_weight, gender, level_tier, muscle_group):
90
+ if base_ratio == 0: return "Bodyweight / NA"
91
+
92
  load = user_weight * base_ratio
93
+
94
  # Gender Logic
95
  if gender == "Female":
96
+ if muscle_group in ["Legs", "Core"]: load *= 0.75
97
+ else: load *= 0.55
98
+
 
 
99
  # Level Logic
100
  if level_tier == 0: load *= 0.6
101
  if level_tier == 2: load *= 1.3
102
+
103
+ final_load = round(load / 2.5) * 2.5 if load > 10 else round(load)
 
 
 
 
 
104
  return f"{int(final_load)} kg"
105
 
106
  def get_exercises(muscle, equipment, injury, level_tier, count=1):
 
108
  if equipment == "Gym Membership": my_gear = ["Gym", "Barbell", "Dumbbells", "Bodyweight"]
109
  elif equipment == "Full Home Gym (Rack+Barbell)": my_gear = ["Barbell", "Dumbbells", "Bodyweight"]
110
  elif equipment == "Home Dumbbells": my_gear = ["Dumbbells", "Bodyweight"]
111
+ else: my_gear = ["Bodyweight", "Yoga Mat"]
112
 
113
  pool = EXERCISE_DB.get(muscle, [])
114
  valid = []
115
+
116
  for ex in pool:
117
+ # Check gear
118
  if not any(g in my_gear for g in ex["equip"]): continue
119
+ # Check injury
120
  if injury in ex["bad"]: continue
121
+ # Check level
122
  if level_tier < ex["level"]: continue
123
  valid.append(ex)
124
+
125
  random.shuffle(valid)
126
+ if not valid: return [{"name": f"Generic {muscle} Move", "ratio": 0}]
 
127
  return valid[:count]
128
 
129
  def generate_routine(plan_name, age, gender, weight, goal, equipment, injury, experience):
130
+
131
  goal_settings = GOAL_CONFIG.get(goal, GOAL_CONFIG["General Health"])
132
  level_tier = LEVEL_CONFIG.get(experience, {"tier": 1})["tier"]
133
+
134
+ # PLAN LOGIC SELECTOR
135
+ # We map the AI's predicted plan name to a structure of muscles to work
136
+
137
+ if "Yoga" in plan_name:
138
+ slots = ["Mobility", "Mobility", "Core", "Mobility", "Core"]
139
+ title = "Yoga & Mobility Flow"
140
+ elif "Running" in plan_name or "Marathon" in plan_name:
141
+ slots = ["Cardio", "Legs", "Core", "Mobility"]
142
+ title = "Endurance Run & Core"
143
+ elif "CrossFit" in plan_name or "WOD" in plan_name:
144
+ slots = ["Legs", "Chest", "Cardio", "Shoulders", "Core"]
145
+ title = "Metabolic Conditioning (WOD)"
146
+ elif "Upper" in plan_name or "Push" in plan_name:
147
+ slots = ["Chest", "Back", "Shoulders", "Core"]
148
+ title = "Upper Body Strength"
149
  elif "Lower" in plan_name or "Legs" in plan_name:
150
+ slots = ["Legs", "Legs", "Core", "Cardio"]
151
+ title = "Lower Body Power"
152
  else:
153
+ # Default Full Body
154
  slots = ["Legs", "Chest", "Back", "Shoulders", "Core"]
155
  title = "Full Body Mix"
156
 
157
+ # --- TEXT GENERATION ---
158
+ text = f"AI PLAN: {title}\n"
159
+ text += f"Strategy: {plan_name}\n"
160
  text += f"User: {age}y | {gender} | {weight}kg | {experience}\n"
 
161
  text += "="*40 + "\n\n"
162
+
163
+ text += f"PROTOCOL:\n"
164
+ text += f"Sets: {goal_settings['sets']} | Reps: {goal_settings['reps']}\n"
165
+ text += f"Intensity: {goal_settings['intensity']} | Rest: {goal_settings['rest']}\n\n"
166
+
167
+ text += f"WORKOUT:\n"
 
 
168
  used_names = []
169
+
170
  for i, muscle in enumerate(slots):
171
  candidates = get_exercises(muscle, equipment, injury, level_tier, count=3)
172
  selected = candidates[0]
173
+ # Avoid duplicates
174
  for cand in candidates:
175
  if cand['name'] not in used_names:
176
  selected = cand
177
  break
178
  used_names.append(selected['name'])
179
+
180
  load = calculate_weight(selected['ratio'], weight, gender, level_tier, muscle)
181
 
182
  text += f"{i+1}. {selected['name']} ({muscle})\n"
183
+ if load != "Bodyweight / NA":
184
+ text += f" Target Load: {load}\n"
185
+ text += "\n"
 
 
 
 
186
 
187
  return text
188
 
 
189
  # MAIN PREDICTOR
 
190
 
191
  def predict_wrapper(age, gender, weight, height, goal, equipment, injury, experience):
192
  input_df = pd.DataFrame({
193
+ 'Age': [age], 'Gender': [gender], 'Weight_kg': [weight],
194
+ 'Height_cm': [height], 'Goal': [goal], 'Equipment': [equipment],
195
  'Injury': [injury], 'Experience': [experience]
196
  })
197
+
198
+ # Predict using the NEW model (trained on 10k rows)
199
  plan_name = model.predict(input_df)[0]
200
 
201
+ # Generate the readable text routine
202
  routine = generate_routine(plan_name, age, gender, weight, goal, equipment, injury, experience)
203
 
204
+ return routine
205
 
 
206
  # UI LAUNCH (GRADIO)
207
+
208
+ goal_options = list(GOAL_CONFIG.keys()) # Auto-update from config
209
+ equip_options = ['Gym Membership', 'Home Dumbbells', 'Bodyweight Only', 'Full Home Gym (Rack+Barbell)', 'Yoga Mat & Bands']
210
 
211
  iface = gr.Interface(
212
  fn=predict_wrapper,
 
215
  gr.Radio(["Male", "Female"], label="Gender", value="Male"),
216
  gr.Number(label="Weight (kg)", value=75),
217
  gr.Number(label="Height (cm)", value=175),
218
+ gr.Dropdown(goal_options, label="Goal", value="Muscle Gain"),
219
+ gr.Dropdown(equip_options, label="Equipment", value="Gym Membership"),
220
  gr.Dropdown(['None', 'Knee', 'Back', 'Shoulder', 'Ankle'], label="Injury", value="None"),
221
  gr.Dropdown(list(LEVEL_CONFIG.keys()), label="Experience", value="Intermediate")
222
  ],
223
  outputs=[
224
+ gr.Textbox(label="AI Personalized Workout", lines=18)
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  ],
226
+ title="SmartFit AI 2.0 - Hyper-Personalized Engine",
227
+ description="Now supporting CrossFit, Yoga, Marathon Training, and Rehab protocols.",
228
  theme="soft"
229
  )
230