Forráskód Böngészése

TG-28: Upgrade SQLite schema to include micronutrients and refine seeding parser

FerRo988 4 hete
szülő
commit
7c94ece10d
3 módosított fájl, 179 hozzáadás és 0 törlés
  1. 27 0
      database.py
  2. 41 0
      nutrition.csv
  3. 111 0
      seed_food_db.py

+ 27 - 0
database.py

@@ -43,6 +43,33 @@ def create_tables():
             FOREIGN KEY (user_id) REFERENCES users (id)
         )
         ''')
+
+        # Create localized foods table based on Sprint 5 architecture
+        cursor.execute('''
+        CREATE TABLE IF NOT EXISTS foods (
+            id INTEGER PRIMARY KEY AUTOINCREMENT,
+            name TEXT NOT NULL,
+            category TEXT,
+            base_weight_g REAL DEFAULT 100.0,
+            calories REAL DEFAULT 0.0,
+            protein_g REAL DEFAULT 0.0,
+            fat_g REAL DEFAULT 0.0,
+            carbs_g REAL DEFAULT 0.0,
+            fiber_g REAL DEFAULT 0.0,
+            sugar_g REAL DEFAULT 0.0,
+            sodium_mg REAL DEFAULT 0.0,
+            vitamin_a_iu REAL DEFAULT 0.0,
+            vitamin_c_mg REAL DEFAULT 0.0,
+            calcium_mg REAL DEFAULT 0.0,
+            iron_mg REAL DEFAULT 0.0,
+            potassium_mg REAL DEFAULT 0.0,
+            cholesterol_mg REAL DEFAULT 0.0,
+            source TEXT DEFAULT 'System'
+        )
+        ''')
+        
+        # Create index for rapid fuzzy search compatibility
+        cursor.execute('CREATE INDEX IF NOT EXISTS idx_food_name ON foods(name COLLATE NOCASE)')
         
         conn.commit()
         conn.close()

+ 41 - 0
nutrition.csv

@@ -0,0 +1,41 @@
+name,calories,protein,fat,carbohydrate,fiber,sugar,sodium
+Chicken Breast (Raw),120,22.5,2.6,0,0,0,45
+Ground Beef (80% Lean),254,17.2,20,0,0,0,66
+Salmon (Raw),208,20,13,0,0,0,59
+Tofu (Firm),144,15.8,8.7,2.8,2.3,0.6,14
+Eggs (Whole),143,12.6,9.5,0.7,0,0.4,142
+White Rice (Cooked),130,2.7,0.3,28.2,0.4,0.1,1
+Brown Rice (Cooked),111,2.6,0.9,23,1.8,0.4,5
+Pasta (Cooked),131,5.2,1.2,25,1.2,0.6,6
+Sweet Potato (Baked),90,2,0.1,20.7,3.3,4.2,36
+Potato (Baked),93,2.5,0.1,21.2,2.2,1.2,10
+Oats (Rolled),389,16.9,6.9,66.3,10.6,0,2
+Quinoa (Cooked),120,4.4,1.9,21.3,2.8,0.9,7
+Lentils (Cooked),116,9,0.4,20.1,7.9,1.8,2
+Black Beans (Cooked),132,8.9,0.5,23.7,8.7,0.3,1
+Chickpeas (Cooked),164,8.9,2.6,27.4,7.6,4.8,7
+Broccoli,34,2.8,0.4,6.6,2.6,1.7,33
+Spinach,23,2.9,0.4,3.6,2.2,0.4,79
+Asparagus,20,2.2,0.1,3.9,2.1,1.9,2
+Carrots,41,0.9,0.2,9.6,2.8,4.7,69
+Bell Pepper (Red),31,1,0.3,6,2.1,4.2,4
+Tomato,18,0.9,0.2,3.9,1.2,2.6,5
+Onion,40,1.1,0.1,9.3,1.7,4.2,4
+Garlic,149,6.4,0.5,33.1,2.1,1,15
+Apple,52,0.3,0.2,13.8,2.4,10.4,1
+Banana,89,1.1,0.3,22.8,2.6,12.2,1
+Orange,47,0.9,0.1,11.8,2.4,9.4,0
+Strawberry,32,0.7,0.3,7.7,2,4.9,1
+Blueberry,57,0.7,0.3,14.5,2.4,9.9,1
+Avocado,160,2,14.7,8.5,6.7,0.7,7
+Almonds,579,21.2,49.9,21.7,12.5,4.4,1
+Walnuts,654,15.2,65.2,13.7,6.7,2.6,2
+Peanut Butter,588,25.1,50.4,20,6,9.9,17
+Olive Oil,884,0,100,0,0,0,2
+Butter,717,0.8,81.1,0.1,0,0.1,11
+Whole Milk,61,3.2,3.3,4.8,0,5.1,43
+Greek Yogurt (Plain),59,10.3,0.4,3.6,0,3.2,36
+Cheddar Cheese,403,24.9,33.1,1.3,0,0.5,621
+Bacon (Cooked),541,37,42,1.4,0,0,1717
+Bread (White),266,8.9,3.3,50.6,2.7,4.3,491
+Bread (Whole Wheat),247,11,3.4,42.7,7,6.2,400

+ 111 - 0
seed_food_db.py

@@ -0,0 +1,111 @@
+import ssl
+import sqlite3
+import urllib.request
+import os
+import csv
+
+DB_PATH = os.path.join(os.path.dirname(__file__), "localfood.db")
+
+def get_db_connection():
+    conn = sqlite3.connect(DB_PATH, timeout=20.0, check_same_thread=False)
+    conn.execute('pragma journal_mode=wal')
+    return conn
+
+def fetch_and_seed():
+    ctx = ssl.create_default_context()
+    ctx.check_hostname = False
+    ctx.verify_mode = ssl.CERT_NONE
+
+    print("Loading fundamental internal CSV dataset...")
+    csv_path = os.path.join(os.path.dirname(__file__), "nutrition.csv")
+    
+    try:
+        with open(csv_path, 'r', encoding='utf-8') as f:
+            lines = f.readlines()
+    except Exception as e:
+        print(f"Failed to read local dataset: {e}")
+        return
+    
+    print(f"Dataset downloaded. Mapping data into localfood.db...")
+    conn = get_db_connection()
+    cursor = conn.cursor()
+
+    reader = csv.reader(lines)
+    try:
+        headers = next(reader)
+    except StopIteration:
+        print("Empty dataset.")
+        return
+    
+    def get_val(row, target_names, default="0"):
+        for t_name in target_names:
+            for i, h in enumerate(headers):
+                if t_name.lower() in h.lower():
+                    # Remove non-numeric characters like "g" or "mg" but keep decimals
+                    val = ''.join(c for c in row[i] if c.isdigit() or c == '.')
+                    return val if val else default
+        return default
+
+    count = 0
+    for row in reader:
+        if len(row) < 3: continue
+        
+        # In this dataset, index 1 is name
+        name = row[1] if len(row) > 1 else row[0]
+        
+        try:
+            calories = float(get_val(row, ['calorie', 'energy']))
+            protein = float(get_val(row, ['protein']))
+            fat = float(get_val(row, ['total_fat', 'fat_g', 'fat']))
+            carbs = float(get_val(row, ['carbohydrate', 'carb']))
+            fiber = float(get_val(row, ['fiber']))
+            sugar = float(get_val(row, ['sugar']))
+            sodium_mg = float(get_val(row, ['sodium']))
+            
+            vitamin_a = float(get_val(row, ['vitamin_a', 'vita']))
+            vitamin_c = float(get_val(row, ['vitamin_c', 'vitc']))
+            calcium = float(get_val(row, ['calcium']))
+            iron = float(get_val(row, ['iron']))
+            potassium = float(get_val(row, ['potassium']))
+            cholesterol = float(get_val(row, ['cholesterol']))
+        except ValueError:
+            continue
+        
+        cursor.execute("SELECT id FROM foods WHERE name = ?", (name[:100],))
+        if cursor.fetchone():
+            continue
+
+        try:
+            cursor.execute('''
+                INSERT INTO foods (name, category, calories, protein_g, fat_g, carbs_g, fiber_g, sugar_g, sodium_mg, vitamin_a_iu, vitamin_c_mg, calcium_mg, iron_mg, potassium_mg, cholesterol_mg, source)
+                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+            ''', (
+                name[:100],
+                "Sourced Ingredient",
+                calories,
+                protein,
+                fat,
+                carbs,
+                fiber,
+                sugar,
+                sodium_mg,
+                vitamin_a,
+                vitamin_c,
+                calcium,
+                iron,
+                potassium,
+                cholesterol,
+                'Sourced_CSV'
+            ))
+            count += 1
+            if count >= 8000:  # Seed max 8000 to keep it lightweight locally
+                break
+        except Exception as e:
+            continue
+
+    conn.commit()
+    conn.close()
+    print(f"Successfully seeded {count} foundational macro tracking items into localfood.db!")
+
+if __name__ == '__main__':
+    fetch_and_seed()