Vishwas1 commited on
Commit
dbeb88a
·
verified ·
1 Parent(s): 2cf268e

Upload 8 files

Browse files
main.py ADDED
@@ -0,0 +1,275 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify, render_template
2
+ import requests
3
+ import os
4
+ import math
5
+ import logging
6
+
7
+ app = Flask(__name__)
8
+ app.static_folder = 'static'
9
+
10
+ # Configure logging
11
+ logging.basicConfig(level=logging.DEBUG)
12
+
13
+ # Configuration
14
+ USDA_API_ENDPOINT = "https://api.nal.usda.gov/fdc/v1"
15
+ USDA_API_KEY = os.environ.get('USDA_API_KEY')
16
+
17
+ # Error messages
18
+ INVALID_INPUT_ERROR = "Invalid input"
19
+ MISSING_REQUIRED_FIELDS_ERROR = "Missing required fields"
20
+ FAILED_TO_FETCH_NUTRIENT_DATA_ERROR = "Failed to fetch nutrient data"
21
+
22
+ @app.route('/')
23
+ def index():
24
+ return render_template('index.html')
25
+
26
+ @app.route('/api/calculate-metrics', methods=['POST'])
27
+ def calculate_metrics():
28
+ data = request.json
29
+ app.logger.debug(f"Received data for calculate_metrics: {data}")
30
+
31
+ required_fields = ['age', 'gender', 'heightFeet', 'heightInches', 'weight', 'targetWeight', 'waist', 'neck', 'hip', 'steps', 'standingHours']
32
+ missing_fields = [field for field in required_fields if field not in data or data[field] is None]
33
+
34
+ if missing_fields:
35
+ app.logger.error(f"Missing required fields: {', '.join(missing_fields)}")
36
+ return jsonify({"error": MISSING_REQUIRED_FIELDS_ERROR, "missing_fields": missing_fields}), 400
37
+
38
+ try:
39
+ age = int(data['age'])
40
+ gender = data['gender']
41
+ height_feet = int(data['heightFeet'])
42
+ height_inches = int(data['heightInches'])
43
+ weight = float(data['weight']) # in kg
44
+ target_weight = float(data['targetWeight']) # in kg
45
+ waist = float(data['waist']) # in cm
46
+ neck = float(data['neck']) # in cm
47
+ hip = float(data['hip']) # in cm
48
+ steps = int(data['steps'])
49
+ standing_hours = float(data['standingHours'])
50
+
51
+ # Convert height to cm
52
+ height = (height_feet * 30.48) + (height_inches * 2.54) # Convert to cm
53
+
54
+ except (ValueError, KeyError) as e:
55
+ app.logger.error(f"Invalid input: {str(e)}")
56
+ return jsonify({"error": INVALID_INPUT_ERROR, "details": str(e)}), 400
57
+
58
+ if age <= 0 or height <= 0 or weight <= 0 or target_weight <= 0 or waist <= 0 or neck <= 0 or hip <= 0 or steps < 0 or standing_hours < 0:
59
+ app.logger.error("Invalid input values")
60
+ return jsonify({"error": INVALID_INPUT_ERROR, "details": "Input values must be positive numbers"}), 400
61
+
62
+ if gender not in ['male', 'female', 'other']:
63
+ app.logger.error("Invalid gender")
64
+ return jsonify({"error": INVALID_INPUT_ERROR, "details": "Gender must be 'male', 'female', or 'other'"}), 400
65
+
66
+ # Calculate BMI
67
+ bmi = weight / ((height / 100) ** 2)
68
+
69
+ # Calculate body fat percentage (using U.S. Navy method)
70
+ if gender == 'male':
71
+ body_fat = 86.010 * math.log10(waist - neck) - 70.041 * math.log10(height) + 36.76
72
+ elif gender == 'female':
73
+ body_fat = 163.205 * math.log10(waist + hip - neck) - 97.684 * math.log10(height) - 78.387
74
+ else:
75
+ # For 'other' gender, use an average of male and female calculations
76
+ body_fat_male = 86.010 * math.log10(waist - neck) - 70.041 * math.log10(height) + 36.76
77
+ body_fat_female = 163.205 * math.log10(waist + hip - neck) - 97.684 * math.log10(height) - 78.387
78
+ body_fat = (body_fat_male + body_fat_female) / 2
79
+
80
+ # Calculate lean body mass
81
+ lean_body_mass = weight * (1 - (body_fat / 100))
82
+
83
+ # Calculate recommended calorie intake (using Mifflin-St Jeor Equation)
84
+ if gender == 'male':
85
+ bmr = 10 * weight + 6.25 * height - 5 * age + 5
86
+ elif gender == 'female':
87
+ bmr = 10 * weight + 6.25 * height - 5 * age - 161
88
+ else:
89
+ # For 'other' gender, use an average of male and female calculations
90
+ bmr_male = 10 * weight + 6.25 * height - 5 * age + 5
91
+ bmr_female = 10 * weight + 6.25 * height - 5 * age - 161
92
+ bmr = (bmr_male + bmr_female) / 2
93
+
94
+ # Adjust for activity level
95
+ activity_factor = 1.2 + (steps / 10000) * 0.1 + (standing_hours / 24) * 0.1
96
+ recommended_calories = bmr * activity_factor
97
+
98
+ # Calculate time to reach target weight
99
+ weight_difference = abs(weight - target_weight)
100
+ daily_calorie_deficit = 500 # Assuming a 500 calorie deficit per day
101
+ days_to_target = (weight_difference * 7700) / daily_calorie_deficit # 7700 calories ≈ 1 kg of body fat
102
+
103
+ response = {
104
+ 'bmi': round(bmi, 2),
105
+ 'bodyFatPercentage': round(body_fat, 2),
106
+ 'leanBodyMass': round(lean_body_mass, 2),
107
+ 'recommendedCalories': round(recommended_calories),
108
+ 'timeToTargetWeight': f"{round(days_to_target)} days"
109
+ }
110
+
111
+ app.logger.debug(f"Calculated metrics: {response}")
112
+ return jsonify(response)
113
+
114
+ @app.route('/api/personalized-recommendations', methods=['POST'])
115
+ def get_personalized_recommendations():
116
+ data = request.json
117
+ app.logger.debug(f"Received data for personalized_recommendations: {data}")
118
+
119
+ required_fields = ['age', 'gender', 'height', 'weight', 'targetWeight', 'bmi', 'bodyFatPercentage', 'recommendedCalories', 'steps', 'standingHours']
120
+ missing_fields = [field for field in required_fields if field not in data or data[field] is None]
121
+ if missing_fields:
122
+ app.logger.error(f"Missing required fields: {', '.join(missing_fields)}")
123
+ return jsonify({"error": MISSING_REQUIRED_FIELDS_ERROR, "missing_fields": missing_fields}), 400
124
+
125
+ try:
126
+ age = int(data['age'])
127
+ gender = data['gender']
128
+ height = float(data['height'])
129
+ weight = float(data['weight'])
130
+ target_weight = float(data['targetWeight'])
131
+ bmi = float(data['bmi'])
132
+ body_fat_percentage = float(data['bodyFatPercentage'])
133
+ recommended_calories = int(data['recommendedCalories'])
134
+ steps = int(data['steps'])
135
+ standing_hours = float(data['standingHours'])
136
+ except (ValueError, KeyError) as e:
137
+ app.logger.error(f"Invalid input: {str(e)}")
138
+ return jsonify({"error": INVALID_INPUT_ERROR, "details": str(e)}), 400
139
+
140
+ # Diet recommendations
141
+ diet_recommendations = []
142
+ if bmi < 18.5:
143
+ diet_recommendations.append("Increase calorie intake with nutrient-dense foods to reach a healthy weight")
144
+ diet_recommendations.append("Focus on foods high in healthy fats, such as avocados, nuts, and olive oil")
145
+ diet_recommendations.append("Incorporate protein-rich foods like lean meats, fish, eggs, and legumes")
146
+ elif 18.5 <= bmi < 25:
147
+ diet_recommendations.append("Maintain a balanced diet with a focus on whole foods")
148
+ diet_recommendations.append("Ensure adequate intake of fruits, vegetables, whole grains, and lean proteins")
149
+ diet_recommendations.append("Monitor portion sizes to maintain your healthy weight")
150
+ elif 25 <= bmi < 30:
151
+ diet_recommendations.append("Slightly reduce calorie intake and focus on nutrient-dense, low-calorie foods")
152
+ diet_recommendations.append("Increase fiber intake through vegetables, fruits, and whole grains")
153
+ diet_recommendations.append("Choose lean proteins and limit saturated fats")
154
+ else:
155
+ diet_recommendations.append("Reduce calorie intake and focus on whole, unprocessed foods")
156
+ diet_recommendations.append("Prioritize vegetables, lean proteins, and complex carbohydrates")
157
+ diet_recommendations.append("Avoid sugary drinks and high-calorie snacks")
158
+
159
+ if (gender == 'male' and body_fat_percentage > 25) or (gender == 'female' and body_fat_percentage > 32) or (gender == 'other' and body_fat_percentage > 28):
160
+ diet_recommendations.append("Increase protein intake to support lean muscle mass")
161
+ diet_recommendations.append("Consider adding a protein shake or Greek yogurt as a snack")
162
+ diet_recommendations.append("Include more fish, chicken, turkey, or plant-based proteins in your meals")
163
+
164
+ diet_recommendations.append(f"Aim for {recommended_calories} calories per day")
165
+ diet_recommendations.append("Include a variety of colorful fruits and vegetables in your diet")
166
+ diet_recommendations.append("Stay hydrated by drinking at least 8 glasses of water daily")
167
+ diet_recommendations.append("Limit processed foods and choose whole grains over refined grains")
168
+
169
+ if weight > target_weight:
170
+ diet_recommendations.append("Create a calorie deficit of 500 calories per day to lose weight")
171
+ diet_recommendations.append("Use smaller plates to help control portion sizes")
172
+ diet_recommendations.append("Start meals with a salad or vegetable soup to increase satiety")
173
+ elif weight < target_weight:
174
+ diet_recommendations.append("Increase your calorie intake by 500 calories per day to gain weight")
175
+ diet_recommendations.append("Add healthy, calorie-dense foods like nuts, seeds, and dried fruits to your meals")
176
+ diet_recommendations.append("Consider drinking smoothies made with fruits, oats, and protein powder")
177
+ else:
178
+ diet_recommendations.append("Maintain your current calorie intake to maintain your weight")
179
+ diet_recommendations.append("Practice mindful eating and listen to your body's hunger and fullness cues")
180
+
181
+ # Exercise recommendations
182
+ exercise_recommendations = []
183
+ if steps < 5000:
184
+ exercise_recommendations.append("Gradually increase your daily step count to at least 7,500 steps")
185
+ exercise_recommendations.append("Take short walks during breaks or after meals")
186
+ exercise_recommendations.append("Use stairs instead of elevators when possible")
187
+ elif 5000 <= steps < 10000:
188
+ exercise_recommendations.append("Aim to reach 10,000 steps per day for better health")
189
+ exercise_recommendations.append("Try brisk walking or light jogging to increase step count")
190
+ exercise_recommendations.append("Consider using a treadmill desk or walking meetings")
191
+ else:
192
+ exercise_recommendations.append("Great job on your step count! Consider adding more intense exercises")
193
+ exercise_recommendations.append("Incorporate interval training or hill walks to challenge yourself")
194
+ exercise_recommendations.append("Set new step goals to maintain motivation")
195
+
196
+ if standing_hours < 2:
197
+ exercise_recommendations.append("Try to increase your standing time to at least 2-4 hours per day")
198
+ exercise_recommendations.append("Use a standing desk or elevate your workstation for part of the day")
199
+ exercise_recommendations.append("Take phone calls while standing or walking")
200
+ elif 2 <= standing_hours < 4:
201
+ exercise_recommendations.append("Good job on standing! Aim to increase your standing time to 4-6 hours per day")
202
+ exercise_recommendations.append("Alternate between sitting and standing every 30-60 minutes")
203
+ exercise_recommendations.append("Try gentle exercises or stretches while standing")
204
+ else:
205
+ exercise_recommendations.append("Excellent standing habits! Maintain your current standing routine")
206
+ exercise_recommendations.append("Incorporate balance exercises or yoga poses while standing")
207
+ exercise_recommendations.append("Consider a treadmill desk for light walking while working")
208
+
209
+ exercise_recommendations.append("Include strength training exercises at least 2-3 times per week")
210
+ exercise_recommendations.append("Aim for at least 150 minutes of moderate-intensity aerobic activity per week")
211
+ exercise_recommendations.append("Don't forget to stretch before and after exercises to improve flexibility")
212
+
213
+ if weight > target_weight:
214
+ exercise_recommendations.append("Incorporate high-intensity interval training (HIIT) to boost fat burning")
215
+ exercise_recommendations.append("Try circuit training to combine strength and cardio exercises")
216
+ exercise_recommendations.append("Consider joining group fitness classes for motivation and guidance")
217
+ elif weight < target_weight:
218
+ exercise_recommendations.append("Focus on compound exercises and progressive overload to build muscle mass")
219
+ exercise_recommendations.append("Incorporate resistance band exercises for muscle growth")
220
+ exercise_recommendations.append("Ensure adequate rest between workouts for muscle recovery and growth")
221
+ else:
222
+ exercise_recommendations.append("Mix cardio and strength training to maintain your current weight and improve overall fitness")
223
+ exercise_recommendations.append("Try new activities or sports to keep your routine interesting")
224
+ exercise_recommendations.append("Set performance-based goals to stay motivated")
225
+
226
+ if age > 50:
227
+ exercise_recommendations.append("Include balance and flexibility exercises to maintain mobility")
228
+ exercise_recommendations.append("Consider low-impact activities like swimming or cycling to protect joints")
229
+
230
+ response = {
231
+ 'dietRecommendations': diet_recommendations,
232
+ 'exerciseRecommendations': exercise_recommendations
233
+ }
234
+
235
+ app.logger.debug(f"Generated recommendations: {response}")
236
+ return jsonify(response)
237
+
238
+ @app.route('/api/search-food', methods=['GET'])
239
+ def search_food():
240
+ query = request.args.get('query', '')
241
+ if not query:
242
+ return jsonify({"error": "Missing query parameter"}), 400
243
+
244
+ try:
245
+ response = requests.get(
246
+ f"{USDA_API_ENDPOINT}/foods/search",
247
+ params={
248
+ "api_key": USDA_API_KEY,
249
+ "query": query,
250
+ "dataType": ["Survey (FNDDS)"],
251
+ "pageSize": 10
252
+ }
253
+ )
254
+ response.raise_for_status()
255
+ data = response.json()
256
+
257
+ results = []
258
+ for food in data.get('foods', []):
259
+ nutrients = {nutrient['nutrientName']: nutrient['value'] for nutrient in food.get('foodNutrients', [])}
260
+ results.append({
261
+ 'description': food['description'],
262
+ 'calories': nutrients.get('Energy', 0),
263
+ 'protein': nutrients.get('Protein', 0),
264
+ 'carbs': nutrients.get('Carbohydrate, by difference', 0),
265
+ 'fat': nutrients.get('Total lipid (fat)', 0)
266
+ })
267
+
268
+ return jsonify(results)
269
+
270
+ except requests.RequestException as e:
271
+ app.logger.error(f"Error fetching food data: {str(e)}")
272
+ return jsonify({"error": "Failed to fetch food data"}), 500
273
+
274
+ if __name__ == '__main__':
275
+ app.run(host='0.0.0.0', port=5000, debug=True)
static/css/styles.css ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body {
2
+ font-family: Arial, sans-serif;
3
+ line-height: 1.6;
4
+ margin: 0;
5
+ padding: 20px;
6
+ max-width: 800px;
7
+ margin: 0 auto;
8
+ }
9
+
10
+ h1, h2, h3 {
11
+ color: #333;
12
+ }
13
+
14
+ form {
15
+ margin-bottom: 20px;
16
+ }
17
+
18
+ label {
19
+ display: block;
20
+ margin-bottom: 5px;
21
+ }
22
+
23
+ input, select {
24
+ width: 100%;
25
+ padding: 5px;
26
+ margin-bottom: 10px;
27
+ }
28
+
29
+ button {
30
+ background-color: #4CAF50;
31
+ color: white;
32
+ padding: 10px 15px;
33
+ border: none;
34
+ cursor: pointer;
35
+ }
36
+
37
+ button:hover {
38
+ background-color: #45a049;
39
+ }
40
+
41
+ ul {
42
+ list-style-type: none;
43
+ padding: 0;
44
+ }
45
+
46
+ li {
47
+ cursor: pointer;
48
+ padding: 5px;
49
+ margin-bottom: 5px;
50
+ background-color: #f0f0f0;
51
+ }
52
+
53
+ li:hover {
54
+ background-color: #e0e0e0;
55
+ }
56
+
57
+ canvas {
58
+ border: 1px solid #ddd;
59
+ margin-top: 20px;
60
+ }
61
+
62
+ .flex-container {
63
+ display: flex;
64
+ justify-content: space-between;
65
+ }
66
+
67
+ .flex-container > div {
68
+ flex: 1;
69
+ margin-right: 20px;
70
+ }
71
+
72
+ #visualization {
73
+ text-align: center;
74
+ }
75
+
76
+ #bmi-display {
77
+ margin-top: 20px;
78
+ }
79
+
80
+ .notification {
81
+ position: fixed;
82
+ top: 20px;
83
+ right: 20px;
84
+ padding: 10px 20px;
85
+ border-radius: 5px;
86
+ color: white;
87
+ font-weight: bold;
88
+ opacity: 0.9;
89
+ transition: opacity 0.3s ease-in-out;
90
+ }
91
+
92
+ .notification.success {
93
+ background-color: #4CAF50;
94
+ }
95
+
96
+ .notification.info {
97
+ background-color: #2196F3;
98
+ }
99
+
100
+ .notification.error {
101
+ background-color: #f44336;
102
+ }
103
+
104
+ @media (max-width: 600px) {
105
+ body {
106
+ padding: 10px;
107
+ }
108
+
109
+ .flex-container {
110
+ flex-direction: column;
111
+ }
112
+
113
+ .flex-container > div {
114
+ margin-right: 0;
115
+ margin-bottom: 20px;
116
+ }
117
+ }
static/data/food_items.json ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "Apple": {
3
+ "calories": 95,
4
+ "effect": "decrease"
5
+ },
6
+ "Banana": {
7
+ "calories": 105,
8
+ "effect": "decrease"
9
+ },
10
+ "Chicken Breast": {
11
+ "calories": 165,
12
+ "effect": "decrease"
13
+ },
14
+ "Pizza Slice": {
15
+ "calories": 285,
16
+ "effect": "increase"
17
+ },
18
+ "Salad": {
19
+ "calories": 100,
20
+ "effect": "decrease"
21
+ },
22
+ "Cheeseburger": {
23
+ "calories": 300,
24
+ "effect": "increase"
25
+ },
26
+ "Yogurt": {
27
+ "calories": 150,
28
+ "effect": "decrease"
29
+ },
30
+ "Ice Cream": {
31
+ "calories": 270,
32
+ "effect": "increase"
33
+ },
34
+ "Broccoli": {
35
+ "calories": 55,
36
+ "effect": "decrease"
37
+ },
38
+ "French Fries": {
39
+ "calories": 365,
40
+ "effect": "increase"
41
+ }
42
+ }
static/js/app.js ADDED
@@ -0,0 +1,247 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ document.addEventListener('DOMContentLoaded', () => {
2
+ const userForm = document.getElementById('user-form');
3
+ const selectedFoodList = document.getElementById('selected-food-list');
4
+ const canvas = document.getElementById('belly-fat-canvas');
5
+ const ctx = canvas.getContext('2d');
6
+ const searchInput = document.getElementById('food-search');
7
+ const searchResults = document.getElementById('search-results');
8
+
9
+ let selectedItems = [];
10
+ let userMetrics = {};
11
+ let recommendedCalories = 2000; // Default value, will be updated after user submits metrics
12
+
13
+ function updateUserMetrics() {
14
+ userMetrics.age = parseInt(document.getElementById('age').value);
15
+ userMetrics.gender = document.getElementById('gender').value;
16
+ userMetrics.heightFeet = parseInt(document.getElementById('height-feet').value);
17
+ userMetrics.heightInches = parseInt(document.getElementById('height-inches').value);
18
+ userMetrics.weight = parseFloat(document.getElementById('weight').value);
19
+ userMetrics.targetWeight = parseFloat(document.getElementById('target-weight').value);
20
+ userMetrics.waist = parseFloat(document.getElementById('waist').value);
21
+ userMetrics.neck = parseFloat(document.getElementById('neck').value);
22
+ userMetrics.hip = parseFloat(document.getElementById('hip').value);
23
+ userMetrics.steps = parseInt(document.getElementById('steps').value);
24
+ userMetrics.standingHours = parseFloat(document.getElementById('standing-hours').value);
25
+ }
26
+
27
+ userForm.addEventListener('submit', (e) => {
28
+ e.preventDefault();
29
+ updateUserMetrics();
30
+ calculateMetrics();
31
+ });
32
+
33
+ function calculateMetrics() {
34
+ console.log('calculateMetrics function called');
35
+ const heightInCm = (userMetrics.heightFeet * 30.48) + (userMetrics.heightInches * 2.54);
36
+ const weightInKg = userMetrics.weight * 0.45359237;
37
+ const targetWeightInKg = userMetrics.targetWeight * 0.45359237;
38
+ const waistInCm = userMetrics.waist * 2.54;
39
+ const neckInCm = userMetrics.neck * 2.54;
40
+ const hipInCm = userMetrics.hip * 2.54;
41
+
42
+ const metricsData = {
43
+ age: userMetrics.age,
44
+ gender: userMetrics.gender,
45
+ heightFeet: userMetrics.heightFeet,
46
+ heightInches: userMetrics.heightInches,
47
+ weight: weightInKg,
48
+ targetWeight: targetWeightInKg,
49
+ waist: waistInCm,
50
+ neck: neckInCm,
51
+ hip: hipInCm,
52
+ steps: userMetrics.steps,
53
+ standingHours: userMetrics.standingHours
54
+ };
55
+
56
+ console.log('Sending metrics data:', metricsData);
57
+ fetch('/api/calculate-metrics', {
58
+ method: 'POST',
59
+ headers: {
60
+ 'Content-Type': 'application/json',
61
+ },
62
+ body: JSON.stringify(metricsData),
63
+ })
64
+ .then(response => {
65
+ console.log('Response status:', response.status);
66
+ return response.json();
67
+ })
68
+ .then(data => {
69
+ console.log('Received metrics data:', data);
70
+ if (data.error) {
71
+ console.error('Error calculating metrics:', data.error);
72
+ showNotification(`Error: ${data.error}`, 'error');
73
+ return;
74
+ }
75
+ document.getElementById('bmi-value').textContent = data.bmi;
76
+ document.getElementById('recommended-calories').textContent = data.recommendedCalories;
77
+ document.getElementById('body-fat-percentage').textContent = data.bodyFatPercentage + '%';
78
+ document.getElementById('lean-body-mass').textContent = (data.leanBodyMass * 2.20462).toFixed(2) + ' lbs';
79
+ document.getElementById('target-weight-time').textContent = data.timeToTargetWeight;
80
+ recommendedCalories = data.recommendedCalories;
81
+ updateBellyFatVisualization({ calories: 0, protein: 0, carbs: 0, fat: 0 });
82
+ getPersonalizedRecommendations(data);
83
+ })
84
+ .catch(error => {
85
+ console.error('Error:', error);
86
+ showNotification(`Error: ${error.message}`, 'error');
87
+ });
88
+ }
89
+
90
+ function getPersonalizedRecommendations(metricsData) {
91
+ const recommendationData = {
92
+ ...userMetrics,
93
+ ...metricsData,
94
+ height: (userMetrics.heightFeet * 30.48) + (userMetrics.heightInches * 2.54)
95
+ };
96
+
97
+ console.log('Sending recommendation data:', recommendationData);
98
+ fetch('/api/personalized-recommendations', {
99
+ method: 'POST',
100
+ headers: {
101
+ 'Content-Type': 'application/json',
102
+ },
103
+ body: JSON.stringify(recommendationData),
104
+ })
105
+ .then(response => response.json())
106
+ .then(data => {
107
+ console.log('Received recommendations:', data);
108
+ if (data.error) {
109
+ console.error('Error getting recommendations:', data.error);
110
+ showNotification(`Error: ${data.error}`, 'error');
111
+ return;
112
+ }
113
+ displayRecommendations(data);
114
+ })
115
+ .catch(error => {
116
+ console.error('Error:', error);
117
+ showNotification(`Error: ${error.message}`, 'error');
118
+ });
119
+ }
120
+
121
+ function displayRecommendations(recommendations) {
122
+ const dietRecommendationsList = document.getElementById('diet-recommendations-list');
123
+ const exerciseRecommendationsList = document.getElementById('exercise-recommendations-list');
124
+
125
+ dietRecommendationsList.innerHTML = '';
126
+ exerciseRecommendationsList.innerHTML = '';
127
+
128
+ recommendations.dietRecommendations.forEach(recommendation => {
129
+ const li = document.createElement('li');
130
+ li.textContent = recommendation;
131
+ dietRecommendationsList.appendChild(li);
132
+ });
133
+
134
+ recommendations.exerciseRecommendations.forEach(recommendation => {
135
+ const li = document.createElement('li');
136
+ li.textContent = recommendation;
137
+ exerciseRecommendationsList.appendChild(li);
138
+ });
139
+ }
140
+
141
+ function searchFood() {
142
+ const query = searchInput.value.trim();
143
+ if (query.length < 2) return;
144
+
145
+ fetch(`/api/search-food?query=${encodeURIComponent(query)}`)
146
+ .then(response => response.json())
147
+ .then(data => {
148
+ displaySearchResults(data);
149
+ })
150
+ .catch(error => console.error('Error:', error));
151
+ }
152
+
153
+ function displaySearchResults(results) {
154
+ searchResults.innerHTML = '';
155
+ results.forEach(item => {
156
+ const li = document.createElement('li');
157
+ li.textContent = item.description;
158
+ li.addEventListener('click', () => addFoodItem(item));
159
+ searchResults.appendChild(li);
160
+ });
161
+ }
162
+
163
+ function addFoodItem(item) {
164
+ selectedItems.push(item);
165
+ updateSelectedFoodList();
166
+ updateBellyFatVisualization();
167
+ }
168
+
169
+ function updateSelectedFoodList() {
170
+ selectedFoodList.innerHTML = '';
171
+ selectedItems.forEach(item => {
172
+ const li = document.createElement('li');
173
+ li.textContent = `${item.description} (${item.calories} kcal)`;
174
+ selectedFoodList.appendChild(li);
175
+ });
176
+ }
177
+
178
+ function updateBellyFatVisualization() {
179
+ const totalNutrients = calculateTotalNutrients();
180
+
181
+ // Clear the canvas
182
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
183
+
184
+ // Draw yellow plate
185
+ ctx.beginPath();
186
+ ctx.arc(canvas.width / 2, canvas.height / 2, canvas.width / 3, 0, 2 * Math.PI);
187
+ ctx.fillStyle = 'yellow';
188
+ ctx.fill();
189
+
190
+ // Draw green circles for food items
191
+ const foodItems = Math.min(selectedItems.length, 20);
192
+ for (let i = 0; i < foodItems; i++) {
193
+ const angle = (i / foodItems) * 2 * Math.PI;
194
+ const radius = canvas.width / 4;
195
+ const x = canvas.width / 2 + radius * Math.cos(angle);
196
+ const y = canvas.height / 2 + radius * Math.sin(angle);
197
+
198
+ ctx.beginPath();
199
+ ctx.arc(x, y, 10, 0, 2 * Math.PI);
200
+ ctx.fillStyle = 'green';
201
+ ctx.fill();
202
+ }
203
+
204
+ // Draw stack graph
205
+ drawStackGraph(totalNutrients);
206
+
207
+ // Update total calories display
208
+ document.getElementById('total-calories').textContent = totalNutrients.calories;
209
+ }
210
+
211
+ function calculateTotalNutrients() {
212
+ return selectedItems.reduce((total, item) => {
213
+ total.calories += item.calories || 0;
214
+ total.protein += item.protein || 0;
215
+ total.carbs += item.carbs || 0;
216
+ total.fat += item.fat || 0;
217
+ return total;
218
+ }, { calories: 0, protein: 0, carbs: 0, fat: 0 });
219
+ }
220
+
221
+ function drawStackGraph(nutrients) {
222
+ const barWidth = 40;
223
+ const barHeight = 100;
224
+ const startX = canvas.width - barWidth - 10;
225
+ const startY = canvas.height - 10;
226
+
227
+ const totalMacros = nutrients.protein + nutrients.carbs + nutrients.fat;
228
+ const proteinHeight = (nutrients.protein / totalMacros) * barHeight;
229
+ const carbsHeight = (nutrients.carbs / totalMacros) * barHeight;
230
+ const fatHeight = (nutrients.fat / totalMacros) * barHeight;
231
+
232
+ ctx.fillStyle = 'red';
233
+ ctx.fillRect(startX, startY - fatHeight, barWidth, fatHeight);
234
+
235
+ ctx.fillStyle = 'blue';
236
+ ctx.fillRect(startX, startY - fatHeight - carbsHeight, barWidth, carbsHeight);
237
+
238
+ ctx.fillStyle = 'green';
239
+ ctx.fillRect(startX, startY - fatHeight - carbsHeight - proteinHeight, barWidth, proteinHeight);
240
+ }
241
+
242
+ // Add these event listeners
243
+ searchInput.addEventListener('input', searchFood);
244
+
245
+ // Call updateBellyFatVisualization initially to draw the empty plate
246
+ updateBellyFatVisualization();
247
+ });
templates/dashboard.html ADDED
File without changes
templates/index.html ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Belly Fat Visualizer</title>
7
+ <link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
8
+ </head>
9
+ <body>
10
+ <h1>Belly Fat Visualizer</h1>
11
+
12
+ <div id="user-metrics">
13
+ <h2>Enter Your Metrics</h2>
14
+ <form id="user-form">
15
+ <label for="age">Age:</label>
16
+ <input type="number" id="age" required>
17
+
18
+ <label for="gender">Gender:</label>
19
+ <select id="gender" required>
20
+ <option value="male">Male</option>
21
+ <option value="female">Female</option>
22
+ <option value="other">Other</option>
23
+ </select>
24
+
25
+ <label for="height-feet">Height (feet):</label>
26
+ <input type="number" id="height-feet" required>
27
+
28
+ <label for="height-inches">Height (inches):</label>
29
+ <input type="number" id="height-inches" required>
30
+
31
+ <label for="weight">Weight (lbs):</label>
32
+ <input type="number" id="weight" required>
33
+
34
+ <label for="target-weight">Target Weight (lbs):</label>
35
+ <input type="number" id="target-weight" required>
36
+
37
+ <label for="waist">Waist Circumference (inches):</label>
38
+ <input type="number" id="waist" required>
39
+
40
+ <label for="neck">Neck Circumference (inches):</label>
41
+ <input type="number" id="neck" required>
42
+
43
+ <label for="hip">Hip Circumference (inches):</label>
44
+ <input type="number" id="hip" required>
45
+
46
+ <label for="steps">Daily Steps:</label>
47
+ <input type="number" id="steps" required>
48
+
49
+ <label for="standing-hours">Standing Hours:</label>
50
+ <input type="number" id="standing-hours" required>
51
+
52
+ <button type="submit">Calculate</button>
53
+ </form>
54
+ </div>
55
+
56
+ <div id="food-selection">
57
+ <h2>Select Food Items</h2>
58
+ <div class="search-container">
59
+ <input type="text" id="food-search" placeholder="Search for food...">
60
+ <ul id="search-results"></ul>
61
+ </div>
62
+ <div class="flex-container">
63
+ <div>
64
+ <h3>Selected Food Items:</h3>
65
+ <ul id="selected-food-list"></ul>
66
+ </div>
67
+ </div>
68
+ <div>
69
+ <h3>Total Calories: <span id="total-calories">0</span></h3>
70
+ </div>
71
+ </div>
72
+
73
+ <div id="visualization">
74
+ <h2>Belly Fat Visualization</h2>
75
+ <canvas id="belly-fat-canvas" width="300" height="300"></canvas>
76
+ <div id="health-metrics">
77
+ <h3>Your BMI: <span id="bmi-value"></span></h3>
78
+ <h3>Recommended Daily Calories: <span id="recommended-calories"></span></h3>
79
+ <h3>Body Fat Percentage: <span id="body-fat-percentage"></span></h3>
80
+ <h3>Lean Body Mass: <span id="lean-body-mass"></span></h3>
81
+ <h3>Time to Reach Target Weight: <span id="target-weight-time"></span></h3>
82
+ </div>
83
+ </div>
84
+
85
+ <div id="recommendations">
86
+ <h2>Personalized Recommendations</h2>
87
+ <div id="diet-recommendations">
88
+ <h3>Diet Recommendations:</h3>
89
+ <ul id="diet-recommendations-list"></ul>
90
+ </div>
91
+ <div id="exercise-recommendations">
92
+ <h3>Exercise Recommendations:</h3>
93
+ <ul id="exercise-recommendations-list"></ul>
94
+ </div>
95
+ </div>
96
+
97
+ <script src="{{ url_for('static', filename='js/app.js') }}"></script>
98
+ </body>
99
+ </html>
templates/login.html ADDED
File without changes
templates/register.html ADDED
File without changes