Rahaf2001 commited on
Commit
bd0e7a6
·
verified ·
1 Parent(s): 72a0a8b

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +305 -0
app.py ADDED
@@ -0,0 +1,305 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from typing import List, Literal, Tuple
3
+
4
+ # -------------------------------
5
+ # Helpers: BMI / BMR / TDEE
6
+ # -------------------------------
7
+ def bmi_value(height_cm: float, weight_kg: float) -> float:
8
+ if height_cm <= 0 or weight_kg <= 0:
9
+ return 0.0
10
+ h_m = height_cm / 100.0
11
+ return round(weight_kg / (h_m ** 2), 2)
12
+
13
+ def bmi_category(bmi: float) -> str:
14
+ if bmi == 0:
15
+ return "Invalid inputs"
16
+ if bmi < 18.5: return "Underweight"
17
+ if bmi < 25: return "Normal"
18
+ if bmi < 30: return "Overweight"
19
+ return "Obese"
20
+
21
+ def bmr_mifflin(sex: Literal["male","female"], age: int, height_cm: float, weight_kg: float) -> float:
22
+ # Mifflin-St Jeor
23
+ s = 5 if sex == "male" else -161
24
+ return 10*weight_kg + 6.25*height_cm - 5*age + s
25
+
26
+ ACTIVITY = {
27
+ "Sedentary (office/no exercise)": 1.2,
28
+ "Light (1-3x/wk)": 1.375,
29
+ "Moderate (3-5x/wk)": 1.55,
30
+ "Active (6-7x/wk)": 1.725,
31
+ "Athlete (2x/day)": 1.9,
32
+ }
33
+
34
+ def tdee(sex: str, age: int, height_cm: float, weight_kg: float, activity: str) -> Tuple[float, float, float]:
35
+ base = bmr_mifflin(sex, age, height_cm, weight_kg)
36
+ factor = ACTIVITY.get(activity, 1.2)
37
+ maintenance = round(base * factor)
38
+ cut = maintenance - 500 # خسارة دهون تقريبية
39
+ bulk = maintenance + 300 # زيادة عضل تدريجية
40
+ return maintenance, cut, bulk
41
+
42
+ def water_intake_ml(weight_kg: float) -> int:
43
+ # 30–35 ml لكل كجم
44
+ return int(weight_kg * 35)
45
+
46
+ # -------------------------------
47
+ # Agent 1: BMI & TDEE
48
+ # -------------------------------
49
+ def agent_bmi_tdee(
50
+ sex, age, height_cm, weight_kg, activity, goal
51
+ ):
52
+ bmi = bmi_value(height_cm, weight_kg)
53
+ cat = bmi_category(bmi)
54
+ maint, cut, bulk = tdee(sex, age, height_cm, weight_kg, activity)
55
+ target = {"Lose fat": cut, "Maintain": maint, "Build muscle": bulk}[goal]
56
+ water = water_intake_ml(weight_kg)
57
+
58
+ md = f"""### 📊 BMI & TDEE
59
+ - **BMI:** `{bmi}` → **{cat}**
60
+ - **Maintenance Calories:** **{maint} kcal/day**
61
+ - **Target for goal ({goal}):** **{target} kcal/day**
62
+ - **Water recommendation:** ~ **{water//1000}–{(water//1000)+0} L/day** (≈ {water} ml)
63
+
64
+ > *These are estimates, not medical advice. Adjust by ±100–150 kcal based on weekly progress.*
65
+ """
66
+ return md
67
+
68
+ # -------------------------------
69
+ # Agent 2: Workout Plan Generator
70
+ # -------------------------------
71
+ GOAL_SPLITS = {
72
+ "Lose fat": ["FBW", "FBW", "LISS Cardio", "Mobility"],
73
+ "Maintain": ["Upper", "Lower", "Full Body", "HIIT/Cardio", "Mobility"],
74
+ "Build muscle": ["Push", "Pull", "Legs", "Upper", "Lower", "Mobility"]
75
+ }
76
+
77
+ def session_template(name: str, level: str, equipment: str) -> List[str]:
78
+ # بسيط ومفهوم للمبتدئ
79
+ if name == "FBW":
80
+ return [
81
+ "Goblet Squat 3x8-10",
82
+ "Push-ups (incline if needed) 3x6-10",
83
+ "Dumbbell Row 3x10",
84
+ "Hip Hinge (RDL/Good Morning) 3x10",
85
+ "Plank 3x30-45s",
86
+ ]
87
+ if name == "Upper":
88
+ return [
89
+ "DB Bench Press 3x8-10",
90
+ "One-arm Row 3x10/side",
91
+ "DB Shoulder Press 3x10",
92
+ "Lat Pulldown or Assisted Pull 3x8-10",
93
+ "Facepull / Band Pull-apart 3x12-15",
94
+ ]
95
+ if name == "Lower":
96
+ return [
97
+ "Squat pattern 4x6-10",
98
+ "Hinge pattern 3x8-10",
99
+ "Split Squat/Lunge 3x8/leg",
100
+ "Calf Raise 3x12-15",
101
+ "Core: Deadbug 3x10",
102
+ ]
103
+ if name == "Push": # صدر/كتف/ترايسبس
104
+ return [
105
+ "DB Bench Press 4x6-10",
106
+ "Incline Push-ups 3x10",
107
+ "DB Shoulder Press 3x8-10",
108
+ "Lateral Raise 3x12-15",
109
+ "Triceps Rope/Extensions 3x10-12",
110
+ ]
111
+ if name == "Pull": # ظهر/بايسبس
112
+ return [
113
+ "Lat Pulldown / Assisted Pull-ups 4x6-10",
114
+ "Seated Row / One-arm Row 3x10",
115
+ "Rear Delt Raise 3x12-15",
116
+ "DB Curl 3x10-12",
117
+ "Back Extension 3x12",
118
+ ]
119
+ if name == "Legs":
120
+ return [
121
+ "Back/Front/Goblet Squat 4x6-10",
122
+ "Romanian Deadlift 3x8-10",
123
+ "Leg Press or Step-ups 3x10",
124
+ "Hamstring Curl 3x10-12",
125
+ "Core: Side Plank 3x30s/side",
126
+ ]
127
+ if name == "HIIT/Cardio":
128
+ return ["20–25 min intervals (1 min fast / 1 min easy) OR 30–40 min brisk walk"]
129
+ if name == "LISS Cardio":
130
+ return ["30–45 min easy jog/bike/walk (Zone 2)"]
131
+ if name == "Mobility":
132
+ return ["15–20 min full-body mobility + light stretching and breathing"]
133
+ return ["Rest / Light activity (walk 6–8k steps)"]
134
+
135
+ def agent_workout(level: str, days_per_week: int, goal: str, equipment: str):
136
+ days_per_week = max(2, min(6, int(days_per_week)))
137
+ base = GOAL_SPLITS[goal]
138
+ plan = []
139
+ for i in range(days_per_week):
140
+ name = base[i % len(base)]
141
+ items = session_template(name, level, equipment)
142
+ plan.append((f"Day {i+1} — {name}", items))
143
+
144
+ md = "### 🏋️ Weekly Plan\n"
145
+ for title, items in plan:
146
+ md += f"\n**{title}**\n" + "\n".join([f"- {x}" for x in items]) + "\n"
147
+ md += "\n*Rest between sets: 60–90s. Choose weights that leave ~2 reps in reserve (RIR 2).*"
148
+ return md
149
+
150
+ # -------------------------------
151
+ # Agent 3: Nutrition & Meal Plan
152
+ # -------------------------------
153
+ PROTEIN_PER_KG = 1.6 # g/kg للمبتدئ
154
+ FAT_MIN_G_PER_KG = 0.6
155
+
156
+ def macros_for_calories(weight_kg: float, calories: int) -> Tuple[int,int,int]:
157
+ protein_g = int(round(PROTEIN_PER_KG * weight_kg))
158
+ fat_g = int(round(FAT_MIN_G_PER_KG * weight_kg))
159
+ # احسبي الكارب من الباقي
160
+ cals_from_p = protein_g * 4
161
+ cals_from_f = fat_g * 9
162
+ carbs_g = max(0, int(round((calories - cals_from_p - cals_from_f) / 4)))
163
+ return protein_g, carbs_g, fat_g
164
+
165
+ def filter_foods(options: List[str], avoid: List[str]) -> List[str]:
166
+ avoid_set = {a.strip().lower() for a in avoid if a.strip()}
167
+ res = []
168
+ for o in options:
169
+ if any(bad in o.lower() for bad in avoid_set):
170
+ continue
171
+ res.append(o)
172
+ return res
173
+
174
+ DEFAULT_PROTEINS = ["chicken breast", "eggs", "tuna", "lean beef", "laban protein", "tofu"]
175
+ DEFAULT_CARBS = ["rice", "oats", "potatoes", "pasta", "whole-wheat bread", "dates", "fruit"]
176
+ DEFAULT_FATS = ["olive oil", "avocado", "nuts", "tahini", "peanut butter"]
177
+ DEFAULT_VEGS = ["salad mix", "cucumber", "tomato", "broccoli", "spinach"]
178
+
179
+ def agent_nutrition(weight_kg: float, target_kcal: int, liked_csv: str, avoid_csv: str, meals: int):
180
+ liked = [x.strip() for x in liked_csv.split(",") if x.strip()]
181
+ avoid = [x.strip() for x in avoid_csv.split(",") if x.strip()]
182
+
183
+ proteins = filter_foods((liked or DEFAULT_PROTEINS), avoid)
184
+ carbs = filter_foods(DEFAULT_CARBS, avoid)
185
+ fats = filter_foods(DEFAULT_FATS, avoid)
186
+ vegs = filter_foods(DEFAULT_VEGS, avoid)
187
+
188
+ p, c, f = macros_for_calories(weight_kg, target_kcal)
189
+ per_meal = max(1, meals)
190
+ p_m, c_m, f_m = p//per_meal, c//per_meal, f//per_meal
191
+
192
+ sample_day = [
193
+ f"Meal {i+1}: {proteins[i % len(proteins)]} + {carbs[i % len(carbs)]} + {vegs[i % len(vegs)]} + {fats[i % len(fats)]}"
194
+ for i in range(per_meal)
195
+ ]
196
+
197
+ md = f"""### 🥗 Nutrition Plan
198
+ - **Target:** **{target_kcal} kcal/day**
199
+ - **Macros (approx.):** Protein **{p} g**, Carbs **{c} g**, Fat **{f} g** → per meal ≈ **{p_m}/{c_m}/{f_m} g**
200
+ - **Preferred foods used:** {", ".join(proteins[:3])} …
201
+
202
+ **Sample Day:**
203
+ {chr(10).join([f"- {m}" for m in sample_day])}
204
+
205
+ **Grocery list (starter):**
206
+ - Protein: {", ".join(proteins)}
207
+ - Carbs: {", ".join(carbs)}
208
+ - Fats: {", ".join(fats)}
209
+ - Veggies: {", ".join(vegs)}
210
+
211
+ > Tips: add 20–30g protein to each meal, veggies freely, and 1–2 pieces fruit/day.
212
+ """
213
+ return md
214
+
215
+ # -------------------------------
216
+ # All-in-one Coach (chains agents)
217
+ # -------------------------------
218
+ def coach_all_in_one(
219
+ sex, age, height_cm, weight_kg, activity, goal,
220
+ level, days, equipment,
221
+ liked_csv, avoid_csv, meals
222
+ ):
223
+ # 1) BMI & TDEE
224
+ report = agent_bmi_tdee(sex, age, height_cm, weight_kg, activity, goal)
225
+ _, cut, bulk = tdee(sex, age, height_cm, weight_kg, activity)
226
+ target = {"Lose fat": cut, "Maintain": tdee(sex, age, height_cm, weight_kg, activity)[0], "Build muscle": bulk}[goal]
227
+
228
+ # 2) Workout
229
+ w = agent_workout(level, days, goal, equipment)
230
+
231
+ # 3) Nutrition
232
+ n = agent_nutrition(weight_kg, target, liked_csv, avoid_csv, meals)
233
+
234
+ return report + "\n---\n" + w + "\n---\n" + n
235
+
236
+ # -------------------------------
237
+ # UI (Gradio)
238
+ # -------------------------------
239
+ with gr.Blocks(title="Beginner Gym Coach - Multi-Agent") as demo:
240
+ gr.Markdown("## 🏋️ Beginner Gym Coach — Multi-Agent\nGive me your basics and I’ll coach you.")
241
+
242
+ with gr.Tab("BMI & TDEE"):
243
+ with gr.Row():
244
+ with gr.Column():
245
+ sex = gr.Radio(["male","female"], value="female", label="Sex")
246
+ age = gr.Slider(15, 70, value=24, step=1, label="Age")
247
+ height = gr.Slider(130, 210, value=165, step=1, label="Height (cm)")
248
+ weight = gr.Slider(35, 160, value=60, step=0.5, label="Weight (kg)")
249
+ activity = gr.Dropdown(list(ACTIVITY.keys()), value="Light (1-3x/wk)", label="Activity")
250
+ goal = gr.Radio(["Lose fat","Maintain","Build muscle"], value="Maintain", label="Goal")
251
+ btn1 = gr.Button("Calculate")
252
+ out1 = gr.Markdown()
253
+ btn1.click(agent_bmi_tdee, [sex, age, height, weight, activity, goal], out1)
254
+
255
+ with gr.Tab("Workout Plan"):
256
+ with gr.Row():
257
+ with gr.Column():
258
+ level = gr.Radio(["Beginner","Intermediate"], value="Beginner", label="Level")
259
+ days = gr.Slider(2, 6, value=4, step=1, label="Days/week")
260
+ goal_w = gr.Radio(["Lose fat","Maintain","Build muscle"], value="Build muscle", label="Goal")
261
+ equipment = gr.Dropdown(["Gym (machines/dumbbells)","Home (bands/db)","Bodyweight only"], value="Gym (machines/dumbbells)", label="Equipment")
262
+ btn2 = gr.Button("Generate Plan")
263
+ out2 = gr.Markdown()
264
+ btn2.click(agent_workout, [level, days, goal_w, equipment], out2)
265
+
266
+ with gr.Tab("Nutrition"):
267
+ with gr.Row():
268
+ with gr.Column():
269
+ target_kcal = gr.Number(value=1900, label="Target calories (kcal)")
270
+ weight_n = gr.Number(value=60, label="Weight (kg)")
271
+ liked = gr.Textbox(label="Preferred foods (comma-separated)", placeholder="chicken, eggs, rice, oats, salad, laban")
272
+ avoid = gr.Textbox(label="Allergies / avoid (comma-separated)", placeholder="nuts, shrimp, gluten")
273
+ meals = gr.Slider(2, 6, value=3, step=1, label="Meals/day")
274
+ btn3 = gr.Button("Build Meal Plan")
275
+ out3 = gr.Markdown()
276
+ btn3.click(agent_nutrition, [weight_n, target_kcal, liked, avoid, meals], out3)
277
+
278
+ with gr.Tab("All-in-One Coach"):
279
+ with gr.Row():
280
+ with gr.Column():
281
+ # Personal
282
+ sex2 = gr.Radio(["male","female"], value="female", label="Sex")
283
+ age2 = gr.Slider(15, 70, value=24, step=1, label="Age")
284
+ height2 = gr.Slider(130, 210, value=165, step=1, label="Height (cm)")
285
+ weight2 = gr.Slider(35, 160, value=60, step=0.5, label="Weight (kg)")
286
+ activity2 = gr.Dropdown(list(ACTIVITY.keys()), value="Light (1-3x/wk)", label="Activity")
287
+ goal2 = gr.Radio(["Lose fat","Maintain","Build muscle"], value="Build muscle", label="Goal")
288
+ # Training
289
+ level2 = gr.Radio(["Beginner","Intermediate"], value="Beginner", label="Level")
290
+ days2 = gr.Slider(2, 6, value=4, step=1, label="Days/week")
291
+ equipment2 = gr.Dropdown(["Gym (machines/dumbbells)","Home (bands/db)","Bodyweight only"], value="Gym (machines/dumbbells)", label="Equipment")
292
+ # Nutrition
293
+ liked2 = gr.Textbox(label="Preferred foods", placeholder="chicken, eggs, rice, potatoes")
294
+ avoid2 = gr.Textbox(label="Allergies / avoid", placeholder="nuts, shrimp")
295
+ meals2 = gr.Slider(2, 6, value=3, step=1, label="Meals/day")
296
+ btn4 = gr.Button("Get My Full Plan 🚀")
297
+ out4 = gr.Markdown()
298
+ btn4.click(
299
+ coach_all_in_one,
300
+ [sex2, age2, height2, weight2, activity2, goal2, level2, days2, equipment2, liked2, avoid2, meals2],
301
+ out4
302
+ )
303
+
304
+ if __name__ == "__main__":
305
+ demo.launch()