-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain_app.py
2065 lines (1800 loc) · 85.2 KB
/
main_app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import sqlite3
import hashlib
import datetime
import re
from getpass import getpass
import cv2
import numpy as np
import pandas as pd
from collections import defaultdict
import numpy as np
import os
# Get the current working directory (cwd) of the Jupyter notebook
cwd = os.getcwd()
# Update paths to reference files in the local directory
DB_PATH = os.path.join(cwd, 'user_auth.db')
PRODUCT_DB_PATH = os.path.join(cwd, 'product_information.db')
HEALTH_DB_PATH = os.path.join(cwd, 'health_form.db')
SHOP_DB_PATH = os.path.join(cwd, 'shopping_list.db')
FAV_DB_PATH = os.path.join(cwd, 'fav_list.db')
REC_PRODUCT_PATH = os.path.join(cwd, 'rec_file.csv')
def add_to_shopping_list(username, product, quantity_shop):
conn = sqlite3.connect(SHOP_DB_PATH)
cursor = conn.cursor()
try:
# Create table if it doesn't exist
cursor.execute('''
CREATE TABLE IF NOT EXISTS shopping_list (
username TEXT,
id INTEGER,
barcode_num TEXT PRIMARY KEY,
product_name TEXT,
ingredients TEXT,
energy REAL,
proteins REAL,
carbohydrates REAL,
cholesterol REAL,
sugars REAL,
total_fat REAL,
saturated_fat REAL,
trans_fat REAL,
sodium REAL,
fruits_vegetables_nuts REAL,
dietary_fibre REAL DEFAULT 0,
allergens TEXT,
nutrition_grade TEXT,
calcium REAL DEFAULT 0,
iodine REAL DEFAULT 0,
zinc REAL DEFAULT 0,
phosphorous REAL DEFAULT 0,
magnesium REAL DEFAULT 0,
vitamin_A REAL DEFAULT 0,
vitamin_B REAL DEFAULT 0,
vitamin_C REAL DEFAULT 0,
vitamin_D REAL DEFAULT 0,
vitamin_E REAL DEFAULT 0,
vitamin_K REAL DEFAULT 0,
other TEXT DEFAULT "",
quantity_shop INT
)
''')
# Ensure quantity_shop is an integer
quantity_shop = int(quantity_shop)
# Check if the product with the same barcode already exists
cursor.execute('SELECT quantity_shop FROM shopping_list WHERE barcode_num = ?', (product[1],))
existing_record = cursor.fetchone()
if existing_record:
# If barcode exists, update the quantity
new_quantity = existing_record[0] + quantity_shop
cursor.execute('UPDATE shopping_list SET quantity_shop = ? WHERE barcode_num = ?', (new_quantity, product[1]))
print(f'Updated quantity for product "{product[2]}" to {new_quantity}.')
else:
# If barcode doesn't exist, insert a new record
product_data = product + (quantity_shop,)
cursor.execute('''
INSERT INTO shopping_list (username, id, barcode_num, product_name, ingredients, energy, proteins, carbohydrates, cholesterol, sugars, total_fat, saturated_fat,
trans_fat, sodium, fruits_vegetables_nuts, dietary_fibre, allergens, nutrition_grade, calcium, iodine, zinc, phosphorous, magnesium, vitamin_A, vitamin_B, vitamin_C, vitamin_D, vitamin_E, vitamin_K, other, quantity_shop)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (username,) + product_data)
print(f'Product "{product[2]}" added to shopping list with quantity {quantity_shop}.')
conn.commit()
except sqlite3.Error as e:
print(f"An error occurred: {e}")
finally:
conn.close()
def add_to_fav_list(username, product, quantity_favourite):
conn = sqlite3.connect(FAV_DB_PATH)
cursor = conn.cursor()
try:
# Create table if it doesn't exist
cursor.execute('''
CREATE TABLE IF NOT EXISTS fav_list (
username TEXT,
id INTEGER,
barcode_num TEXT PRIMARY KEY,
product_name TEXT,
ingredients TEXT,
energy REAL,
proteins REAL,
carbohydrates REAL,
cholesterol REAL,
sugars REAL,
total_fat REAL,
saturated_fat REAL,
trans_fat REAL,
sodium REAL,
fruits_vegetables_nuts REAL,
dietary_fibre REAL DEFAULT 0,
allergens TEXT,
nutrition_grade TEXT,
calcium REAL DEFAULT 0,
iodine REAL DEFAULT 0,
zinc REAL DEFAULT 0,
phosphorous REAL DEFAULT 0,
magnesium REAL DEFAULT 0,
vitamin_A REAL DEFAULT 0,
vitamin_B REAL DEFAULT 0,
vitamin_C REAL DEFAULT 0,
vitamin_D REAL DEFAULT 0,
vitamin_E REAL DEFAULT 0,
vitamin_K REAL DEFAULT 0,
other TEXT DEFAULT "",
quantity_favourite INT
)
''')
# Ensure quantity_favourite is an integer
quantity_favourite = int(quantity_favourite)
# Check if the product with the same barcode already exists
cursor.execute('SELECT quantity_favourite FROM fav_list WHERE barcode_num = ?', (product[1],))
existing_record = cursor.fetchone()
if existing_record:
# If barcode exists, update the quantity
new_quantity = existing_record[0] + quantity_favourite
cursor.execute('UPDATE fav_list SET quantity_favourite = ? WHERE barcode_num = ?', (new_quantity, product[1]))
print(f'Updated quantity for product "{product[2]}" to {new_quantity}.')
else:
# If barcode doesn't exist, insert a new record
product_data = product + (quantity_favourite,)
cursor.execute('''
INSERT INTO fav_list (username, id, barcode_num, product_name, ingredients, energy, proteins, carbohydrates, cholesterol, sugars, total_fat, saturated_fat,
trans_fat, sodium, fruits_vegetables_nuts, dietary_fibre, allergens, nutrition_grade, calcium, iodine, zinc, phosphorous, magnesium, vitamin_A, vitamin_B, vitamin_C, vitamin_D, vitamin_E, vitamin_K, other, quantity_favourite)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (username,) + product_data)
print(f'Product "{product[2]}" added to fav list with quantity {quantity_favourite}.')
conn.commit()
except sqlite3.Error as e:
print(f"An error occurred: {e}")
finally:
conn.close()
def view_fav_list(username):
conn = sqlite3.connect(FAV_DB_PATH)
cursor = conn.cursor()
try:
cursor.execute('SELECT * FROM fav_list WHERE username=?', (username,))
products = cursor.fetchall()
if products:
print("\nFavourite List:")
for item in products:
print(f"- Product Name: {item[3]} , Quantity: {item[30]} ")
else:
print("Your favourite list is empty.")
except sqlite3.Error as e:
print(f"An error occurred: {e}. It might be caused by an invalid column name or unexpected characters.")
finally:
conn.close()
def view_shopping_list(username):
conn = sqlite3.connect(SHOP_DB_PATH)
cursor = conn.cursor()
try:
cursor.execute('SELECT * FROM shopping_list WHERE username=?', (username,))
products = cursor.fetchall()
if products:
print("\nShopping List:")
for item in products:
print(f"- Product Name: {item[3]} , Quantity: {item[30]} ")
else:
print("Your shopping list is empty.")
except sqlite3.Error as e:
print(f"An error occurred: {e}. It might be caused by an invalid column name or unexpected characters.")
finally:
conn.close()
def delete_from_fav_list(username, product_name_fav, quantity_to_delete_fav):
conn = sqlite3.connect(FAV_DB_PATH)
cursor = conn.cursor()
try:
# First, check if the product exists by product name
cursor.execute('''
SELECT product_name, quantity_favourite
FROM fav_list
WHERE username = ? AND product_name = ?
''', (username, product_name_fav))
product = cursor.fetchone()
if product:
current_quantity = product[1] # Get the current quantity (second column is quantity_favourite)
new_quantity = current_quantity - int(quantity_to_delete_fav) # Ensure quantity_to_delete_favis an integer
if new_quantity > 0:
# Update the quantity in the database if the new quantity is greater than zero
cursor.execute('''
UPDATE fav_list
SET quantity_favourite = ?
WHERE username = ? AND product_name = ?
''', (new_quantity, username, product_name_fav)) # Use only product_name for the update
print(f'Updated quantity for product "{product[0]}" to {new_quantity}.')
else:
# If new quantity is 0 or less, remove the product from the list
cursor.execute('''
DELETE FROM fav_list
WHERE username = ? AND product_name = ?
''', (username, product_name_fav)) # Use only product_name for the deletion
print(f'Removed product "{product[0]}" from the favourite list.')
conn.commit()
else:
print(f'Product "{product_name_fav}" not found in the favourite list.')
except sqlite3.Error as e:
print(f"An error occurred: {e}")
finally:
conn.close()
def delete_from_shopping_list(username, product_name, quantity_to_delete_shop):
conn = sqlite3.connect(SHOP_DB_PATH)
cursor = conn.cursor()
try:
# First, check if the product exists by product name
cursor.execute('''
SELECT product_name, quantity_shop
FROM shopping_list
WHERE username = ? AND product_name = ?
''', (username, product_name))
product = cursor.fetchone()
if product:
current_quantity = product[1] # Get the current quantity (second column is quantity_shop)
new_quantity = current_quantity - int(quantity_to_delete_shop) # Ensure quantity_to_delete_shop_shop is an integer
if new_quantity > 0:
# Update the quantity in the database if the new quantity is greater than zero
cursor.execute('''
UPDATE shopping_list
SET quantity_shop = ?
WHERE username = ? AND product_name = ?
''', (new_quantity, username, product_name)) # Use only product_name for the update
print(f'Updated quantity for product "{product[0]}" to {new_quantity}.')
else:
# If new quantity is 0 or less, remove the product from the list
cursor.execute('''
DELETE FROM shopping_list
WHERE username = ? AND product_name = ?
''', (username, product_name)) # Use only product_name for the deletion
print(f'Removed product "{product[0]}" from the shopping list.')
conn.commit()
else:
print(f'Product "{product_name}" not found in the shopping list.')
except sqlite3.Error as e:
print(f"An error occurred: {e}")
finally:
conn.close()
def calculate_nutrition_summary_fav():
conn = sqlite3.connect(FAV_DB_PATH)
cursor = conn.cursor()
total_carbohydrates = 0
total_proteins = 0
total_sugars = 0
total_fat = 0
total_sodium = 0
try:
cursor.execute('SELECT carbohydrates, proteins, sugars, total_fat, sodium FROM fav_list')
products = cursor.fetchall()
for product in products:
total_carbohydrates += product[0] if product[0] is not None else 0
total_proteins += product[1] if product[1] is not None else 0
total_sugars += product[2] if product[2] is not None else 0
total_fat += product[3] if product[3] is not None else 0
total_sodium += product[4] if product[4] is not None else 0
print("\nNutrition Summary of Favourite List:")
print(f"Total Carbohydrates: {total_carbohydrates:.2f} g")
print(f"Total Proteins: {total_proteins:.2f} g")
print(f"Total Sugars: {total_sugars:.2f} g")
print(f"Total Fat: {total_fat:.2f} g")
print(f"Total Sodium: {total_sodium:.2f} g")
except sqlite3.Error as e:
print(f"An error occurred: {e}")
finally:
conn.close()
def calculate_nutrition_summary_shopping():
conn = sqlite3.connect(SHOP_DB_PATH)
cursor = conn.cursor()
total_carbohydrates = 0
total_proteins = 0
total_sugars = 0
total_fat = 0
total_sodium = 0
try:
cursor.execute('SELECT carbohydrates, proteins, sugars, total_fat, sodium FROM shopping_list')
products = cursor.fetchall()
for product in products:
total_carbohydrates += product[0] if product[0] is not None else 0
total_proteins += product[1] if product[1] is not None else 0
total_sugars += product[2] if product[2] is not None else 0
total_fat += product[3] if product[3] is not None else 0
total_sodium += product[4] if product[4] is not None else 0
print("\nNutrition Summary of Shopping List:")
print(f"Total Carbohydrates: {total_carbohydrates:.2f} g")
print(f"Total Proteins: {total_proteins:.2f} g")
print(f"Total Sugars: {total_sugars:.2f} g")
print(f"Total Fat: {total_fat:.2f} g")
print(f"Total Sodium: {total_sodium:.2f} g")
except sqlite3.Error as e:
print(f"An error occurred: {e}")
finally:
conn.close()
def preprocess_frame(frame):
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
thresholded = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
return thresholded
def read_barcodes(frame):
try:
barcodes = pyzbar.decode(frame)
for barcode in barcodes:
barcode_info = barcode.data.decode('utf-8')
if barcode_info.isdigit():
return barcode_info
except Exception as e:
print(f"Error decoding barcode: {e}")
return None
def scan_barcode(username, stream_url=None):
if stream_url is None:
# Get user input for the IP address
ip_address = input("Enter the IP address of your phone (e.g., 192.168.1.100): ")
stream_url = f'http://{ip_address}:8080/video'
cap = cv2.VideoCapture(stream_url)
if not cap.isOpened():
print("Error: Could not open video stream.")
return
print("Scanning barcode... Press 'q' to quit.")
scanned_barcodes = set() # Keep track of scanned barcodes to avoid duplicates
while True:
ret, frame = cap.read()
if not ret:
print("Failed to grab frame")
break
# Process the frame and read the barcode
processed_frame = preprocess_frame(frame)
barcode = read_barcodes(processed_frame)
if barcode and barcode not in scanned_barcodes:
scanned_barcodes.add(barcode)
print(f"\nBarcode detected: {barcode}")
display_product_info(username, barcode) # Pass the barcode directly to display_product_info
cv2.imshow('Barcode Scanner', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
print("Scanning cancelled by user")
break
cap.release()
cv2.destroyAllWindows()
def get_product_info(barcode):
# Connect to the SQLite database
conn = sqlite3.connect(PRODUCT_DB_PATH)
cursor = conn.cursor()
try:
# Query to fetch all columns for the matching barcode
query = """
SELECT id, barcode_num, product_name, ingredients, energy, proteins, carbohydrates, cholesterol, sugars, total_fat, saturated_fat,
trans_fat, sodium, fruits_vegetables_nuts, dietary_fibre, allergens, nutrition_grade, calcium, iodine, zinc, phosphorous, magnesium, vitamin_A, vitamin_B, vitamin_C, vitamin_D, vitamin_E, vitamin_K, other
FROM products
WHERE barcode_num = ?
"""
# Execute the query with the scanned barcode
cursor.execute(query, (barcode,))
# Fetch the result
result = cursor.fetchone()
return result
except sqlite3.Error as e:
print(f"An error occurred: {e}")
finally:
# Close the database connection
conn.close()
return None
def display_product_info(username, barcode):
result = get_product_info(barcode)
if result:
# Display the product information
print("\nProduct Information:")
print(f"ID: {result[0]}")
print(f"Barcode: {result[1]}")
print(f"Product Name: {result[2]}")
print(f"Ingredients: {result[3]}")
print(f"Energy: {result[4]} kcal")
print(f"Proteins: {result[5]} g")
print(f"Carbohydrates: {result[6]} g")
print(f"Cholesterol: {result[7]} g")
print(f"Sugars: {result[8]} g")
print(f"Total Fat: {result[9]} g")
print(f"Saturated Fat: {result[10]} g")
print(f"Trans Fat: {result[11]} g")
print(f"Sodium: {result[12]} g")
print(f"Fruits/Vegetables/Nuts: {result[13]} g")
print(f"Dietary fibre: {result[14]} g")
print(f"Allergens: {result[15]}")
print(f"Nutrition Grade: {result[16]}")
# Only display these values if they are not 0
if result[17] != 0:
print(f"Calcium: {result[17]} g")
if result[18] != 0:
print(f"Iodine: {result[18]} g")
if result[19] != 0:
print(f"Zinc: {result[19]} g")
if result[20] != 0:
print(f"Phosphorous: {result[20]} g")
if result[21] != 0:
print(f"Magnesium: {result[21]} g")
if result[22] != 0:
print(f"Vitamin A: {result[22]} g")
if result[23] != 0:
print(f"Vitamin B: {result[23]} g")
if result[24] != 0:
print(f"Vitamin C: {result[24]} g")
if result[25] != 0:
print(f"Vitamin D: {result[25]} g")
if result[26] != 0:
print(f"Vitamin E: {result[26]} g")
if result[27] != 0:
print(f"Vitamin K: {result[27]} g")
if result[28]: # Assuming 'other' is a string and we want to display it if it's not empty
print(f"Other: {result[28]}")
# Rest of the function remains the same
allergens = result[15] # Assuming this is a list of allergens
if 'milk' in allergens.lower():
print("\n⚠️ WARNING: This product contains dairy!")
if 'wheat' in allergens.lower():
print("\n⚠️ WARNING: This product contains wheat!")
if 'soy' in allergens.lower():
print("\n⚠️ WARNING: This product contains soy!")
if 'peanut' in allergens.lower():
print("\n⚠️ WARNING: This product contains peanut!")
if 'nut' in allergens.lower():
print("\n⚠️ WARNING: This product contains nuts!")
if 'sulphite' in allergens.lower():
print("\n⚠️ WARNING: This product contains sulphite!")
# Nutritional tags based on specified conditions
sugars = result[8]
sodium = result[12]
energy_kcal = result[4]
fats = result[9]
saturated_fat = result[10]
proteins = result[5]
if sugars > 22.5:
print("\n⚠️ WARNING: This product is high in sugar!")
elif sugars <= 5:
print("\n🍎 NOTE: This product is low in sugar!")
if sodium > 0.6:
print("\n⚠️ WARNING: This product is high in sodium!")
elif sodium <= 0.1:
print("\n🥗 NOTE: This product is low in sodium!")
if energy_kcal > 0:
protein_energy_percentage = (proteins * 4 / energy_kcal) * 100
if protein_energy_percentage >= 20:
print("\n💪 NOTE: This product is high in protein!")
if fats > 17.5:
print("\n🍔 WARNING: This product is high in total fat!")
elif fats < 0.5:
print("\n🥬 NOTE: This product is fat-free!")
elif fats < 3:
print("\n🥗 NOTE: This product is low in fat!")
if saturated_fat > 5:
print("\n🥓 WARNING: This product is high in saturated fat!")
elif saturated_fat < 0.1:
print("\n🌱 NOTE: This product is free of saturated fat!")
elif saturated_fat < 1.5:
print("\n🥑 NOTE: This product is low in saturated fat!")
# Retrieve the user's health data
conn = sqlite3.connect(HEALTH_DB_PATH)
cursor = conn.cursor()
cursor.execute("SELECT * FROM health_form WHERE username = ?", (username,))
user_health_data = cursor.fetchone()
conn.close()
if user_health_data:
# Prepare user health data for score calculation
user_data = {
'age': user_health_data[1],
'height': user_health_data[2],
'weight': user_health_data[3],
'diet_type': user_health_data[4],
'chronic_illnesses': user_health_data[5],
'dietary_restrictions': user_health_data[6],
'trigger_ingredients': user_health_data[7],
'health_goals': user_health_data[8]
}
# Prepare product data for score calculation
product_data = {
'energy': result[4],
'proteins': result[5],
'carbohydrates': result[6],
'cholesterol': result[7],
'sugars': result[8],
'total_fat': result[9],
'saturated_fat': result[10],
'trans_fat': result[11],
'sodium': result[12],
'dietary_fibre': result[14],
'allergens': result[15]
}
# Calculate the health score
health_score = calculate_health_score(user_data, product_data)
print(f"\n🧑⚕️ Health Score (for {username}): {health_score}/5")
# Ask if the user wants to add the product to the shopping list
add_to_shop_list = input("\nDo you want to add this product to your shopping list? (yes/no): ").strip().lower()
if add_to_shop_list == 'yes':
quantity_shop = input("\n Enter quantity of product (int): ")
add_to_shopping_list(username, result, quantity_shop) # Pass all fields of the product
view_shop_list = input("Do you want to view your shopping list? (yes/no): ").strip().lower()
if view_shop_list == 'yes':
view_shopping_list(username)
nut_sum_shop = input("Do you want to view nutrition summary of your shopping list? (yes/no): ").strip().lower()
if nut_sum_shop == 'yes':
calculate_nutrition_summary_shopping()
add_to_favorite_list = input("\nDo you want to add this product to your favourite list? (yes/no): ").strip().lower()
if add_to_favorite_list == 'yes':
quantity_favourite = input("\n Enter quantity of product (int): ")
add_to_fav_list(username, result, quantity_favourite) # Pass all fields of the product
view_favourite_list = input("Do you want to view your favourite list? (yes/no): ").strip().lower()
if view_favourite_list == 'yes':
view_fav_list(username)
nut_sum_fav = input("Do you want to view nutrition summary of your favourite list? (yes/no): ").strip().lower()
if nut_sum_fav == 'yes':
calculate_nutrition_summary_shopping()
else:
print(f"No product found with barcode: {barcode}")
def display_filters():
print("Select a filter option:")
print("1. Carbohydrates")
print("2. Proteins")
print("3. Sugars")
print("4. Total Fat")
print("5. Saturated Fat")
def check_db_validity():
"""Check the validity of both user auth and product databases."""
def check_user_auth_db():
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
try:
cursor.execute("PRAGMA table_info(Users);")
columns = cursor.fetchall()
expected_columns = {'username', 'password', 'email', 'phone_number', 'registration_date'}
actual_columns = {column[1] for column in columns}
if not expected_columns.issubset(actual_columns):
print("User auth DB is missing some expected columns.")
return False
except sqlite3.Error as e:
print("User auth DB validation failed:", e)
return False
finally:
conn.close()
return True
def check_product_db():
conn = sqlite3.connect(PRODUCT_DB_PATH)
cursor = conn.cursor()
try:
cursor.execute("PRAGMA table_info(Products);")
columns = cursor.fetchall()
expected_columns = {'barcode_num', 'product_name', 'ingredients', 'energy', 'proteins', 'carbohydrates', 'cholesterol', 'sugars', 'total_fat', 'saturated_fat',
'trans_fat', 'sodium', 'fruits_vegetables_nuts', 'dietary_fibre', 'allergens', 'nutrition_grade', 'calcium', 'iodine', 'zinc', 'phosphorous', 'magnesium', 'vitamin_A', 'vitamin_B', 'vitamin_C', 'vitamin_D', 'vitamin_E', 'vitamin_K', 'other'
}
actual_columns = {column[1] for column in columns}
if not expected_columns.issubset(actual_columns):
print("Product DB is missing some expected columns.")
return False
except sqlite3.Error as e:
print("Product DB validation failed:", e)
return False
finally:
conn.close()
return True
user_db_valid = check_user_auth_db()
product_db_valid = check_product_db()
if not user_db_valid or not product_db_valid:
print("One or both databases are not valid. Please check the database setup.")
return False
return True
def initialize_product_db():
"""Initialize the product database and ensure the Products table exists."""
conn = sqlite3.connect(PRODUCT_DB_PATH)
cursor = conn.cursor()
# Drop table if it exists
cursor.execute("DROP TABLE IF EXISTS Products")
# Create the Products table with the specified schema
cursor.execute("""
CREATE TABLE IF NOT EXISTS Products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
barcode_num TEXT UNIQUE,
product_name TEXT,
ingredients TEXT,
energy REAL,
proteins REAL,
carbohydrates REAL,
cholesterol REAL,
sugars REAL,
total_fat REAL,
saturated_fat REAL,
trans_fat REAL,
sodium REAL,
fruits_vegetables_nuts REAL,
dietary_fibre REAL DEFAULT 0,
allergens TEXT,
nutrition_grade TEXT,
calcium REAL DEFAULT 0,
iodine REAL DEFAULT 0,
zinc REAL DEFAULT 0,
phosphorous REAL DEFAULT 0,
magnesium REAL DEFAULT 0,
vitamin_A REAL DEFAULT 0,
vitamin_B REAL DEFAULT 0,
vitamin_C REAL DEFAULT 0,
vitamin_D REAL DEFAULT 0,
vitamin_E REAL DEFAULT 0,
vitamin_K REAL DEFAULT 0,
other TEXT DEFAULT ""
)
""")
conn.commit()
conn.close()
print("Product database initialized and schema created.")
def get_valid_float(prompt):
while True:
try:
return float(input(prompt))
except ValueError:
print("Invalid input. Please enter a numeric value.")
def get_valid_int(prompt, max_choice):
while True:
try:
choice = int(input(prompt))
if 1 <= choice <= max_choice:
return choice
else:
print(f"Invalid choice. Please enter a number between 1 and {max_choice}.")
except ValueError:
print("Invalid input. Please enter a numeric value.")
def collect_form_data(username):
"""Collect and store health data from the user."""
conn = sqlite3.connect(HEALTH_DB_PATH)
cursor = conn.cursor()
age = get_valid_int("Enter your age: ", 100)
height = get_valid_float("Enter your height (in cm): ")
weight = get_valid_float("Enter your weight (in kg): ")
print("What is your dietary type?")
print("1. Eggetarian 2. Vegetarian 3. Non-vegetarian 4. Jain")
diet_choice = get_valid_int("Your choice: ", 4)
diet_type = ['Eggetarian', 'Vegetarian', 'Non-vegetarian', 'Jain'][diet_choice-1]
print("What chronic illnesses do you have? (separate multiple answers with commas)")
print("1. Diabetes 2. Obesity 3. High blood pressure 4. Heart diseases 5. Lactose intolerance/food allergies 6. None")
chronic_illness_choices = input("Your choices: ").split(',')
illness_map = ['Diabetes', 'Obesity', 'High blood pressure', 'Heart diseases', 'Lactose intolerance/food allergies', 'None']
try:
chronic_illnesses = [illness_map[int(choice.strip())-1] for choice in chronic_illness_choices]
except (IndexError, ValueError):
print("Invalid choice(s). Defaulting to 'None'.")
chronic_illnesses = ['None']
print("What specific dietary restrictions do you follow? (separate multiple answers with commas)")
print("1. Low-sugar 2. Low-fat 3. Low-salt 4. Protein-rich 5. Anti-inflammatory 6. Gluten-free")
dietary_restriction_choices = input("Your choices: ").split(',')
restriction_map = ['Low-sugar', 'Low-fat', 'Low-salt', 'Protein-rich', 'Anti-inflammatory', 'Gluten-free']
try:
dietary_restrictions = [restriction_map[int(choice.strip())-1] for choice in dietary_restriction_choices]
except (IndexError, ValueError):
print("Invalid choice(s). No dietary restrictions recorded.")
dietary_restrictions = []
print("Are there specific ingredients that trigger your condition(s) or cause discomfort? (separate multiple answers with commas)")
print("1. Sugar 2. Fats 3. Salt 4. Lactose 5. Wheat 6. None")
trigger_choices = input("Your choices: ").split(',')
# Define the mapping including 'None'
trigger_map = ['Sugar', 'Fats', 'Salt', 'Lactose', 'Wheat', 'None']
try:
# Use list comprehension to gather selected triggers
trigger_ingredients = [trigger_map[int(choice.strip()) - 1] for choice in trigger_choices]
# Check if 'None' was selected, if so clear the list
if 'None' in trigger_ingredients:
trigger_ingredients = ['None']
except (IndexError, ValueError):
print("Invalid choice(s). No trigger ingredients recorded.")
trigger_ingredients = []
print("What health goal do you have? (separate multiple answers with commas)")
print("1. Blood sugar control 2. Weight maintenance 3. Manage cholesterol 4. Blood pressure control 5. Bodybuilding 6. Control symptoms of your chronic illness 7. None")
health_goal_choices = input("Your choices: ").split(',')
goal_map = ['Blood sugar control', 'Weight maintenance', 'Manage cholesterol', 'Blood pressure control', 'Bodybuilding', 'Control symptoms of your chronic illness', 'None']
try:
health_goals = [goal_map[int(choice.strip())-1] for choice in health_goal_choices]
except (IndexError, ValueError):
print("Invalid choice(s). Defaulting to 'None'.")
health_goals = ['None']
cursor.execute('''
INSERT INTO health_form (username, age, height, weight, diet_type, chronic_illnesses, dietary_restrictions, trigger_ingredients, health_goals)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (username, age, height, weight, diet_type,','.join(chronic_illnesses),','.join(dietary_restrictions), ','.join(trigger_ingredients), ','.join(health_goals)))
conn.commit()
conn.close()
return {
'What is your dietary type?': [diet_type],
'What chronic illnesses do you have? (separate multiple answers with commas)': chronic_illnesses,
'What specific dietary restrictions do you follow? (separate multiple answers with commas)': dietary_restrictions,
'Are there specific ingredients that trigger your condition(s) or cause discomfort? (separate multiple answers with commas)': trigger_ingredients,
'What health goal do you have? (separate multiple answers with commas)': health_goals
}
def calculate_probabilities(user_input, data):
total_count = len(data)
ingredient_counts = defaultdict(int)
conditional_counts = defaultdict(lambda: defaultdict(int))
for _, row in data.iterrows():
ingredients_str = row['What are some healthy alternatives/ingredients you include in your diet?']
if pd.notna(ingredients_str) and isinstance(ingredients_str, str):
ingredients = [ing.strip().lower() for ing in ingredients_str.split(',')]
for ingredient in ingredients:
ingredient_counts[ingredient] += 1
for column, values in user_input.items():
if pd.notna(row[column]):
row_values = set(val.strip().lower() for val in str(row[column]).split(','))
if any(value.lower() in row_values for value in values):
conditional_counts[ingredient][column] += 1
probabilities = {}
smoothing_factor = 0.1 # Laplace smoothing
for ingredient, count in ingredient_counts.items():
prior = (count + smoothing_factor) / (total_count + smoothing_factor * len(ingredient_counts))
likelihood = 1
for column, values in user_input.items():
cond_count = conditional_counts[ingredient][column]
likelihood *= (cond_count + smoothing_factor) / (count + smoothing_factor * 2)
probabilities[ingredient] = prior * likelihood
return probabilities
def recommend_ingredients(username):
# Fetch user data from the health database
user_input = fetch_health_data(username)
# Load the CSV file
df = pd.read_csv(REC_PRODUCT_PATH)
df.columns = [
'What is your dietary type?',
'What chronic illnesses do you have? (separate multiple answers with commas)',
'What specific dietary restrictions do you follow? (separate multiple answers with commas)',
'Are there specific ingredients that trigger your condition(s) or cause discomfort? (separate multiple answers with commas)',
'What are some healthy alternatives/ingredients you include in your diet?',
'What health goal do you have? (separate multiple answers with commas)'
]
# Calculate probabilities
probabilities = calculate_probabilities(user_input, df)
# Sort ingredients by probability and filter those with confidence >= 0.010
recommended_ingredients = sorted(
[(ingredient, prob) for ingredient, prob in probabilities.items() if prob >= 0.010],
key=lambda x: x[1],
reverse=True
)
print("\nRecommended healthy alternatives/ingredients for your diet:")
if recommended_ingredients:
for i, (ingredient, _) in enumerate(recommended_ingredients, 1):
print(f"{i}. {ingredient.capitalize()}")
else:
print("No recommendations were found based on your input.")
# Ensure recommended_ingredients is a list and process each item
if isinstance(recommended_ingredients, tuple):
recommended_ingredients = list(recommended_ingredients)
elif not isinstance(recommended_ingredients, list):
recommended_ingredients = [recommended_ingredients]
# Process each ingredient
processed_ingredients = []
for item in recommended_ingredients:
# Split by numbers and periods, then take the last part
parts = re.split(r'\d+\.?\s*', item[0]) # Note: item[0] to get the ingredient name
ingredient = parts[-1].strip().lower() if parts else ''
if ingredient:
processed_ingredients.append(ingredient)
products = get_products_by_ingredients(processed_ingredients)
# Display product information
display_product_info_ing(products)
return None
def fetch_health_data(username):
"""Fetch health data from the database for a given user."""
conn = sqlite3.connect(HEALTH_DB_PATH)
cursor = conn.cursor()
cursor.execute('''
SELECT age, height, weight, diet_type, chronic_illnesses, dietary_restrictions, trigger_ingredients, health_goals
FROM health_form
WHERE username = ?
''', (username,))
result = cursor.fetchone()
if result:
# Map the fetched data to a dictionary similar to the form data
age, height, weight, diet_type, chronic_illnesses, dietary_restrictions, trigger_ingredients, health_goals, = result
health_data = {
'What is your dietary type?': [diet_type],
'What chronic illnesses do you have? (separate multiple answers with commas)': chronic_illnesses.split(','),
'What specific dietary restrictions do you follow? (separate multiple answers with commas)': dietary_restrictions.split(','),
'Are there specific ingredients that trigger your condition(s) or cause discomfort? (separate multiple answers with commas)': trigger_ingredients.split(','),
'What health goal do you have? (separate multiple answers with commas)': health_goals.split(',')
}
else:
print(f"No data found for user {username}.")
health_data = {}
conn.close()
return health_data
def get_products_by_ingredients(ingredients):
# Connect to the SQLite database
conn = sqlite3.connect(PRODUCT_DB_PATH)
cursor = conn.cursor()
try:
# Ensure ingredients is a list and remove any blank spaces
if isinstance(ingredients, tuple):
ingredients = list(ingredients)
elif not isinstance(ingredients, list):
ingredients = [ingredients]
# Remove blank spaces and empty strings from ingredients
ingredients = [i.strip().lower() for i in ingredients if i.strip()]
# Create a query that will match any of the ingredients
query = """
SELECT id, barcode_num, product_name, ingredients, energy, proteins, carbohydrates, cholesterol, sugars, total_fat, saturated_fat, trans_fat, sodium, fruits_vegetables_nuts, dietary_fibre, allergens, nutrition_grade, calcium, iodine, zinc, phosphorous, magnesium, vitamin_A, vitamin_B, vitamin_C, vitamin_D, vitamin_E, vitamin_K, other
FROM products
WHERE {}
"""
# Create conditions for each ingredient
conditions = " OR ".join([f"LOWER(ingredients) LIKE ?" for _ in ingredients])
query = query.format(conditions)
# Execute the query with all ingredients
cursor.execute(query, tuple(f'%{ingredient}%' for ingredient in ingredients))
# Fetch all matching results
results = cursor.fetchall()
return results
except sqlite3.Error as e:
print(f"An error occurred: {e}")
finally:
# Close the database connection
conn.close()
return None
def display_product_info_ing(products):
if not products:
print("No products found containing any of the recommended ingredients.")
return
for product in products:
print("\nProduct Information:")
print(f"Product Name: {product[2]}")
print(f"Barcode: {product[1]}")
print(f"Ingredients: {product[3]}")
print(f"Energy: {product[4]}")
print(f"Proteins: {product[5]}")
print(f"Carbohydrates: {product[6]}")
print(f"Cholesterol: {product[7]}")
print(f"Sugars: {product[8]}")
print(f"Total Fat: {product[9]}")
print(f"Saturated Fat: {product[10]}")
print(f"Trans Fat: {product[11]}")
print(f"Sodium: {product[12]}")
print(f"Fruits/Vegetables/Nuts: {product[13]}")
print(f"Dietary Fibre: {product[14]}")
print(f"Allergens: {product[15]}")
print(f"Nutrition Grade: {product[16]}")
print(f"Calcium: {product[17]}")
print(f"Iodine: {product[18]}")
print(f"Zinc: {product[19]}")
print(f"Phosphorous: {product[20]}")
print(f"Magnesium: {product[21]}")
print(f"Vitamin A: {product[22]}")
print(f"Vitamin B: {product[23]}")
print(f"Vitamin C: {product[24]}")
print(f"Vitamin D: {product[25]}")
print(f"Vitamin E: {product[26]}")
print(f"Vitamin K: {product[27]}")
print(f"Other: {product[28]}")
print("-" * 50)
class Register:
def __init__(self, *args):
self.conn = sqlite3.connect(DB_PATH)
self.data = {}
self.get_user_input(args)
def get_user_input(self, variables):
for variable in variables:
if variable.lower() == "password":