Hozifa Elgharbawy commited on
Commit
f52f1cd
·
1 Parent(s): ebc986f

add nutrition_model

Browse files
models-server/models/nutrition_model.py CHANGED
@@ -1,94 +1,96 @@
1
- import random
2
  import pandas as pd
3
- import numpy as np
4
  import pickle
5
- import sys
6
  import os
7
- import pickle
8
 
9
  SERVER_FILE_DIR = os.path.dirname(os.path.abspath(__file__))
10
- NUTRITION_MODEL_PATH = os.path.join(
11
- SERVER_FILE_DIR, *"../resources/models/nutrition_model.pkl".split("/")
12
- )
 
 
 
13
 
 
14
 
15
  class NutritionModel:
16
- def generate_plan(self,calories):
17
- the_model = self.nutrition_model
18
- lunch_attr = {"Calories":calories*0.5,
19
- "FatContent":random.uniform(19, 97),
20
- "SaturatedFatContent":random.uniform(6, 12),
21
- "CholesterolContent": random.uniform(77, 299),
22
- "SodiumContent":random.uniform(565, 2299),
23
- "CarbohydrateContent":random.uniform(28, 317),
24
- "FiberContent": random.uniform(2, 38),
25
- "SugarContent": random.uniform(0, 38),
26
- "ProteinContent":random.uniform(20, 123)}
 
 
 
 
27
 
28
  lunch_df = pd.DataFrame(lunch_attr, index=[0])
29
 
30
- breakfast_attr = {"Calories":calories*0.30,
31
- "FatContent":random.uniform(8.7, 20),
32
- "SaturatedFatContent":random.uniform(1.7, 3.7),
33
- "CholesterolContent": random.uniform(0, 63),
34
- "SodiumContent":random.uniform(163, 650),
35
- "CarbohydrateContent":random.uniform(23, 56),
36
- "FiberContent": random.uniform(2.6, 8),
37
- "SugarContent": random.uniform(3.5, 13),
38
- "ProteinContent":random.uniform(6, 25)}
 
 
39
 
40
  breakfast_df = pd.DataFrame(breakfast_attr, index=[0])
41
 
42
- dinner_attr = {"Calories":calories*0.30,
43
- "FatContent":random.uniform(15, 33),
44
- "SaturatedFatContent":random.uniform(6, 8),
45
- "CholesterolContent": random.uniform(22, 86),
46
- "SodiumContent":random.uniform(265, 775),
47
- "CarbohydrateContent":random.uniform(14, 44),
48
- "FiberContent": random.uniform(101, 110),
49
- "SugarContent": random.uniform(3, 13),
50
- "ProteinContent":random.uniform(11, 25)}
 
 
51
 
52
  dinner_df = pd.DataFrame(dinner_attr, index=[0])
53
 
54
- snack_attr = {"Calories":random.uniform(90, 190),
55
- "FatContent":random.uniform(1.7, 10),
56
- "SaturatedFatContent":random.uniform(0.7, 3),
57
- "CholesterolContent": random.uniform(2, 16),
58
- "SodiumContent":random.uniform(47, 200),
59
- "CarbohydrateContent":random.uniform(10, 31),
60
- "FiberContent": random.uniform(0.4, 2.5),
61
- "SugarContent": random.uniform(5.7, 21),
62
- "ProteinContent":random.uniform(3, 20)}
 
 
63
 
64
  snack_df = pd.DataFrame(snack_attr, index=[0])
65
 
66
- drinks_attr = {"Calories":random.uniform(60, 125),
67
- "FatContent":random.uniform(0.2, 0.6),
68
- "SaturatedFatContent":random.uniform(0, 0.1),
69
- "CholesterolContent": random.uniform(0, 0.1),
70
- "SodiumContent":random.uniform(3.5, 51),
71
- "CarbohydrateContent":random.uniform(14, 30),
72
- "FiberContent": random.uniform(0.2, 3.6),
73
- "SugarContent": random.uniform(109, 122),
74
- "ProteinContent":random.uniform(0.4, 6)}
75
-
76
- drink_df = pd.DataFrame(drinks_attr, index=[0])
77
-
78
- lunch = the_model.transform(lunch_df)
79
- breakfast = the_model.transform(breakfast_df)
80
- dinner = the_model.transform(dinner_df)
81
- snack = the_model.transform(snack_df)
82
- drink = the_model.transform(drink_df)
83
 
84
- meals = np.concatenate((breakfast, lunch, dinner, snack, drink), axis=0)
85
  meals = np.transpose(meals)
86
-
87
- return meals
88
-
89
 
90
- def load(self):
 
 
 
91
 
 
 
 
92
  with open(NUTRITION_MODEL_PATH, "rb") as f:
93
  self.nutrition_model = pickle.load(f)
94
 
 
1
+ import random
2
  import pandas as pd
3
+ import numpy as np
4
  import pickle
 
5
  import os
 
6
 
7
  SERVER_FILE_DIR = os.path.dirname(os.path.abspath(__file__))
8
+ NUTRITION_MODEL_PATH = os.path.join(SERVER_FILE_DIR, "../resources/models/nutrition_model.pkl")
9
+ MEALS_JSON_PATH = os.path.join(SERVER_FILE_DIR, "../../src/resources/meals.json")
10
+
11
+ # Ensure the file exists
12
+ if not os.path.exists(MEALS_JSON_PATH):
13
+ raise FileNotFoundError(f"File {MEALS_JSON_PATH} does not exist")
14
 
15
+ df = pd.read_json(MEALS_JSON_PATH)
16
 
17
  class NutritionModel:
18
+ def __init__(self):
19
+ self.load()
20
+
21
+ def generate_plan(self, calories):
22
+ lunch_attr = {
23
+ "Calories": calories * 0.5,
24
+ "FatContent": random.uniform(19, 97),
25
+ "SaturatedFatContent": random.uniform(6, 12),
26
+ "CholesterolContent": random.uniform(77, 299),
27
+ "SodiumContent": random.uniform(565, 2299),
28
+ "CarbohydrateContent": random.uniform(28, 317),
29
+ "FiberContent": random.uniform(2, 38),
30
+ "SugarContent": random.uniform(0, 38),
31
+ "ProteinContent": random.uniform(20, 123)
32
+ }
33
 
34
  lunch_df = pd.DataFrame(lunch_attr, index=[0])
35
 
36
+ breakfast_attr = {
37
+ "Calories": calories * 0.30,
38
+ "FatContent": random.uniform(8.7, 20),
39
+ "SaturatedFatContent": random.uniform(1.7, 3.7),
40
+ "CholesterolContent": random.uniform(0, 63),
41
+ "SodiumContent": random.uniform(163, 650),
42
+ "CarbohydrateContent": random.uniform(23, 56),
43
+ "FiberContent": random.uniform(2.6, 8),
44
+ "SugarContent": random.uniform(3.5, 13),
45
+ "ProteinContent": random.uniform(6, 25)
46
+ }
47
 
48
  breakfast_df = pd.DataFrame(breakfast_attr, index=[0])
49
 
50
+ dinner_attr = {
51
+ "Calories": calories * 0.30,
52
+ "FatContent": random.uniform(8.7, 20),
53
+ "SaturatedFatContent": random.uniform(1.7, 3.7),
54
+ "CholesterolContent": random.uniform(0, 63),
55
+ "SodiumContent": random.uniform(163, 650),
56
+ "CarbohydrateContent": random.uniform(23, 56),
57
+ "FiberContent": random.uniform(2.6, 8),
58
+ "SugarContent": random.uniform(3.5, 13),
59
+ "ProteinContent": random.uniform(6, 25)
60
+ }
61
 
62
  dinner_df = pd.DataFrame(dinner_attr, index=[0])
63
 
64
+ snack_attr = {
65
+ "Calories": random.uniform(90, 190),
66
+ "FatContent": random.uniform(1.7, 10),
67
+ "SaturatedFatContent": random.uniform(0.7, 3),
68
+ "CholesterolContent": random.uniform(2, 16),
69
+ "SodiumContent": random.uniform(47, 200),
70
+ "CarbohydrateContent": random.uniform(10, 31),
71
+ "FiberContent": random.uniform(0.4, 2.5),
72
+ "SugarContent": random.uniform(5.7, 21),
73
+ "ProteinContent": random.uniform(3, 20)
74
+ }
75
 
76
  snack_df = pd.DataFrame(snack_attr, index=[0])
77
 
78
+ lunch = self.nutrition_model.transform(lunch_df)
79
+ breakfast = self.nutrition_model.transform(breakfast_df)
80
+ dinner = self.nutrition_model.transform(dinner_df)
81
+ snack = self.nutrition_model.transform(snack_df)
 
 
 
 
 
 
 
 
 
 
 
 
 
82
 
83
+ meals = np.concatenate((breakfast, lunch, dinner, snack), axis=0)
84
  meals = np.transpose(meals)
 
 
 
85
 
86
+ days = []
87
+ for i in range(7):
88
+ day_meals = df.iloc[meals[i]].to_dict(orient="records")
89
+ days.append(day_meals)
90
 
91
+ return days
92
+
93
+ def load(self):
94
  with open(NUTRITION_MODEL_PATH, "rb") as f:
95
  self.nutrition_model = pickle.load(f)
96
 
models-server/server.py CHANGED
@@ -55,8 +55,7 @@ def nutrition_predict():
55
  if value is None:
56
  return jsonify({"error": f"{paramName} is missing"}), 400
57
  params[paramName] = value
58
- print("nutrition_model", nutrition_model.generate_plan(**params), type(nutrition_model.generate_plan(**params)))
59
- return jsonify({"result": list(nutrition_model.generate_plan(**params))})
60
 
61
 
62
  if __name__ == "__main__":
 
55
  if value is None:
56
  return jsonify({"error": f"{paramName} is missing"}), 400
57
  params[paramName] = value
58
+ return jsonify({"result": nutrition_model.generate_plan(**params)})
 
59
 
60
 
61
  if __name__ == "__main__":
src/common/models/meal-plan.model.ts CHANGED
@@ -16,6 +16,7 @@ export interface IMealPlan {
16
  day_number: number;
17
  meals: mongoose.Types.ObjectId[];
18
  }[];
 
19
  }
20
 
21
  const mealPlanSchema = new Schema({
@@ -36,6 +37,7 @@ const mealPlanSchema = new Schema({
36
  ],
37
  },
38
  ],
 
39
  });
40
 
41
 
 
16
  day_number: number;
17
  meals: mongoose.Types.ObjectId[];
18
  }[];
19
+ aiGenerated: boolean;
20
  }
21
 
22
  const mealPlanSchema = new Schema({
 
37
  ],
38
  },
39
  ],
40
+ aiGenerated: { type: Boolean, required: true, default: false },
41
  });
42
 
43
 
src/lib/models/nutrition_model.ts ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { config } from "@configs/config";
2
+
3
+ const endpoint = '/nutrition';
4
+
5
+ // Define the structure of a Nutrition Prediction Item
6
+ export interface INutritionPredictionItem {
7
+ Calories: number;
8
+ CarbohydrateContent: number;
9
+ FatContent: number;
10
+ Images: string[];
11
+ Name: string;
12
+ ProteinContent: number;
13
+ RecipeIngredientParts: string[];
14
+ RecipeInstructions: string[];
15
+ type: string;
16
+ }
17
+
18
+ export interface INParams {
19
+ calories: number
20
+ }
21
+
22
+ export class NutritionModel {
23
+ public static async predictMealPlan(
24
+ params: INParams
25
+ ): Promise<INutritionPredictionItem[][]> {
26
+ const response = await fetch(
27
+ `${config.modelsServerUrl}${endpoint}`,
28
+ {
29
+ method: "POST",
30
+ headers: {
31
+ "Content-Type": "application/json",
32
+ },
33
+ body: JSON.stringify(params),
34
+ }
35
+ );
36
+
37
+ if (!response.ok) {
38
+ console.error(await response.text());
39
+ throw new Error("Failed to fetch data from the server");
40
+ }
41
+
42
+ return response.json().then((data) => {
43
+ return data.result as INutritionPredictionItem[][];
44
+ });
45
+ }
46
+ }
src/modules/users/modules/meal-plans/controller/meal-plans.controller.ts CHANGED
@@ -23,6 +23,7 @@ export class UsersMealPlansController extends BaseController {
23
 
24
  setRoutes(): void {
25
  this.router.get("/", asyncHandler(this.list));
 
26
  }
27
 
28
  @SwaggerGet()
@@ -48,4 +49,27 @@ export class UsersMealPlansController extends BaseController {
48
  res
49
  );
50
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  }
 
23
 
24
  setRoutes(): void {
25
  this.router.get("/", asyncHandler(this.list));
26
+ this.router.get("/ss", asyncHandler(this.ss));
27
  }
28
 
29
  @SwaggerGet()
 
49
  res
50
  );
51
  };
52
+
53
+ @SwaggerGet("/ss")
54
+ ss = async (req: Request, res: Response) => {
55
+ let pMealPlan = await this.mealPlansService.createModelMealPlan({
56
+ id: "664a4b170da4e428849859a0",
57
+ name: "User 0",
58
+ email: "[email protected]",
59
+ image: "https://placehold.co/300x400",
60
+ role: "user" as any,
61
+ gender: "male" as any,
62
+ dob: new Date("1990-01-31T22:00:00.000+00:00"),
63
+ height: 170,
64
+ weight: 70,
65
+ fitness_level: "beginner" as any,
66
+ });
67
+
68
+ return JsonResponse.success(
69
+ {
70
+ data: { pMealPlan: pMealPlan},
71
+ },
72
+ res
73
+ );
74
+ };
75
  }
src/modules/users/modules/meal-plans/services/meal-plans.service.ts CHANGED
@@ -1,4 +1,73 @@
1
  import { MealPlan } from "@common/models/meal-plan.model";
2
  import { CrudService } from "@lib/services/crud.service";
 
 
 
 
3
 
4
- export class MealPlansService extends CrudService(MealPlan) {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import { MealPlan } from "@common/models/meal-plan.model";
2
  import { CrudService } from "@lib/services/crud.service";
3
+ import { NutritionModel, INParams, INutritionPredictionItem } from "@lib/models/nutrition_model";
4
+ import { calcAge } from "@lib/utils/age";
5
+ import { MealsService } from "../../meals/services/meals.service";
6
+ import { UserRegisteredMealPlansService } from "../../user-registered-meal-plans/services/user-registered-meal-plans.service";
7
 
8
+ export class MealPlansService extends CrudService(MealPlan) {
9
+ private mealsService = new MealsService();
10
+ private userRegisteredMealPlansService = new UserRegisteredMealPlansService();
11
+
12
+ public async createModelMealPlan(user: any) {
13
+ let caloriesPerDay = 0;
14
+ if (user.gender === "male") {
15
+ caloriesPerDay = 10 * user.weight + 6.25 * user.height - 5 * calcAge(user.dob) + 5;
16
+ } else {
17
+ caloriesPerDay = 10 * user.weight + 6.25 * user.height - 5 * calcAge(user.dob) - 161;
18
+ }
19
+
20
+ const params: INParams = {
21
+ calories: caloriesPerDay,
22
+ };
23
+
24
+ let pMealPlan: INutritionPredictionItem[][] = [];
25
+ for (let i = 0; i < 4; i++) {
26
+ const mealPlanChunk = await NutritionModel.predictMealPlan(params);
27
+ pMealPlan = pMealPlan.concat(mealPlanChunk);
28
+ }
29
+
30
+ const mealsNames = pMealPlan.flat().map((meal) => meal.Name);
31
+ const meals = await this.mealsService.listAll({ name: { $in: mealsNames } });
32
+
33
+ const mealPlan = await this.create({
34
+ aiGenerated: true,
35
+ image: "https://placehold.co/300x400",
36
+ description: `AI Generated Meal Plan (${new Date().toLocaleDateString()})`,
37
+ duration: 28,
38
+ level: user.fitness_level,
39
+ your_journey: `Welcome to your personalized meal plan journey! As someone with a ${user.fitness_level} fitness level, this plan is tailored to meet your specific needs.`,
40
+ key_features: [
41
+ {
42
+ title: "Balanced Nutrition",
43
+ description: `Each meal provides a well-balanced mix of nutrients to support your health goals.`,
44
+ },
45
+ {
46
+ title: "Customizable Meals",
47
+ description: `Meals can be adjusted to fit your dietary preferences.`,
48
+ },
49
+ {
50
+ title: "Easy to Prepare",
51
+ description: `All meals are designed to be quick and easy to prepare.`,
52
+ },
53
+ {
54
+ title: "Variety and Flavor",
55
+ description: `Enjoy a diverse range of delicious meals.`,
56
+ },
57
+ ],
58
+ days: pMealPlan.map((day, i) => ({
59
+ day_number: i + 1,
60
+ meals: day.map((m) => meals.find((meal) => meal.name === m.Name)?._id),
61
+ })),
62
+ });
63
+
64
+ await this.userRegisteredMealPlansService.createForUser(
65
+ {
66
+ MealPlan: mealPlan._id,
67
+ },
68
+ user._id
69
+ );
70
+
71
+ return mealPlan;
72
+ }
73
+ }
src/modules/users/modules/user-registered-meal-plans/services/user-registered-meal-plans.service.ts CHANGED
@@ -2,10 +2,12 @@ import { UserRegisteredMealPlan } from "@common/models/user-registered-meal-plan
2
  import { CrudService } from "@lib/services/crud.service";
3
  import { MealPlansService } from "../../meal-plans/services/meal-plans.service";
4
  import { HttpError } from "@lib/error-handling/http-error";
 
 
5
 
6
 
7
  export class UserRegisteredMealPlansService extends CrudService(UserRegisteredMealPlan) {
8
- private mealPlansService: MealPlansService = new MealPlansService();
9
 
10
  async unregisterCurrentMealPlan(userId: string) {
11
  return await this.updateMany({
 
2
  import { CrudService } from "@lib/services/crud.service";
3
  import { MealPlansService } from "../../meal-plans/services/meal-plans.service";
4
  import { HttpError } from "@lib/error-handling/http-error";
5
+ import { MealPlan } from "@common/models/meal-plan.model";
6
+
7
 
8
 
9
  export class UserRegisteredMealPlansService extends CrudService(UserRegisteredMealPlan) {
10
+ private mealPlansService = new (CrudService(MealPlan))()
11
 
12
  async unregisterCurrentMealPlan(userId: string) {
13
  return await this.updateMany({
src/modules/users/modules/workouts/controllers/workouts.controller.ts CHANGED
@@ -49,13 +49,7 @@ export class UsersWorkoutController extends BaseController {
49
  }
50
 
51
  const { docs, paginationData } = await this.workoutsService.list(
52
- {
53
- ...filter,
54
- $or: [
55
- { aiGenerated: true, created_by: req.jwtPayload.id },
56
- { aiGenerated: false },
57
- ],
58
- },
59
  paginationQuery
60
  );
61
 
 
49
  }
50
 
51
  const { docs, paginationData } = await this.workoutsService.list(
52
+ filter,
 
 
 
 
 
 
53
  paginationQuery
54
  );
55
 
src/modules/users/modules/workouts/services/workouts.service.ts CHANGED
@@ -7,11 +7,7 @@ import { calcAge } from "@lib/utils/age";
7
  import { ExerciseService } from "../../exercises/services/exercises.service";
8
  import { UserRegisteredWorkoutsService } from "../../user-registered-workouts/services/user-registered-workouts.service";
9
 
10
- export class WorkoutService extends CrudService(Workout, {
11
- defaultFilter: {
12
- aiGenerated: false,
13
- },
14
- }) {
15
  private exerciseService = new ExerciseService();
16
  private userRegisteredWorkoutsService = new UserRegisteredWorkoutsService();
17
 
 
7
  import { ExerciseService } from "../../exercises/services/exercises.service";
8
  import { UserRegisteredWorkoutsService } from "../../user-registered-workouts/services/user-registered-workouts.service";
9
 
10
+ export class WorkoutService extends CrudService(Workout) {
 
 
 
 
11
  private exerciseService = new ExerciseService();
12
  private userRegisteredWorkoutsService = new UserRegisteredWorkoutsService();
13