diff --git a/Essential/FoodSearch.py b/Essential/FoodSearch.py new file mode 100644 index 0000000..25ad312 --- /dev/null +++ b/Essential/FoodSearch.py @@ -0,0 +1,13 @@ +import sqlite3 + +class FoodSearch: + def __init__(self, db_path): + self.conn = sqlite3.connect(db_path) + self.cursor = self.conn.cursor() + + def search(self, user_input) -> list: + query = f"SELECT * FROM food_data WHERE product_name LIKE '%{user_input}%'" + self.cursor.execute(query) + results = self.cursor.fetchall() + + return results \ No newline at end of file diff --git a/Essential/__pycache__/FoodSearch.cpython-311.pyc b/Essential/__pycache__/FoodSearch.cpython-311.pyc new file mode 100644 index 0000000..6134ad6 Binary files /dev/null and b/Essential/__pycache__/FoodSearch.cpython-311.pyc differ diff --git a/Essential/__pycache__/foodItem.cpython-311.pyc b/Essential/__pycache__/foodItem.cpython-311.pyc new file mode 100644 index 0000000..93fbb59 Binary files /dev/null and b/Essential/__pycache__/foodItem.cpython-311.pyc differ diff --git a/Essential/foodDatabase.py b/Essential/foodDatabase.py new file mode 100644 index 0000000..a02a969 --- /dev/null +++ b/Essential/foodDatabase.py @@ -0,0 +1,83 @@ +import sqlite3 + +conn = sqlite3.connect('food.db') +c = conn.cursor() + +# create table +c.execute('''CREATE TABLE food + (id INTEGER PRIMARY KEY AUTOINCREMENT, + product_name TEXT, + brands TEXT, + brands_tags TEXT, + categories TEXT, + categories_tags TEXT, + categories_en TEXT, + origins TEXT, + origins_tags TEXT, + origins_en TEXT, + countries TEXT, + countries_tags TEXT, + countries_en TEXT, + image_url TEXT, + image_ingredients_url TEXT, + image_nutrition_url TEXT, + energy_kcal_100g REAL, + fat_100g REAL, + saturated_fat_100g REAL, + unsaturated_fat_100g REAL, + omega_3_fat_100g REAL, + omega_6_fat_100g REAL, + omega_9_fat_100g REAL, + trans_fat_100g REAL, + cholesterol_100g REAL, + carbohydrates_100g REAL, + sugars_100g REAL, + sucrose_100g REAL, + glucose_100g REAL, + fructose_100g REAL, + lactose_100g REAL, + maltose_100g REAL, + fiber_100g REAL, + soluble_fiber_100g REAL, + insoluble_fiber_100g REAL, + proteins_100g REAL, + salt_100g REAL, + added_salt_100g REAL, + sodium_100g REAL, + alcohol_100g REAL, + vitamin_a_100g REAL, + beta_carotene_100g REAL, + vitamin_d_100g REAL, + vitamin_e_100g REAL, + vitamin_k_100g REAL, + vitamin_c_100g REAL, + vitamin_b1_100g REAL, + vitamin_b2_100g REAL, + vitamin_pp_100g REAL, + vitamin_b6_100g REAL, + vitamin_b9_100g REAL, + vitamin_b12_100g REAL, + bicarbonate_100g REAL, + potassium_100g REAL, + chloride_100g REAL, + calcium_100g REAL, + phosphorus_100g REAL, + iron_100g REAL, + magnesium_100g REAL, + zinc_100g REAL, + copper_100g REAL, + manganese_100g REAL, + fluoride_100g REAL, + selenium_100g REAL, + chromium_100g REAL, + molybdenum_100g REAL, + iodine_100g REAL, + caffeine_100g REAL, + carbon_footprint_100g REAL, + carbon_footprint_from_meat_or_fish_100g REAL, + cocoa_100g REAL)''') + +# commit changes and close connection +conn.commit() +conn.close() + diff --git a/Essential/foodItem.py b/Essential/foodItem.py index d3deba8..3365bfc 100644 --- a/Essential/foodItem.py +++ b/Essential/foodItem.py @@ -78,13 +78,11 @@ class foodItem(): return False def nutrient_score_intl(self): - # define the nutrient score factors nutrient_factors = {'fat': 9, 'saturated_fat': 10, 'trans_fat': 10, 'cholesterol': 5, 'sodium': 6, 'carbohydrates': 7, 'sugars': 6, 'fiber': 5, 'proteins': 5, 'vitamin_a': 15, 'vitamin_c': 15, 'calcium': 10, 'iron': 10} - # calculate the nutrient score for each nutrient nutrient_scores = {} for nutrient, factor in nutrient_factors.items(): value = getattr(self, nutrient+'_100g') @@ -97,11 +95,11 @@ class foodItem(): return total_score def _get_daily_requirement(self, nutrient): - # define the daily requirement for each nutrient daily_requirement = {'fat': 70, 'saturated_fat': 20, 'trans_fat': 2, 'cholesterol': 300, 'sodium': 2000, 'carbohydrates': 260, 'sugars': 90, 'fiber': 38, 'proteins': 50, 'vitamin_a': 900, 'vitamin_c': 90, 'calcium': 1000, 'iron': 18} + # for nutrients without a daily requirement, return None return daily_requirement.get(nutrient, None) @@ -111,4 +109,7 @@ class foodItem(): for i, row in df.iterrows(): product = cls(row) products.append(product) - return products \ No newline at end of file + return products + + def __str__(self) -> str: + return self.product_name \ No newline at end of file diff --git a/Essential/prepare_db.py b/Essential/prepare_db.py new file mode 100644 index 0000000..a92987c --- /dev/null +++ b/Essential/prepare_db.py @@ -0,0 +1,24 @@ +import sqlite3 +import pandas as pd +import re + +thai_df = pd.read_csv('thai_data.csv') +us_df = pd.read_csv('us_data.csv') +japan_df = pd.read_csv('japan_data.csv') + +conn = sqlite3.connect('food_data.db') + +thai_df = thai_df[~thai_df.product_name.str.contains('to be deleted', na=False, flags=re.IGNORECASE)] +japan_df = japan_df[~japan_df.product_name.str.contains('to be deleted', na=False, flags=re.IGNORECASE)] +us_df = us_df[~us_df.product_name.str.contains('to be deleted', na=False, flags=re.IGNORECASE)] + +thai_df = thai_df.dropna(subset=['product_name']) +japan_df = japan_df.dropna(subset=['product_name']) +us_df = us_df.dropna(subset=['product_name']) + +thai_df.to_sql('thai_food', conn, if_exists='replace', index=False) +us_df.to_sql('us_food', conn, if_exists='replace', index=False) +japan_df.to_sql('japan_food', conn, if_exists='replace', index=False) + +conn.commit() +conn.close() \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000..5c72a3b --- /dev/null +++ b/app.py @@ -0,0 +1,97 @@ +import tkinter as tk +import requests +import io +from PIL import Image, ImageTk +from Essential.FoodSearch import FoodSearch + + +class App: + def __init__(self, master): + self.master = master + self.food_search = FoodSearch('food_data.db') + + self.search_var = tk.StringVar() + self.search_var.trace('w', self.search_callback) + + self.search_entry = tk.Entry(self.master, textvariable=self.search_var) + self.search_entry.grid(row=0, column=0, padx=10, pady=10) + + self.search_button = tk.Button(self.master, text="Search", command=self.search) + self.search_button.grid(row=1, column=0, padx=10, pady=10) + + self.results_frame = tk.Frame(self.master) + self.results_frame.grid(row=2, column=0, padx=10, pady=10, sticky="nsew") + + self.scrollbar = tk.Scrollbar(self.results_frame) + self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y) + + self.results_listbox = tk.Listbox(self.results_frame, yscrollcommand=self.scrollbar.set) + self.results_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) + + self.scrollbar.config(command=self.results_listbox.yview) + + self.selected_item = None + + self.image_frame = tk.Frame(self.master, bg='white') + self.image_frame.grid(row=0, column=2, rowspan=3, padx=10, pady=10, sticky="nsew") + + self.master.columnconfigure(0, weight=1) + self.master.columnconfigure(1, weight=0) + self.master.columnconfigure(2, weight=1) + self.master.rowconfigure(2, weight=1) + + def search_callback(self, *args): + pass + + def search(self): + results = self.food_search.search(self.search_var.get()) + self.update_results(results) + + def update_results(self, results): + self.results_listbox.delete(0, tk.END) + for result in results: + self.results_listbox.insert(tk.END, result[1]) + + def clear_results(self): + self.results_listbox.delete(0, tk.END) + + def on_item_selected(self, event): + widget = event.widget + selection = widget.curselection() + if selection: + index = selection[0] + value = widget.get(index) + self.selected_item = value + self.show_image(self.selected_item) + + def show_image(self, item): + image_url = None + for result in self.food_search.search(self.search_var.get()): + if result[1] == item: + image_url = result[13] + break + + if not image_url: + return + + response = requests.get(image_url) + img_data = response.content + img = Image.open(io.BytesIO(img_data)) + img = img.resize((300, 300), Image.ANTIALIAS) + img_tk = ImageTk.PhotoImage(img) + + # remove old image label widget + for widget in self.image_frame.winfo_children(): + widget.destroy() + + self.image_frame.configure(bg='white') + label = tk.Label(self.image_frame, image=img_tk, bg='white') + label.image = img_tk + label.pack(fill=tk.BOTH, expand=True) +root = tk.Tk() +app = App(root) +root.geometry("800x400") +root.title('Food Search') +app.results_listbox.bind('<>', app.on_item_selected) + +root.mainloop()