Anupam007 commited on
Commit
17407a4
·
verified ·
1 Parent(s): 53f5013

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +269 -530
app.py CHANGED
@@ -4,677 +4,416 @@ import numpy as np
4
  import matplotlib.pyplot as plt
5
  import os
6
  import datetime
 
7
  from sklearn.linear_model import LinearRegression
8
  from sklearn.preprocessing import StandardScaler
9
  import joblib
10
  import warnings
11
  warnings.filterwarnings('ignore')
12
 
13
- # Initialize data directory and file
14
  os.makedirs('data', exist_ok=True)
15
  DATA_FILE = 'data/weight_journal.csv'
 
16
  MODEL_FILE = 'data/weight_prediction_model.pkl'
17
  SCALER_FILE = 'data/weight_prediction_scaler.pkl'
 
18
 
19
- # Initialize or load dataframe
20
  if os.path.exists(DATA_FILE):
21
  df = pd.read_csv(DATA_FILE)
22
- df['date'] = pd.to_datetime(df['date']) # Ensure date is datetime
23
  else:
24
  df = pd.DataFrame(columns=['date', 'weight', 'calories_consumed', 'calories_burned',
25
  'water_intake', 'sleep_hours', 'stress_level', 'mood',
26
  'exercise_minutes', 'notes'])
27
  df.to_csv(DATA_FILE, index=False)
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  def add_entry(date, weight, calories_consumed, calories_burned, water_intake, sleep_hours,
30
  stress_level, mood, exercise_minutes, notes):
31
- """Add a new entry to the journal"""
32
  global df
33
-
34
- # Validate required fields
35
  if not date or not weight:
36
  return "❌ Date and weight are required fields."
37
-
38
  try:
39
- # Convert date to datetime
40
  entry_date = pd.to_datetime(date)
41
-
42
- # Check if an entry with this date already exists
43
  if entry_date in df['date'].values:
44
- return f"❌ An entry for {date} already exists. Use the Update tab to modify it."
45
-
46
- # Create new entry
47
  new_entry = {
48
  'date': entry_date,
49
- 'weight': weight,
50
- 'calories_consumed': calories_consumed if calories_consumed is not None else 0,
51
- 'calories_burned': calories_burned if calories_burned is not None else 0,
52
- 'water_intake': water_intake if water_intake is not None else 0,
53
- 'sleep_hours': sleep_hours if sleep_hours is not None else 0,
54
- 'stress_level': stress_level if stress_level is not None else 5,
55
- 'mood': mood if mood else 'Neutral',
56
- 'exercise_minutes': exercise_minutes if exercise_minutes is not None else 0,
57
- 'notes': notes if notes else ''
58
  }
59
-
60
- # Add to dataframe
61
  df = pd.concat([df, pd.DataFrame([new_entry])], ignore_index=True)
62
- df = df.sort_values('date', ascending=False) # Sort by date descending
63
-
64
- # Save to CSV
65
  df.to_csv(DATA_FILE, index=False)
66
-
67
- # Run prediction update if we have enough data
68
- if len(df) >= 7: # Need at least a week of data for prediction
69
- train_prediction_model()
70
-
71
  return f"✅ Entry for {date} added successfully!"
72
-
73
  except Exception as e:
74
  return f"❌ Error: {str(e)}"
75
 
76
  def view_entries(num_entries=10):
77
- """View most recent entries in the journal"""
78
- global df
79
-
80
  if len(df) == 0:
81
- return pd.DataFrame(columns=['date', 'weight', 'calories_consumed', 'calories_burned',
82
- 'water_intake', 'sleep_hours', 'stress_level', 'mood',
83
- 'exercise_minutes', 'notes'])
84
-
85
- # Sort by date and get most recent entries
86
- sorted_df = df.sort_values('date', ascending=False)
87
-
88
- # Format date for display
89
- display_df = sorted_df.head(int(num_entries)).copy()
90
  display_df['date'] = display_df['date'].dt.strftime('%Y-%m-%d')
91
-
92
  return display_df
93
 
94
  def update_entry(date, weight, calories_consumed, calories_burned, water_intake, sleep_hours,
95
- stress_level, mood, exercise_minutes, notes):
96
- """Update an existing entry in the journal"""
97
  global df
98
-
99
- # Validate date
100
  if not date:
101
  return "❌ Date is required."
102
-
103
  try:
104
- # Convert date to datetime
105
  entry_date = pd.to_datetime(date)
106
-
107
- # Check if an entry with this date exists
108
  if entry_date not in df['date'].values:
109
  return f"❌ No entry found for {date}."
110
-
111
- # Get the row index
112
  idx = df[df['date'] == entry_date].index[0]
113
-
114
- # Update values if provided
115
- if weight is not None:
116
- df.at[idx, 'weight'] = weight
117
- if calories_consumed is not None:
118
- df.at[idx, 'calories_consumed'] = calories_consumed
119
- if calories_burned is not None:
120
- df.at[idx, 'calories_burned'] = calories_burned
121
- if water_intake is not None:
122
- df.at[idx, 'water_intake'] = water_intake
123
- if sleep_hours is not None:
124
- df.at[idx, 'sleep_hours'] = sleep_hours
125
- if stress_level is not None:
126
- df.at[idx, 'stress_level'] = stress_level
127
- if mood:
128
- df.at[idx, 'mood'] = mood
129
- if exercise_minutes is not None:
130
- df.at[idx, 'exercise_minutes'] = exercise_minutes
131
- if notes is not None:
132
- df.at[idx, 'notes'] = notes
133
-
134
- # Save to CSV
135
  df.to_csv(DATA_FILE, index=False)
136
-
137
- # Run prediction update if we have enough data
138
- if len(df) >= 7: # Need at least a week of data for prediction
139
- train_prediction_model()
140
-
141
  return f"✅ Entry for {date} updated successfully!"
142
-
143
  except Exception as e:
144
  return f"❌ Error: {str(e)}"
145
 
146
  def delete_entry(date):
147
- """Delete an entry from the journal"""
148
  global df
149
-
150
- # Validate date
151
  if not date:
152
  return "❌ Date is required."
153
-
154
  try:
155
- # Convert date to datetime
156
  entry_date = pd.to_datetime(date)
157
-
158
- # Check if an entry with this date exists
159
  if entry_date not in df['date'].values:
160
  return f"❌ No entry found for {date}."
161
-
162
- # Delete the entry
163
  df = df[df['date'] != entry_date]
164
-
165
- # Save to CSV
166
  df.to_csv(DATA_FILE, index=False)
167
-
168
- # Run prediction update if we have enough data
169
- if len(df) >= 7: # Need at least a week of data for prediction
170
- train_prediction_model()
171
-
172
  return f"✅ Entry for {date} deleted successfully!"
173
-
174
  except Exception as e:
175
  return f"❌ Error: {str(e)}"
176
 
177
  def load_entry_by_date(date):
178
- """Load an entry by date for viewing or editing"""
179
- global df
180
-
181
- # Validate date
182
  if not date:
183
- return None, None, None, None, None, None, None, None, None, "❌ Date is required."
184
-
185
  try:
186
- # Convert date to datetime
187
  entry_date = pd.to_datetime(date)
188
-
189
- # Check if an entry with this date exists
190
  if entry_date not in df['date'].values:
191
- return None, None, None, None, None, None, None, None, None, f"❌ No entry found for {date}."
192
-
193
- # Get the entry
194
  entry = df[df['date'] == entry_date].iloc[0]
195
-
196
- # Return all fields
197
- return (entry['weight'], entry['calories_consumed'], entry['calories_burned'],
198
- entry['water_intake'], entry['sleep_hours'], entry['stress_level'],
199
- entry['mood'], entry['exercise_minutes'], entry['notes'],
200
- f"✅ Entry for {date} loaded successfully!")
201
-
202
  except Exception as e:
203
- return None, None, None, None, None, None, None, None, None, f"❌ Error: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
205
  def create_weight_plot():
206
- """Create a plot showing weight over time"""
207
- global df
208
-
209
- if len(df) < 3: # Need at least a few entries for a meaningful plot
210
- return "❌ Not enough data to create a plot. Please add more entries.", None
211
-
212
- # Create a copy of the dataframe for plotting
213
- plot_df = df.copy()
214
- plot_df = plot_df.sort_values('date') # Sort by date for proper timeline
215
-
216
- # Create the figure
217
  plt.figure(figsize=(10, 6))
218
- plt.plot(plot_df['date'], plot_df['weight'], marker='o', linestyle='-', color='blue')
 
 
219
  plt.title('Weight Over Time')
220
  plt.xlabel('Date')
221
  plt.ylabel('Weight')
 
222
  plt.grid(True, alpha=0.3)
223
  plt.xticks(rotation=45)
224
-
225
- # Add a trend line if we have enough data
226
- if len(plot_df) >= 5:
227
- x = np.arange(len(plot_df))
228
- y = plot_df['weight'].values
229
- z = np.polyfit(x, y, 1)
230
- p = np.poly1d(z)
231
- plt.plot(plot_df['date'], p(x), "r--", alpha=0.8, label=f"Trend: {z[0]:.2f} per day")
232
- plt.legend()
233
-
234
- # Save the figure to a temporary file
235
  temp_file = "temp_weight_plot.png"
236
  plt.tight_layout()
237
  plt.savefig(temp_file)
238
  plt.close()
 
239
 
240
- return "✅ Plot generated successfully!", temp_file
241
-
242
- def create_calories_plot():
243
- """Create a plot showing calories consumed vs burned over time"""
244
- global df
245
-
246
- if len(df) < 3: # Need at least a few entries for a meaningful plot
247
- return "❌ Not enough data to create a plot. Please add more entries.", None
248
-
249
- # Create a copy of the dataframe for plotting
250
- plot_df = df.copy()
251
- plot_df = plot_df.sort_values('date') # Sort by date for proper timeline
252
-
253
- # Calculate net calories (consumed - burned)
254
- plot_df['net_calories'] = plot_df['calories_consumed'] - plot_df['calories_burned']
255
 
256
- # Create the figure
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  plt.figure(figsize=(10, 6))
258
- plt.bar(plot_df['date'], plot_df['calories_consumed'], alpha=0.7, color='blue', label='Consumed')
259
- plt.bar(plot_df['date'], -plot_df['calories_burned'], alpha=0.7, color='red', label='Burned')
260
- plt.plot(plot_df['date'], plot_df['net_calories'], marker='o', linestyle='-', color='green', label='Net Calories')
261
-
262
- plt.title('Calories Consumed vs. Burned')
263
  plt.xlabel('Date')
264
- plt.ylabel('Calories')
265
  plt.grid(True, alpha=0.3)
266
  plt.xticks(rotation=45)
267
- plt.axhline(y=0, color='black', linestyle='-', alpha=0.3)
268
  plt.legend()
269
-
270
- # Save the figure to a temporary file
271
- temp_file = "temp_calories_plot.png"
272
- plt.tight_layout()
273
- plt.savefig(temp_file)
274
- plt.close()
275
-
276
- return "✅ Plot generated successfully!", temp_file
277
-
278
- def create_water_sleep_plot():
279
- """Create a plot showing water intake vs sleep hours over time"""
280
- global df
281
-
282
- if len(df) < 3: # Need at least a few entries for a meaningful plot
283
- return "❌ Not enough data to create a plot. Please add more entries.", None
284
-
285
- # Create a copy of the dataframe for plotting
286
- plot_df = df.copy()
287
- plot_df = plot_df.sort_values('date') # Sort by date for proper timeline
288
-
289
- # Create a figure with dual y-axis
290
- fig, ax1 = plt.subplots(figsize=(10, 6))
291
-
292
- # Plot water intake on left y-axis
293
- color = 'tab:blue'
294
- ax1.set_xlabel('Date')
295
- ax1.set_ylabel('Water Intake (cups)', color=color)
296
- ax1.plot(plot_df['date'], plot_df['water_intake'], color=color, marker='o', label='Water Intake')
297
- ax1.tick_params(axis='y', labelcolor=color)
298
-
299
- # Create second y-axis for sleep hours
300
- ax2 = ax1.twinx()
301
- color = 'tab:red'
302
- ax2.set_ylabel('Sleep Hours', color=color)
303
- ax2.plot(plot_df['date'], plot_df['sleep_hours'], color=color, marker='s', label='Sleep Hours')
304
- ax2.tick_params(axis='y', labelcolor=color)
305
-
306
- # Rotate date labels for better readability
307
- fig.autofmt_xdate()
308
-
309
- # Add title and grid
310
- plt.title('Water Intake vs Sleep Hours Over Time')
311
- ax1.grid(True, alpha=0.3)
312
-
313
- # Add a legend
314
- lines1, labels1 = ax1.get_legend_handles_labels()
315
- lines2, labels2 = ax2.get_legend_handles_labels()
316
- ax1.legend(lines1 + lines2, labels1 + labels2, loc='best')
317
-
318
- # Save the figure to a temporary file
319
- temp_file = "temp_water_sleep_plot.png"
320
- plt.tight_layout()
321
- plt.savefig(temp_file)
322
- plt.close()
323
-
324
- return "✅ Plot generated successfully!", temp_file
325
 
326
  def train_prediction_model():
327
- """Train a machine learning model to predict weight based on other factors"""
328
- global df
329
-
330
- if len(df) < 7: # Need at least a week of data
331
- return "❌ Not enough data to train model. Please add at least 7 entries."
332
-
333
- try:
334
- # Create a copy and sort by date
335
- model_df = df.copy()
336
- model_df = model_df.sort_values('date')
337
-
338
- # Create features
339
- features = ['calories_consumed', 'calories_burned', 'water_intake',
340
- 'sleep_hours', 'stress_level', 'exercise_minutes']
341
- X = model_df[features]
342
- y = model_df['weight']
343
-
344
- # Check for missing values and fill with medians
345
- for col in X.columns:
346
- if X[col].isnull().any():
347
- X[col] = X[col].fillna(X[col].median())
348
-
349
- # Scale features
350
- scaler = StandardScaler()
351
- X_scaled = scaler.fit_transform(X)
352
-
353
- # Train model
354
- model = LinearRegression()
355
- model.fit(X_scaled, y)
356
-
357
- # Save model and scaler
358
- joblib.dump(model, MODEL_FILE)
359
- joblib.dump(scaler, SCALER_FILE)
360
-
361
- # Calculate model performance
362
- y_pred = model.predict(X_scaled)
363
- mse = np.mean((y - y_pred) ** 2)
364
- rmse = np.sqrt(mse)
365
-
366
- # Calculate feature importance
367
- importance = pd.DataFrame({
368
- 'Feature': features,
369
- 'Importance': np.abs(model.coef_)
370
- }).sort_values('Importance', ascending=False)
371
-
372
- # Generate report
373
- report = f"✅ Model trained successfully!\n\n"
374
- report += f"Model performance: RMSE = {rmse:.2f}\n\n"
375
- report += "Feature Importance:\n"
376
- for _, row in importance.iterrows():
377
- report += f"- {row['Feature']}: {row['Importance']:.2f}\n"
378
-
379
- return report
380
-
381
- except Exception as e:
382
- return f"❌ Error training model: {str(e)}"
383
-
384
- def predict_weight_trajectory(days=30, calorie_adjustment=0, water_adjustment=0,
385
- sleep_adjustment=0, stress_adjustment=0, exercise_adjustment=0):
386
- """Predict weight trajectory for the next N days based on current trends and adjustments"""
387
- global df
388
-
389
- if len(df) < 7: # Need at least a week of data
390
- return "❌ Not enough data for prediction. Please add at least 7 entries.", None, ""
391
-
392
- if not os.path.exists(MODEL_FILE) or not os.path.exists(SCALER_FILE):
393
- return "❌ Prediction model not trained. Please train the model first.", None, ""
394
-
395
- try:
396
- # Load model and scaler
397
- model = joblib.load(MODEL_FILE)
398
- scaler = joblib.load(SCALER_FILE)
399
-
400
- # Get the most recent entry as baseline
401
- last_entry = df.sort_values('date', ascending=False).iloc[0]
402
-
403
- # Get average values from the last week for prediction
404
- last_week = df.sort_values('date', ascending=False).head(7)
405
- avg_calories_consumed = last_week['calories_consumed'].mean() + calorie_adjustment
406
- avg_calories_burned = last_week['calories_burned'].mean() + calorie_adjustment # We apply same adjustment
407
- avg_water = last_week['water_intake'].mean() + water_adjustment
408
- avg_sleep = last_week['sleep_hours'].mean() + sleep_adjustment
409
- avg_stress = last_week['stress_level'].mean() + stress_adjustment
410
- avg_exercise = last_week['exercise_minutes'].mean() + exercise_adjustment
411
-
412
- # Create prediction data
413
- future_dates = [last_entry['date'] + datetime.timedelta(days=i) for i in range(1, days+1)]
414
- predict_data = pd.DataFrame({
415
- 'date': future_dates,
416
- 'calories_consumed': [avg_calories_consumed] * days,
417
- 'calories_burned': [avg_calories_burned] * days,
418
- 'water_intake': [avg_water] * days,
419
- 'sleep_hours': [avg_sleep] * days,
420
- 'stress_level': [avg_stress] * days,
421
- 'exercise_minutes': [avg_exercise] * days
422
- })
423
-
424
- # Scale features for prediction
425
- features = ['calories_consumed', 'calories_burned', 'water_intake',
426
- 'sleep_hours', 'stress_level', 'exercise_minutes']
427
- X_pred = predict_data[features]
428
- X_pred_scaled = scaler.transform(X_pred)
429
-
430
- # Predict weights
431
- predicted_weights = model.predict(X_pred_scaled)
432
- predict_data['weight'] = predicted_weights
433
-
434
- # Create plot
435
- plt.figure(figsize=(10, 6))
436
-
437
- # Plot historical data
438
- hist_data = df.copy().sort_values('date')
439
- plt.plot(hist_data['date'], hist_data['weight'], 'o-', color='blue', label='Historical')
440
-
441
- # Plot prediction
442
- plt.plot(predict_data['date'], predict_data['weight'], 'o--', color='red', label='Predicted')
443
-
444
- # Add details
445
- plt.title('Weight Trajectory Prediction')
446
- plt.xlabel('Date')
447
- plt.ylabel('Weight')
448
- plt.grid(True, alpha=0.3)
449
- plt.xticks(rotation=45)
450
- plt.legend()
451
-
452
- # Calculate metrics
453
- start_weight = hist_data['weight'].iloc[-1]
454
- end_weight = predict_data['weight'].iloc[-1]
455
- weight_change = end_weight - start_weight
456
-
457
- # Generate report
458
- report = f"✅ Prediction completed!\n\n"
459
- report += f"Starting weight: {start_weight:.1f}\n"
460
- report += f"Predicted weight after {days} days: {end_weight:.1f}\n"
461
- report += f"Projected change: {weight_change:.1f} ({weight_change/start_weight*100:.1f}%)\n"
462
-
463
- # Generate recommendations
464
- if weight_change > 0:
465
- recommendations = "## 📊 Recommendations for Weight Loss:\n\n"
466
- recommendations += "Based on the prediction model, here are personalized recommendations:\n\n"
467
-
468
- if calorie_adjustment >= 0:
469
- recommendations += "1. **Reduce calorie intake** by 300-500 calories per day\n"
470
- if avg_exercise < 30:
471
- recommendations += "2. **Increase exercise** to at least 30 minutes per day\n"
472
- if avg_water < 8:
473
- recommendations += "3. **Drink more water**, aim for 8+ cups daily\n"
474
- if avg_sleep < 7:
475
- recommendations += "4. **Improve sleep quality** to 7-8 hours per night\n"
476
- if avg_stress > 5:
477
- recommendations += "5. **Implement stress management techniques** like meditation\n"
478
- else:
479
- recommendations = "## 📊 Recommendations to Maintain Progress:\n\n"
480
- recommendations += "Based on the prediction model, you're on track! Here are tips to maintain progress:\n\n"
481
- recommendations += "1. **Keep consistent** with your current habits\n"
482
- recommendations += "2. **Add variety** to your exercise routine to stay engaged\n"
483
- recommendations += "3. **Continue tracking** your metrics to monitor trends\n"
484
-
485
- return report, plt, recommendations
486
-
487
- except Exception as e:
488
- return f"❌ Error generating prediction: {str(e)}", None, ""
489
-
490
- def create_sample_data():
491
- """Create sample data for demonstration purposes"""
492
- # Start date (30 days ago)
493
- start_date = datetime.datetime.now() - datetime.timedelta(days=30)
494
-
495
- # Initialize weight and other parameters
496
- initial_weight = 180 # Example starting weight
497
-
498
- # Create sample dataframe
499
- sample_data = []
500
-
501
- for i in range(30):
502
- # Current date
503
- current_date = start_date + datetime.timedelta(days=i)
504
-
505
- # Weight trend (gradually decreasing with some fluctuation)
506
- # Add some randomness for realism
507
- weight_change = -0.1 * i / 30 # Gradual decrease
508
- daily_fluctuation = np.random.normal(0, 0.3) # Random daily fluctuation
509
- current_weight = initial_weight + (weight_change * initial_weight) + daily_fluctuation
510
-
511
- # Other parameters (with realistic values and some correlation to weight loss)
512
- calories_consumed = np.random.randint(1800, 2300)
513
- calories_burned = np.random.randint(2000, 2500)
514
- water_intake = np.random.randint(5, 10)
515
- sleep_hours = np.random.normal(7, 0.5)
516
- stress_level = np.random.randint(3, 8)
517
- exercise_minutes = np.random.randint(20, 60)
518
-
519
- # Mood (correlated somewhat with other factors)
520
- mood_options = ['Great', 'Good', 'Neutral', 'Poor']
521
- mood_probs = [0.2, 0.5, 0.2, 0.1] # Probability distribution
522
- mood = np.random.choice(mood_options, p=mood_probs)
523
-
524
- # Notes
525
- notes = ''
526
-
527
- # Add to sample data
528
- sample_data.append({
529
- 'date': current_date,
530
- 'weight': round(current_weight, 1),
531
- 'calories_consumed': calories_consumed,
532
- 'calories_burned': calories_burned,
533
- 'water_intake': water_intake,
534
- 'sleep_hours': round(sleep_hours, 1),
535
- 'stress_level': stress_level,
536
- 'mood': mood,
537
- 'exercise_minutes': exercise_minutes,
538
- 'notes': notes
539
- })
540
-
541
- return pd.DataFrame(sample_data)
542
 
543
  # Gradio Interface
544
- with gr.Blocks(title="Weight Loss Journal", theme=gr.themes.Soft()) as iface:
545
- gr.Markdown("# 🏋️‍♀️ Weight Loss Journal")
 
 
 
 
 
 
546
 
547
  with gr.Tab("Add Entry"):
548
  with gr.Row():
549
  with gr.Column():
550
  date_input = gr.Textbox(label="Date (YYYY-MM-DD)")
551
- weight_input = gr.Number(label="Weight")
552
  calories_consumed_input = gr.Number(label="Calories Consumed")
553
  calories_burned_input = gr.Number(label="Calories Burned")
554
  water_intake_input = gr.Number(label="Water Intake (cups)")
555
  sleep_hours_input = gr.Number(label="Sleep Hours")
556
- stress_level_input = gr.Slider(minimum=1, maximum=10, step=1, label="Stress Level (1-10)")
557
- mood_input = gr.Dropdown(choices=['Great', 'Good', 'Neutral', 'Poor'], label="Mood")
558
  exercise_minutes_input = gr.Number(label="Exercise Minutes")
559
  notes_input = gr.Textbox(label="Notes")
560
  add_button = gr.Button("Add Entry", variant="primary")
561
  add_output = gr.Markdown()
562
- add_button.click(add_entry,
563
- inputs=[date_input, weight_input, calories_consumed_input, calories_burned_input,
564
- water_intake_input, sleep_hours_input, stress_level_input, mood_input,
565
- exercise_minutes_input, notes_input],
566
- outputs=add_output)
567
 
568
  with gr.Tab("View Entries"):
569
- num_entries_view = gr.Slider(minimum=5, maximum=30, step=5, value=10, label="Number of Entries to View")
570
- view_button = gr.Button("View Entries", variant="secondary")
571
  view_output = gr.DataFrame()
572
  view_button.click(view_entries, inputs=num_entries_view, outputs=view_output)
573
 
574
  with gr.Tab("Update Entry"):
575
- date_update_input = gr.Textbox(label="Date to Update (YYYY-MM-DD)")
576
  with gr.Row():
577
  with gr.Column():
578
- weight_update_input = gr.Number(label="Weight")
579
  calories_consumed_update_input = gr.Number(label="Calories Consumed")
580
  calories_burned_update_input = gr.Number(label="Calories Burned")
581
  water_intake_update_input = gr.Number(label="Water Intake (cups)")
582
  sleep_hours_update_input = gr.Number(label="Sleep Hours")
583
- stress_level_update_input = gr.Slider(minimum=1, maximum=10, step=1, label="Stress Level (1-10)")
584
- mood_update_input = gr.Dropdown(choices=['Great', 'Good', 'Neutral', 'Poor'], label="Mood")
585
  exercise_minutes_update_input = gr.Number(label="Exercise Minutes")
586
  notes_update_input = gr.Textbox(label="Notes")
587
- update_button = gr.Button("Update Entry", variant="primary")
588
  update_output = gr.Markdown()
589
- update_button.click(update_entry,
590
- inputs=[date_update_input, weight_update_input, calories_consumed_update_input,
591
- calories_burned_update_input, water_intake_update_input, sleep_hours_update_input,
592
- stress_level_update_input, mood_update_input, exercise_minutes_update_input,
593
- notes_update_input],
594
- outputs=update_output)
595
-
596
- with gr.Tab("Delete Entry"):
597
- date_delete_input = gr.Textbox(label="Date to Delete (YYYY-MM-DD)")
598
- delete_button = gr.Button("Delete Entry", variant="secondary")
599
- delete_output = gr.Markdown()
600
- delete_button.click(delete_entry, inputs=date_delete_input, outputs=delete_output)
601
-
602
- with gr.Tab("Load Entry"):
603
- date_load_input = gr.Textbox(label="Date to Load (YYYY-MM-DD)")
604
- load_button = gr.Button("Load Entry", variant="secondary")
605
- with gr.Row():
606
- with gr.Column():
607
- weight_load_output = gr.Number(label="Weight")
608
- calories_consumed_load_output = gr.Number(label="Calories Consumed")
609
- calories_burned_load_output = gr.Number(label="Calories Burned")
610
- water_intake_load_output = gr.Number(label="Water Intake (cups)")
611
- sleep_hours_load_output = gr.Number(label="Sleep Hours")
612
- stress_level_load_output = gr.Slider(minimum=1, maximum=10, step=1, label="Stress Level (1-10)")
613
- mood_load_output = gr.Dropdown(choices=['Great', 'Good', 'Neutral', 'Poor'], label="Mood")
614
- exercise_minutes_load_output = gr.Number(label="Exercise Minutes")
615
- notes_load_output = gr.Textbox(label="Notes")
616
- load_output = gr.Markdown()
617
- load_button.click(load_entry_by_date, inputs=date_load_input, outputs=[weight_load_output, calories_consumed_load_output, calories_burned_load_output, water_intake_load_output, sleep_hours_load_output, stress_level_load_output, mood_load_output, exercise_minutes_load_output, notes_load_output, load_output])
618
 
619
  with gr.Tab("Analytics"):
620
- with gr.Row():
621
- with gr.Column():
622
- weight_plot_button = gr.Button("Weight Over Time", variant="secondary")
623
- weight_plot_output_text = gr.Markdown()
624
- weight_plot_output = gr.Image()
625
- with gr.Column():
626
- calories_plot_button = gr.Button("Calories Consumed vs. Burned", variant="secondary")
627
- calories_plot_output_text = gr.Markdown()
628
- calories_plot_output = gr.Image()
629
- with gr.Column():
630
- water_sleep_plot_button = gr.Button("Water Intake vs. Sleep Hours", variant="secondary")
631
- water_sleep_plot_output_text = gr.Markdown()
632
- water_sleep_plot_output = gr.Image()
633
-
634
- weight_plot_button.click(create_weight_plot, inputs=[], outputs=[weight_plot_output_text, weight_plot_output])
635
- calories_plot_button.click(create_calories_plot, inputs=[], outputs=[calories_plot_output_text, calories_plot_output])
636
- water_sleep_plot_button.click(create_water_sleep_plot, inputs=[], outputs=[water_sleep_plot_output_text, water_sleep_plot_output])
637
 
638
  with gr.Tab("Prediction"):
639
- with gr.Row():
640
- with gr.Column():
641
- days_input = gr.Slider(minimum=7, maximum=90, step=7, value=30, label="Days to Predict")
642
- calorie_adjustment_input = gr.Number(label="Calorie Deficit Adjustment")
643
- water_adjustment_input = gr.Number(label="Water Intake Adjustment")
644
- sleep_adjustment_input = gr.Number(label="Sleep Hours Adjustment")
645
- stress_adjustment_input = gr.Number(label="Stress Level Adjustment")
646
- exercise_adjustment_input = gr.Number(label="Exercise Minutes Adjustment")
647
- predict_button = gr.Button("Predict Weight Trajectory", variant="primary")
648
  prediction_output_text = gr.Markdown()
649
  prediction_plot_output = gr.Plot()
650
  recommendation_output = gr.Markdown()
651
- predict_button.click(predict_weight_trajectory,
652
- inputs=[days_input, calorie_adjustment_input, water_adjustment_input,
653
- sleep_adjustment_input, stress_adjustment_input, exercise_adjustment_input],
654
  outputs=[prediction_output_text, prediction_plot_output, recommendation_output])
655
 
656
  with gr.Tab("Train Model"):
657
- train_button = gr.Button("Train Prediction Model", variant="primary")
658
  train_output = gr.Markdown()
659
- train_button.click(train_prediction_model, inputs=[], outputs=train_output)
660
 
661
- with gr.Tab("Sample Data"):
662
- sample_button = gr.Button("Generate and Load Sample Data", variant="secondary")
663
- sample_output = gr.Markdown()
 
 
 
664
 
 
665
  def load_sample_data():
666
- """Load sample data into the dataframe"""
667
  global df
668
- sample_df = create_sample_data()
669
- df = pd.concat([df, sample_df], ignore_index=True)
670
- df['date'] = pd.to_datetime(df['date']) # Ensure date is datetime
671
- df = df.sort_values('date', ascending=False) # Sort by date descending
672
- df.to_csv('data/weight_journal.csv', index=False)
673
-
674
- # Run prediction update
675
- if len(df) >= 7: # Need at least a week of data for prediction
676
- train_prediction_model()
677
- return "✅ Sample data loaded successfully! Please refresh the other tabs for results."
 
 
 
 
 
 
 
 
 
 
678
 
679
- sample_button.click(load_sample_data, inputs=[], outputs=sample_output)
680
  iface.launch(debug=False)
 
4
  import matplotlib.pyplot as plt
5
  import os
6
  import datetime
7
+ import json
8
  from sklearn.linear_model import LinearRegression
9
  from sklearn.preprocessing import StandardScaler
10
  import joblib
11
  import warnings
12
  warnings.filterwarnings('ignore')
13
 
14
+ # Initialize data directory and files
15
  os.makedirs('data', exist_ok=True)
16
  DATA_FILE = 'data/weight_journal.csv'
17
+ GOAL_FILE = 'data/goal.json'
18
  MODEL_FILE = 'data/weight_prediction_model.pkl'
19
  SCALER_FILE = 'data/weight_prediction_scaler.pkl'
20
+ ACHIEVEMENTS_FILE = 'data/achievements.json'
21
 
22
+ # Load or initialize dataframe
23
  if os.path.exists(DATA_FILE):
24
  df = pd.read_csv(DATA_FILE)
25
+ df['date'] = pd.to_datetime(df['date'])
26
  else:
27
  df = pd.DataFrame(columns=['date', 'weight', 'calories_consumed', 'calories_burned',
28
  'water_intake', 'sleep_hours', 'stress_level', 'mood',
29
  'exercise_minutes', 'notes'])
30
  df.to_csv(DATA_FILE, index=False)
31
 
32
+ # Load or initialize goals
33
+ if os.path.exists(GOAL_FILE):
34
+ with open(GOAL_FILE, 'r') as f:
35
+ goal = json.load(f)
36
+ else:
37
+ goal = {'target_weight': None, 'target_date': None}
38
+
39
+ # Load or initialize achievements
40
+ if os.path.exists(ACHIEVEMENTS_FILE):
41
+ with open(ACHIEVEMENTS_FILE, 'r') as f:
42
+ achievements = json.load(f)
43
+ else:
44
+ achievements = []
45
+
46
+ # Load Indian food dataset with robust column handling
47
+ try:
48
+ from datasets import load_dataset
49
+ ds = load_dataset("Anupam007/nutarian-Indianfood")
50
+ food_df = pd.DataFrame(ds['train'])
51
+ print(f"Successfully loaded Indian food dataset with {len(food_df)} items")
52
+ print("Columns in dataset:", food_df.columns.tolist())
53
+ # Rename potential column names to 'name' for consistency
54
+ if 'name' not in food_df.columns:
55
+ if 'food_name' in food_df.columns:
56
+ food_df = food_df.rename(columns={'food_name': 'name'})
57
+ elif 'item' in food_df.columns:
58
+ food_df = food_df.rename(columns={'item': 'name'})
59
+ else:
60
+ raise ValueError("No suitable 'name' column found in dataset")
61
+ # Ensure 'calories' column exists
62
+ if 'calories' not in food_df.columns and 'calorie_count' in food_df.columns:
63
+ food_df = food_df.rename(columns={'calorie_count': 'calories'})
64
+ elif 'calories' not in food_df.columns:
65
+ raise ValueError("No 'calories' column found in dataset")
66
+ except Exception as e:
67
+ print(f"Failed to load dataset or process columns: {e}. Using fallback data.")
68
+ food_df = pd.DataFrame({
69
+ 'name': ['Rice', 'Dal', 'Roti', 'Chicken Curry'],
70
+ 'calories': [130, 150, 80, 200]
71
+ })
72
+
73
+ # Core Functions
74
  def add_entry(date, weight, calories_consumed, calories_burned, water_intake, sleep_hours,
75
  stress_level, mood, exercise_minutes, notes):
 
76
  global df
 
 
77
  if not date or not weight:
78
  return "❌ Date and weight are required fields."
 
79
  try:
 
80
  entry_date = pd.to_datetime(date)
 
 
81
  if entry_date in df['date'].values:
82
+ return f"❌ An entry for {date} already exists."
 
 
83
  new_entry = {
84
  'date': entry_date,
85
+ 'weight': float(weight),
86
+ 'calories_consumed': float(calories_consumed or 0),
87
+ 'calories_burned': float(calories_burned or 0),
88
+ 'water_intake': float(water_intake or 0),
89
+ 'sleep_hours': float(sleep_hours or 0),
90
+ 'stress_level': int(stress_level or 5),
91
+ 'mood': mood or 'Neutral',
92
+ 'exercise_minutes': float(exercise_minutes or 0),
93
+ 'notes': notes or ''
94
  }
 
 
95
  df = pd.concat([df, pd.DataFrame([new_entry])], ignore_index=True)
96
+ df = df.sort_values('date', ascending=False)
 
 
97
  df.to_csv(DATA_FILE, index=False)
98
+ update_achievements()
 
 
 
 
99
  return f"✅ Entry for {date} added successfully!"
 
100
  except Exception as e:
101
  return f"❌ Error: {str(e)}"
102
 
103
  def view_entries(num_entries=10):
 
 
 
104
  if len(df) == 0:
105
+ return pd.DataFrame(columns=df.columns)
106
+ display_df = df.sort_values('date', ascending=False).head(int(num_entries)).copy()
 
 
 
 
 
 
 
107
  display_df['date'] = display_df['date'].dt.strftime('%Y-%m-%d')
 
108
  return display_df
109
 
110
  def update_entry(date, weight, calories_consumed, calories_burned, water_intake, sleep_hours,
111
+ stress_level, mood, exercise_minutes, notes):
 
112
  global df
 
 
113
  if not date:
114
  return "❌ Date is required."
 
115
  try:
 
116
  entry_date = pd.to_datetime(date)
 
 
117
  if entry_date not in df['date'].values:
118
  return f"❌ No entry found for {date}."
 
 
119
  idx = df[df['date'] == entry_date].index[0]
120
+ if weight is not None: df.at[idx, 'weight'] = float(weight)
121
+ if calories_consumed is not None: df.at[idx, 'calories_consumed'] = float(calories_consumed)
122
+ if calories_burned is not None: df.at[idx, 'calories_burned'] = float(calories_burned)
123
+ if water_intake is not None: df.at[idx, 'water_intake'] = float(water_intake)
124
+ if sleep_hours is not None: df.at[idx, 'sleep_hours'] = float(sleep_hours)
125
+ if stress_level is not None: df.at[idx, 'stress_level'] = int(stress_level)
126
+ if mood: df.at[idx, 'mood'] = mood
127
+ if exercise_minutes is not None: df.at[idx, 'exercise_minutes'] = float(exercise_minutes)
128
+ if notes is not None: df.at[idx, 'notes'] = notes
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  df.to_csv(DATA_FILE, index=False)
130
+ update_achievements()
 
 
 
 
131
  return f"✅ Entry for {date} updated successfully!"
 
132
  except Exception as e:
133
  return f"❌ Error: {str(e)}"
134
 
135
  def delete_entry(date):
 
136
  global df
 
 
137
  if not date:
138
  return "❌ Date is required."
 
139
  try:
 
140
  entry_date = pd.to_datetime(date)
 
 
141
  if entry_date not in df['date'].values:
142
  return f"❌ No entry found for {date}."
 
 
143
  df = df[df['date'] != entry_date]
 
 
144
  df.to_csv(DATA_FILE, index=False)
145
+ update_achievements()
 
 
 
 
146
  return f"✅ Entry for {date} deleted successfully!"
 
147
  except Exception as e:
148
  return f"❌ Error: {str(e)}"
149
 
150
  def load_entry_by_date(date):
 
 
 
 
151
  if not date:
152
+ return [None] * 9 + ["❌ Date is required."]
 
153
  try:
 
154
  entry_date = pd.to_datetime(date)
 
 
155
  if entry_date not in df['date'].values:
156
+ return [None] * 9 + [f"❌ No entry found for {date}."]
 
 
157
  entry = df[df['date'] == entry_date].iloc[0]
158
+ return [entry[col] for col in ['weight', 'calories_consumed', 'calories_burned', 'water_intake',
159
+ 'sleep_hours', 'stress_level', 'mood', 'exercise_minutes', 'notes']] + \
160
+ [f"✅ Entry for {date} loaded successfully!"]
 
 
 
 
161
  except Exception as e:
162
+ return [None] * 9 + [f"❌ Error: {str(e)}"]
163
+
164
+ # Visualization Functions
165
+ def create_dashboard():
166
+ if len(df) < 3:
167
+ return "❌ Not enough data.", None
168
+ fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15, 5))
169
+ df.sort_values('date').plot(x='date', y='weight', ax=ax1, title="Weight Trend", marker='o', color='blue')
170
+ df.sort_values('date').plot(x='date', y=['calories_consumed', 'calories_burned'], ax=ax2, title="Calories", kind='bar')
171
+ df.sort_values('date').plot(x='date', y='water_intake', ax=ax3, title="Water Intake", marker='s', color='green')
172
+ for ax in [ax1, ax2, ax3]:
173
+ ax.grid(True, alpha=0.3)
174
+ ax.tick_params(axis='x', rotation=45)
175
+ plt.tight_layout()
176
+ return "✅ Dashboard ready!", fig
177
 
178
  def create_weight_plot():
179
+ if len(df) < 3:
180
+ return "❌ Not enough data.", None
181
+ plot_df = df.sort_values('date')
 
 
 
 
 
 
 
 
182
  plt.figure(figsize=(10, 6))
183
+ plt.plot(plot_df['date'], plot_df['weight'], marker='o', linestyle='-', color='blue', label='Weight')
184
+ if goal['target_weight']:
185
+ plt.axhline(y=goal['target_weight'], color='green', linestyle='--', label='Goal')
186
  plt.title('Weight Over Time')
187
  plt.xlabel('Date')
188
  plt.ylabel('Weight')
189
+ plt.legend()
190
  plt.grid(True, alpha=0.3)
191
  plt.xticks(rotation=45)
 
 
 
 
 
 
 
 
 
 
 
192
  temp_file = "temp_weight_plot.png"
193
  plt.tight_layout()
194
  plt.savefig(temp_file)
195
  plt.close()
196
+ return "✅ Plot generated!", temp_file
197
 
198
+ # Goal Setting
199
+ def set_goal(target_weight, target_date):
200
+ global goal
201
+ if not target_weight or not target_date:
202
+ return "❌ Target weight and date are required."
203
+ try:
204
+ goal = {'target_weight': float(target_weight), 'target_date': pd.to_datetime(target_date).strftime('%Y-%m-%d')}
205
+ with open(GOAL_FILE, 'w') as f:
206
+ json.dump(goal, f)
207
+ return "✅ Goal set successfully!"
208
+ except Exception as e:
209
+ return f"❌ Error: {str(e)}"
 
 
 
210
 
211
+ def view_goal():
212
+ if not goal['target_weight']:
213
+ return "No goal set yet."
214
+ return f"Target Weight: {goal['target_weight']} | Target Date: {goal['target_date']}\n" + \
215
+ f"Progress: {((df['weight'].iloc[-1] - goal['target_weight']) / (df['weight'].iloc[0] - goal['target_weight']) * 100):.1f}%"
216
+
217
+ # Achievements
218
+ def update_achievements():
219
+ global achievements
220
+ new_achievements = []
221
+ if len(df) >= 1 and "First Entry 🏅" not in achievements:
222
+ new_achievements.append("First Entry 🏅")
223
+ if len(df) >= 7 and df['date'].diff().mean().days <= 1 and "Consistency Star 🌟" not in achievements:
224
+ new_achievements.append("Consistency Star 🌟")
225
+ if len(df) >= 7 and df['water_intake'].tail(7).mean() >= 8 and "Water Warrior 💧" not in achievements:
226
+ new_achievements.append("Water Warrior 💧")
227
+ achievements.extend(new_achievements)
228
+ with open(ACHIEVEMENTS_FILE, 'w') as f:
229
+ json.dump(achievements, f)
230
+ return "\n".join(achievements) or "No achievements yet—keep going!"
231
+
232
+ # Prediction
233
+ def predict_weight_trajectory(days=30, calorie_adjustment=0, exercise_adjustment=0):
234
+ if len(df) < 7 or not os.path.exists(MODEL_FILE):
235
+ return "❌ Not enough data or model not trained.", None, ""
236
+ model = joblib.load(MODEL_FILE)
237
+ scaler = joblib.load(SCALER_FILE)
238
+ last_entry = df.sort_values('date', ascending=False).iloc[0]
239
+ last_week = df.sort_values('date', ascending=False).head(7)
240
+ avg_calories_consumed = last_week['calories_consumed'].mean() + calorie_adjustment
241
+ avg_calories_burned = last_week['calories_burned'].mean() + calorie_adjustment
242
+ avg_exercise = last_week['exercise_minutes'].mean() + exercise_adjustment
243
+ predict_data = pd.DataFrame({
244
+ 'date': [last_entry['date'] + datetime.timedelta(days=i) for i in range(1, days+1)],
245
+ 'calories_consumed': [avg_calories_consumed] * days,
246
+ 'calories_burned': [avg_calories_burned] * days,
247
+ 'water_intake': [last_week['water_intake'].mean()] * days,
248
+ 'sleep_hours': [last_week['sleep_hours'].mean()] * days,
249
+ 'stress_level': [last_week['stress_level'].mean()] * days,
250
+ 'exercise_minutes': [avg_exercise] * days
251
+ })
252
+ X_pred = predict_data[['calories_consumed', 'calories_burned', 'water_intake', 'sleep_hours', 'stress_level', 'exercise_minutes']]
253
+ X_pred_scaled = scaler.transform(X_pred)
254
+ predict_data['weight'] = model.predict(X_pred_scaled)
255
+
256
  plt.figure(figsize=(10, 6))
257
+ plt.plot(df['date'], df['weight'], 'o-', color='blue', label='Historical')
258
+ plt.plot(predict_data['date'], predict_data['weight'], 'o--', color='red', label='Predicted')
259
+ if goal['target_weight']:
260
+ plt.axhline(y=goal['target_weight'], color='green', linestyle='--', label='Goal')
261
+ plt.title('Weight Trajectory Prediction')
262
  plt.xlabel('Date')
263
+ plt.ylabel('Weight')
264
  plt.grid(True, alpha=0.3)
265
  plt.xticks(rotation=45)
 
266
  plt.legend()
267
+
268
+ start_weight = df['weight'].iloc[-1]
269
+ end_weight = predict_data['weight'].iloc[-1]
270
+ report = f"Starting weight: {start_weight:.1f}\nPredicted weight after {days} days: {end_weight:.1f}\n" + \
271
+ f"Change: {end_weight - start_weight:.1f}"
272
+ recommendations = "Keep tracking consistently!" if end_weight < start_weight else "Consider reducing calories."
273
+ return report, plt, recommendations
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
 
275
  def train_prediction_model():
276
+ if len(df) < 7:
277
+ return "❌ Not enough data."
278
+ model_df = df.sort_values('date')
279
+ features = ['calories_consumed', 'calories_burned', 'water_intake', 'sleep_hours', 'stress_level', 'exercise_minutes']
280
+ X = model_df[features].fillna(model_df[features].median())
281
+ y = model_df['weight']
282
+ scaler = StandardScaler()
283
+ X_scaled = scaler.fit_transform(X)
284
+ model = LinearRegression()
285
+ model.fit(X_scaled, y)
286
+ joblib.dump(model, MODEL_FILE)
287
+ joblib.dump(scaler, SCALER_FILE)
288
+ return "✅ Model trained!"
289
+
290
+ # Food Log
291
+ def log_food(food_name, quantity):
292
+ if food_name not in food_df['name'].values:
293
+ return "❌ Food not found."
294
+ calories = food_df[food_df['name'] == food_name]['calories'].iloc[0] * quantity
295
+ return f"✅ Logged {quantity} of {food_name} ({calories} calories). Add to your entry!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
 
297
  # Gradio Interface
298
+ with gr.Blocks(title="FitJourney", theme=gr.themes.Soft(primary_hue="blue")) as iface:
299
+ gr.Markdown("# 🏋️‍♀️ FitJourney - Your Weight Loss Companion")
300
+
301
+ with gr.Tab("Dashboard"):
302
+ dashboard_button = gr.Button("Show Dashboard", variant="primary")
303
+ dashboard_text = gr.Markdown()
304
+ dashboard_plot = gr.Plot()
305
+ dashboard_button.click(create_dashboard, outputs=[dashboard_text, dashboard_plot])
306
 
307
  with gr.Tab("Add Entry"):
308
  with gr.Row():
309
  with gr.Column():
310
  date_input = gr.Textbox(label="Date (YYYY-MM-DD)")
311
+ weight_input = gr.Number(label="Weight (lbs)")
312
  calories_consumed_input = gr.Number(label="Calories Consumed")
313
  calories_burned_input = gr.Number(label="Calories Burned")
314
  water_intake_input = gr.Number(label="Water Intake (cups)")
315
  sleep_hours_input = gr.Number(label="Sleep Hours")
316
+ stress_level_input = gr.Slider(1, 10, step=1, label="Stress Level")
317
+ mood_input = gr.Dropdown(['Great', 'Good', 'Neutral', 'Poor'], label="Mood")
318
  exercise_minutes_input = gr.Number(label="Exercise Minutes")
319
  notes_input = gr.Textbox(label="Notes")
320
  add_button = gr.Button("Add Entry", variant="primary")
321
  add_output = gr.Markdown()
322
+ add_button.click(add_entry, inputs=[date_input, weight_input, calories_consumed_input, calories_burned_input,
323
+ water_intake_input, sleep_hours_input, stress_level_input, mood_input,
324
+ exercise_minutes_input, notes_input], outputs=add_output)
 
 
325
 
326
  with gr.Tab("View Entries"):
327
+ num_entries_view = gr.Slider(5, 30, step=5, value=10, label="Entries to View")
328
+ view_button = gr.Button("View", variant="secondary")
329
  view_output = gr.DataFrame()
330
  view_button.click(view_entries, inputs=num_entries_view, outputs=view_output)
331
 
332
  with gr.Tab("Update Entry"):
333
+ date_update_input = gr.Textbox(label="Date (YYYY-MM-DD)")
334
  with gr.Row():
335
  with gr.Column():
336
+ weight_update_input = gr.Number(label="Weight (lbs)")
337
  calories_consumed_update_input = gr.Number(label="Calories Consumed")
338
  calories_burned_update_input = gr.Number(label="Calories Burned")
339
  water_intake_update_input = gr.Number(label="Water Intake (cups)")
340
  sleep_hours_update_input = gr.Number(label="Sleep Hours")
341
+ stress_level_update_input = gr.Slider(1, 10, step=1, label="Stress Level")
342
+ mood_update_input = gr.Dropdown(['Great', 'Good', 'Neutral', 'Poor'], label="Mood")
343
  exercise_minutes_update_input = gr.Number(label="Exercise Minutes")
344
  notes_update_input = gr.Textbox(label="Notes")
345
+ update_button = gr.Button("Update", variant="primary")
346
  update_output = gr.Markdown()
347
+ update_button.click(update_entry, inputs=[date_update_input, weight_update_input, calories_consumed_update_input,
348
+ calories_burned_update_input, water_intake_update_input, sleep_hours_update_input,
349
+ stress_level_update_input, mood_update_input, exercise_minutes_update_input,
350
+ notes_update_input], outputs=update_output)
351
+
352
+ with gr.Tab("Goals"):
353
+ target_weight_input = gr.Number(label="Target Weight (lbs)")
354
+ target_date_input = gr.Textbox(label="Target Date (YYYY-MM-DD)")
355
+ goal_button = gr.Button("Set Goal", variant="primary")
356
+ goal_output = gr.Markdown()
357
+ goal_view_button = gr.Button("View Goal Progress", variant="secondary")
358
+ goal_view_output = gr.Markdown()
359
+ goal_button.click(set_goal, inputs=[target_weight_input, target_date_input], outputs=goal_output)
360
+ goal_view_button.click(view_goal, outputs=goal_view_output)
361
+
362
+ with gr.Tab("Achievements"):
363
+ achievements_output = gr.Markdown(value=update_achievements())
364
+ gr.Button("Refresh Achievements").click(update_achievements, outputs=achievements_output)
 
 
 
 
 
 
 
 
 
 
 
365
 
366
  with gr.Tab("Analytics"):
367
+ weight_plot_button = gr.Button("Weight Over Time", variant="secondary")
368
+ weight_plot_output_text = gr.Markdown()
369
+ weight_plot_output = gr.Image()
370
+ weight_plot_button.click(create_weight_plot, outputs=[weight_plot_output_text, weight_plot_output])
 
 
 
 
 
 
 
 
 
 
 
 
 
371
 
372
  with gr.Tab("Prediction"):
373
+ days_input = gr.Slider(7, 90, step=7, value=30, label="Days to Predict")
374
+ calorie_adjustment_input = gr.Number(label="Calorie Adjustment")
375
+ exercise_adjustment_input = gr.Number(label="Exercise Adjustment")
376
+ predict_button = gr.Button("Predict", variant="primary")
 
 
 
 
 
377
  prediction_output_text = gr.Markdown()
378
  prediction_plot_output = gr.Plot()
379
  recommendation_output = gr.Markdown()
380
+ predict_button.click(predict_weight_trajectory, inputs=[days_input, calorie_adjustment_input, exercise_adjustment_input],
 
 
381
  outputs=[prediction_output_text, prediction_plot_output, recommendation_output])
382
 
383
  with gr.Tab("Train Model"):
384
+ train_button = gr.Button("Train Model", variant="primary")
385
  train_output = gr.Markdown()
386
+ train_button.click(train_prediction_model, outputs=train_output)
387
 
388
+ with gr.Tab("Food Log"):
389
+ food_name_input = gr.Dropdown(choices=food_df['name'].tolist(), label="Food Item")
390
+ quantity_input = gr.Number(label="Quantity", minimum=1, value=1)
391
+ food_log_button = gr.Button("Log Food", variant="secondary")
392
+ food_log_output = gr.Markdown()
393
+ food_log_button.click(log_food, inputs=[food_name_input, quantity_input], outputs=food_log_output)
394
 
395
+ with gr.Tab("Sample Data"):
396
  def load_sample_data():
 
397
  global df
398
+ start_date = datetime.datetime.now() - datetime.timedelta(days=30)
399
+ sample_data = [{'date': start_date + datetime.timedelta(days=i),
400
+ 'weight': 180 - (0.1 * i) + np.random.normal(0, 0.3),
401
+ 'calories_consumed': np.random.randint(1800, 2300),
402
+ 'calories_burned': np.random.randint(2000, 2500),
403
+ 'water_intake': np.random.randint(5, 10),
404
+ 'sleep_hours': round(np.random.normal(7, 0.5), 1),
405
+ 'stress_level': np.random.randint(3, 8),
406
+ 'mood': np.random.choice(['Great', 'Good', 'Neutral', 'Poor']),
407
+ 'exercise_minutes': np.random.randint(20, 60),
408
+ 'notes': ''} for i in range(30)]
409
+ df = pd.concat([df, pd.DataFrame(sample_data)], ignore_index=True)
410
+ df['date'] = pd.to_datetime(df['date'])
411
+ df = df.sort_values('date', ascending=False)
412
+ df.to_csv(DATA_FILE, index=False)
413
+ update_achievements()
414
+ return "✅ Sample data loaded!"
415
+ sample_button = gr.Button("Load Sample Data", variant="secondary")
416
+ sample_output = gr.Markdown()
417
+ sample_button.click(load_sample_data, outputs=sample_output)
418
 
 
419
  iface.launch(debug=False)