Advertisement
Guest User

Untitled

a guest
Jul 26th, 2024
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.01 KB | None | 0 0
  1. import random
  2. import json
  3. import os
  4. import re
  5. from collections import defaultdict
  6. import logging
  7. from kivy.app import App
  8. from kivy.uix.label import Label
  9. from kivy.uix.button import Button
  10. from kivy.uix.boxlayout import BoxLayout
  11. from kivy.uix.scrollview import ScrollView
  12. from kivy.uix.textinput import TextInput
  13. from kivy.uix.popup import Popup
  14. from kivy.uix.image import Image
  15. from kivy.uix.floatlayout import FloatLayout
  16.  
  17. # Configure logging
  18. logging.basicConfig(filename='app.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
  19.  
  20. class RecipeApp(App):
  21. def build(self):
  22. try:
  23. self.recipes = self.load_recipes()
  24.  
  25. self.layout = FloatLayout()
  26.  
  27. self.background = Image(source='background.jpg', allow_stretch=True, keep_ratio=False)
  28. self.layout.add_widget(self.background)
  29.  
  30. self.main_layout = BoxLayout(orientation='vertical', padding=10, spacing=10, size_hint=(0.8, 0.8))
  31. self.main_layout.pos_hint = {'center_x': 0.5, 'center_y': 0.5}
  32.  
  33. button_layout = BoxLayout(orientation='horizontal', size_hint_y=None, height=50, spacing=10)
  34.  
  35. self.add_recipe_button = Button(text="Add Recipe", size_hint=(0.3, 1), background_color=(0, 0.5, 0.5, 1))
  36. self.add_recipe_button.bind(on_press=self.show_add_recipe_form)
  37. button_layout.add_widget(self.add_recipe_button)
  38.  
  39. self.remove_recipe_button = Button(text="Remove Recipe", size_hint=(0.3, 1), background_color=(0.5, 0, 0, 1))
  40. self.remove_recipe_button.bind(on_press=self.show_remove_recipe_list)
  41. button_layout.add_widget(self.remove_recipe_button)
  42.  
  43. self.generate_list_button = Button(text="Generate Shopping List", size_hint=(0.4, 1), background_color=(0.5, 0.5, 0, 1))
  44. self.generate_list_button.bind(on_press=self.generate_shopping_list)
  45. button_layout.add_widget(self.generate_list_button)
  46.  
  47. self.main_layout.add_widget(button_layout)
  48.  
  49. self.recipe_display = ScrollView(size_hint=(1, 1))
  50. self.recipe_label = Label(size_hint_y=None, text='', text_size=(None, None), valign='top', halign='left', color=(1, 1, 1, 1))
  51. self.recipe_label.bind(texture_size=self._update_label_height)
  52. self.recipe_display.add_widget(self.recipe_label)
  53. self.main_layout.add_widget(self.recipe_display)
  54.  
  55. self.layout.add_widget(self.main_layout)
  56.  
  57. self.update_recipe_display()
  58. return self.layout
  59. except Exception as e:
  60. logging.exception("Error during build")
  61.  
  62. def _update_label_height(self, instance, value):
  63. instance.height = instance.texture_size[1]
  64. instance.width = instance.texture_size[0]
  65.  
  66. def load_recipes(self):
  67. try:
  68. if os.path.exists('recipes.json'):
  69. with open('recipes.json', 'r') as f:
  70. return json.load(f)
  71. else:
  72. return {} # Start with an empty dictionary if no recipes.json file exists
  73. except Exception as e:
  74. logging.exception("Error loading recipes")
  75. return {}
  76.  
  77. def save_recipes(self):
  78. try:
  79. with open('recipes.json', 'w') as f:
  80. json.dump(self.recipes, f)
  81. except Exception as e:
  82. logging.exception("Error saving recipes")
  83.  
  84. def show_add_recipe_form(self, instance):
  85. try:
  86. layout = BoxLayout(orientation='vertical', padding=10, spacing=10)
  87. self.recipe_name_input = TextInput(hint_text='Recipe Name', size_hint_y=None, height=30)
  88. self.recipe_ingredients_input = TextInput(hint_text='Ingredients (comma separated)', size_hint_y=None, height=100)
  89.  
  90. layout.add_widget(self.recipe_name_input)
  91. layout.add_widget(self.recipe_ingredients_input)
  92.  
  93. submit_button = Button(text='Submit', size_hint_y=None, height=40, background_color=(0, 0.5, 0, 1))
  94. submit_button.bind(on_press=self.add_recipe)
  95. layout.add_widget(submit_button)
  96.  
  97. self.popup = Popup(title='Add Recipe', content=layout, size_hint=(0.8, 0.8))
  98. self.popup.open()
  99. except Exception as e:
  100. logging.exception("Error showing add recipe form")
  101.  
  102. def add_recipe(self, instance):
  103. try:
  104. recipe_name = self.recipe_name_input.text
  105. ingredients_text = self.recipe_ingredients_input.text
  106. ingredients = [ingredient.strip() for ingredient in ingredients_text.split(',')]
  107. self.recipes[recipe_name] = ingredients
  108. self.save_recipes()
  109. self.popup.dismiss()
  110. self.update_recipe_display()
  111. except Exception as e:
  112. logging.exception("Error adding recipe")
  113.  
  114. def show_remove_recipe_list(self, instance):
  115. try:
  116. layout = BoxLayout(orientation='vertical', padding=10, spacing=10)
  117. for recipe in self.recipes.keys():
  118. recipe_layout = BoxLayout(orientation='horizontal', size_hint_y=None, height=40)
  119. recipe_label = Label(text=recipe, size_hint_x=0.8, color=(1, 1, 1, 1)) # Text color set to white
  120. remove_button = Button(text='Remove', size_hint_x=0.2, background_color=(0.5, 0, 0, 1))
  121. remove_button.bind(on_press=lambda btn, r=recipe: self.remove_recipe(r))
  122. recipe_layout.add_widget(recipe_label)
  123. recipe_layout.add_widget(remove_button)
  124. layout.add_widget(recipe_layout)
  125.  
  126. self.popup = Popup(title='Remove Recipe', content=layout, size_hint=(0.8, 0.8))
  127. self.popup.open()
  128. except Exception as e:
  129. logging.exception("Error showing remove recipe list")
  130.  
  131. def remove_recipe(self, recipe_name):
  132. try:
  133. if recipe_name in self.recipes:
  134. del self.recipes[recipe_name]
  135. self.save_recipes()
  136. self.popup.dismiss()
  137. self.update_recipe_display()
  138. except Exception as e:
  139. logging.exception("Error removing recipe")
  140.  
  141. def update_recipe_display(self):
  142. try:
  143. display_text = "Recipes:\n"
  144. for recipe, ingredients in self.recipes.items():
  145. display_text += f"\n{recipe}:\n"
  146. for ingredient in ingredients:
  147. display_text += f"{ingredient}\n"
  148. self.recipe_label.text = display_text
  149. except Exception as e:
  150. logging.exception("Error updating recipe display")
  151.  
  152. def generate_shopping_list(self, instance):
  153. try:
  154. if len(self.recipes) < 2:
  155. logging.warning("Not enough recipes to generate a shopping list.")
  156. return
  157.  
  158. selected_recipes = random.sample(list(self.recipes.items()), 2)
  159. display_text = "Selected Recipes:\n"
  160. for recipe, ingredients in selected_recipes:
  161. display_text += f"\n{recipe}:\n"
  162. for ingredient in ingredients:
  163. display_text += f"{ingredient}\n"
  164.  
  165. all_ingredients = defaultdict(float)
  166. for recipe, ingredients in selected_recipes:
  167. for ingredient in ingredients:
  168. quantity, item = self.parse_ingredient(ingredient)
  169. all_ingredients[item] += quantity
  170.  
  171. # Debugging: print all ingredients and quantities
  172. logging.debug(f"All ingredients combined: {dict(all_ingredients)}")
  173.  
  174. shopping_list_text = "Shopping List:\n\n"
  175. for item, quantity in all_ingredients.items():
  176. shopping_list_text += f"{quantity} {item}\n"
  177.  
  178. self.show_shopping_list_popup(display_text + "\n\n" + shopping_list_text)
  179. except Exception as e:
  180. logging.exception("Error generating shopping list")
  181.  
  182. def parse_ingredient(self, ingredient):
  183. try:
  184. logging.debug(f"Parsing ingredient: {ingredient}")
  185.  
  186. # Check if the ingredient starts with a number
  187. match = re.match(r'(\d*\.?\d*)\s*(.*)', ingredient)
  188. if match:
  189. quantity_str, item = match.groups()
  190. quantity = float(quantity_str) if quantity_str else 1 # Default quantity to 1 if not specified
  191. item = item.strip()
  192. logging.debug(f"Parsed quantity: {quantity}, item: {item}")
  193. return quantity, item
  194. else:
  195. logging.debug(f"No quantity found, default to 1 for item: {ingredient.strip()}")
  196. return 1, ingredient.strip() # Default quantity is 1 if no number is found
  197. except Exception as e:
  198. logging.exception("Error parsing ingredient")
  199. return 1, ingredient.strip() # Default quantity is 1 in case of error
  200.  
  201. def show_shopping_list_popup(self, text):
  202. try:
  203. layout = BoxLayout(orientation='vertical', padding=10, spacing=10)
  204. shopping_list_label = Label(text=text, size_hint_y=None, height=400, text_size=(None, None), valign='top', halign='left', color=(1, 1, 1, 1))
  205. shopping_list_label.bind(texture_size=self._update_label_height)
  206. scroll_view = ScrollView()
  207. scroll_view.add_widget(shopping_list_label)
  208. layout.add_widget(scroll_view)
  209.  
  210. close_button = Button(text='Close', size_hint_y=None, height=40, background_color=(0.5, 0, 0, 1))
  211. close_button.bind(on_press=self.close_popup)
  212. layout.add_widget(close_button)
  213.  
  214. self.popup = Popup(title='Shopping List', content=layout, size_hint=(0.8, 0.8))
  215. self.popup.open()
  216. except Exception as e:
  217. logging.exception("Error showing shopping list popup")
  218.  
  219. def close_popup(self, instance):
  220. try:
  221. self.popup.dismiss()
  222. except Exception as e:
  223. logging.exception("Error closing popup")
  224.  
  225. if __name__ == '__main__':
  226. RecipeApp().run()
  227.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement