Plan / app.py
AlaaElsayed's picture
Upload app.py
8b7d0a4
raw
history blame
3.92 kB
from flask import Flask, request, jsonify, make_response
import pandas as pd
import joblib
from flask_cors import CORS
from collections import OrderedDict
import json
app = Flask(__name__)
CORS(app) # Enables cross-origin requests (e.g., from Flutter)
# Load models and encoders
food_model = joblib.load("goal_classifier.pkl")
exercise_model = joblib.load("exercise_classifier.pkl")
encoders = joblib.load("encoders.pkl")
df = pd.read_csv("fitness_meal_plan_with_exercises.csv")
# Load individual encoders
le_gender = encoders['gender']
le_workout = encoders['workout']
le_goal = encoders['goal']
le_exercise = encoders['exercise']
preprocessor = encoders['preprocessor']
# --- Utilities ---
def calculate_bmi(weight_kg, height_cm):
return weight_kg / ((height_cm / 100) ** 2)
def get_meal_plan(week, day):
filtered = df[(df['Week'] == week) & (df['Day'] == day)]
if not filtered.empty:
row = filtered.iloc[0]
return OrderedDict([
("Breakfast", {"Meal": row["Breakfast"], "Calories": int(row["Calories_Breakfast"])}),
("Snack_1", {"Meal": row["Snack_1"], "Calories": int(row["Calories_Snack_1"])}),
("Lunch", {"Meal": row["Lunch"], "Calories": int(row["Calories_Lunch"])}),
("Snack_2", {"Meal": row["Snack_2"], "Calories": int(row["Calories_Snack_2"])}),
("Dinner", {"Meal": row["Dinner"], "Calories": int(row["Calories_Dinner"])})
])
return OrderedDict()
def get_exercise(week, day):
filtered = df[(df['Week'] == week) & (df['Day'] == day)]
if not filtered.empty:
row = filtered.iloc[0]
# Decode label if encoded
try:
row['Exercise_Name'] = le_exercise.inverse_transform([row['Exercise_Name']])[0]
except:
pass
return row[['Exercise_Name', 'Exercise_Description', 'Exercise_Duration']].to_dict()
return {}
# --- Main API Endpoint ---
@app.route("/recommend", methods=["POST"])
def recommend():
data = request.get_json()
try:
# Encode inputs
user_input = {
'Gender': le_gender.transform([data['Gender']])[0],
'Age': data['Age'],
'Height_cm': data['Height_cm'],
'Weight_kg': data['Weight_kg'],
'Workout_History': le_workout.transform([data['Workout_History']])[0],
'Goal': le_goal.transform([data['Goal']])[0],
'Week': data['Week'],
'Day': data['Day']
}
# Add BMI for potential future use
user_input['BMI'] = calculate_bmi(user_input['Weight_kg'], user_input['Height_cm'])
# Prepare input for prediction (not used in current response)
user_df = pd.DataFrame([user_input])
user_X = preprocessor.transform(user_df)
# Perform predictions (optional if not needed in response)
food_model.predict(user_X)
exercise_model.predict(user_X)
# Return either meal or exercise plan
if data['choice'] == 'meal':
meal_plan = get_meal_plan(user_input['Week'], user_input['Day'])
response_data = {
"Meal_Plan": meal_plan,
"Total_Calories": sum(meal["Calories"] for meal in meal_plan.values())
}
elif data['choice'] == 'exercise':
exercise = get_exercise(user_input['Week'], user_input['Day'])
response_data = {"Exercise": exercise}
else:
return jsonify({"error": "Invalid choice. Must be 'meal' or 'exercise'"}), 400
return make_response(json.dumps(response_data, ensure_ascii=False), 200, {'Content-Type': 'application/json'})
except Exception as e:
return jsonify({'error': str(e)}), 400
# --- Run the Flask app ---
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)