Changes between Version 2 and Version 3 of RelationalModel


Ignore:
Timestamp:
04/20/26 08:34:14 (12 days ago)
Author:
231550
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • RelationalModel

    v2 v3  
    11[[Image(RelationalModel-ProjectCode.svg)]]
     2
     3**Descriptive documentation and argumentation**\\
     4
     51. User & Role Management (User, Roles, User_roles)\\
     6
     7The User table is the central entity of the entire model. Rather than embedding
     8a role directly into the User table as a simple string or enum (e.g. role VARCHAR(20)),
     9the decision was made to create a separate Roles table and a User_roles junction table.
     10
     11**Why this way:**
     12A simple enum column would restrict each user to exactly one role and make it difficult to
     13add new roles in the future without altering the table structure. By using a junction table,
     14the model supports many-to-many role assignment — a user could theoretically be both a
     15nutritionist and an admin simultaneously. It also means new roles can be added simply by
     16inserting a new row into Roles, with no schema changes required. This is a much more scalable
     17and flexible design for a platform that may evolve over time.
     18
     192. Food Categorization (Category — self-referencing)\\
     20
     21The Category table contains a self-referencing foreign key ParentCategory_id
     22that points back to its own primary key.
     23
     24**Why this way:**
     25Food categories in the real world are hierarchical. For example "Chicken Breast" belongs
     26to "Poultry", which belongs to "Meat & Fish", which belongs to "Protein Sources". A flat
     27single-level category system would not capture this hierarchy. By making Category self-referencing,
     28the model supports unlimited nesting depth of categories without needing additional tables.
     29The ParentCategory_id is nullable, meaning top-level categories simply have no parent.
     30ON DELETE SET NULL ensures that if a parent category is deleted, its children are not deleted
     31— they simply become top-level categories themselves
     32
     333. Nutritional Tracking (Food, Nutrient, Food_nutrients)\\
     34
     35Rather than adding individual columns to the Food table for each nutrient
     36(e.g. protein INT4, carbs INT4, fat INT4), the model uses a separate Nutrient
     37table and a Food_nutrients junction table.
     38
     39**Why this way:**
     40The number of nutrients tracked can vary enormously — from basic macros (protein, carbs, fat)
     41to micronutrients (Vitamin C, Iron, Calcium, Omega-3 etc.). Hardcoding nutrient columns into
     42Food would make the schema inflexible and would require an ALTER TABLE every time a new
     43nutrient needs to be tracked. The junction table approach allows any number of nutrients
     44to be associated with any food, and new nutrients can be added simply by inserting into the Nutrient
     45table.
     46
     474. Serving Sizes (ServingSize)\\
     48
     49ServingSize is modeled as a separate table linked to Food with a many-to-one relationship,
     50rather than a single serving size column on Food.
     51
     52**Why this way:**
     53A single food can have multiple valid serving sizes. For example "Oats" could be measured
     54as "1 cup (90g)", "1 tablespoon (10g)", or "100g". If serving size were a single column
     55on Food, users would be forced to always log in the same unit, which is unrealistic.
     56The separate table allows the platform to offer users a dropdown of recognized serving sizes
     57when logging food, improving accuracy and user experience. The amount and unit columns together
     58define exactly how much that serving represents.
     59
     605. Exercise & Muscle Targeting (Exercise, Muscle, Exercise_muscles, Activity)\\
     61
     62Exercises are organized under Activities and linked to Muscles through a junction table.
     63
     64**Why this way:**
     65The Activity table (e.g. "Cardio", "Strength Training", "Flexibility") acts as a high-level
     66grouping for exercises, allowing users to filter and browse exercises by type. This is kept
     67separate from Exercise because one activity type contains many exercises.
     68
     69The Exercise_muscles junction table exists because a single exercise targets multiple muscles
     70(e.g. a bench press works the chest, triceps, and shoulders simultaneously), and a single muscle
     71is targeted by many exercises. This is a true many-to-many relationship that cannot be modeled
     72with a simple FK column. By tracking this explicitly, the platform can show users a muscle map
     73of which areas they are training, and generate reports like "you haven't trained your legs this week."
     74
     756. Diet Planning (Diet, Diet_foods, Diet_Exercise_Targets)\\
     76
     77The Diet table acts as a plan template rather than a per-user record.
     78Users are linked to diets through the User_Diets junction table.
     79
     80**Why this way:**
     81If diet data were embedded directly into a user record, the same diet plan could not be shared
     82across multiple users. By separating the Diet as its own entity, the same diet plan
     83(e.g. "Keto Diet", "High Protein Plan") can be assigned to many users simultaneously.
     84The company's nutritionists can create a library of diet plans that any user can be enrolled in.
     85As well as giving users the option to create their own custom diets where they input their own
     86foods and exercises in accordance to their needs.
     87
     88Diet_foods specifies exactly which foods are part of the diet and in what amounts, while Diet_Exercise_Targets
     89specifies which exercises should be performed and how many times per week. Together these two tables fully
     90define what a user on a given diet should eat and how they should exercise, giving the platform
     91enough data to track compliance and progress.
     92
     937. Gamification (Streak, Streak_type, Achievements, User_achievements)\\
     94
     95The gamification layer is modeled with full normalization rather than simple counters.
     96
     97**Why this way:**
     98Streak_type is separated from Streak for the same reason Nutrient is separated from Food
     99— there can be many types of streaks (logging streaks, calorie streaks, workout streaks)
     100and new types should be addable without schema changes. Each user's Streak record tracks
     101both current_count and longest_count, the latter being historically significant even when
     102a streak is broken. The CHECK constraint longest_count >= current_count enforces this business
     103rule at the database level.
     104
     105Achievements are similarly separated from User_achievements. The Achievements table defines
     106the achievement criteria (what needs to be done, how many times, in what period), while User_achievements
     107simply records when a specific user met those criteria. This means achievements are defined
     108once and can be earned by any number of users, rather than duplicating achievement definitions per user.
     109
     1108. Goals (Goal, User_goals)\\
     111
     112Goals are modeled as a shared reference table linked to users through User_goals,
     113with each goal tied to a specific diet plan.
     114
     115**Why this way:**
     116A goal like "Lose Weight" or "Gain Weight" is a general concept that many users share.
     117Rather than each user defining their own goal from scratch, goals are predefined and
     118linked to appropriate diet plans. This means when a user selects a goal, the system can
     119automatically suggest or assign the corresponding diet plan. The User_goals junction table
     120adds start_date and end_date to give each user's goal a defined timeframe, making progress
     121trackable and time-bound.
     122
     123
     124