206 lines
5.3 KiB
Python
206 lines
5.3 KiB
Python
"""
|
|
Written by Lucas Jensen
|
|
Portfolio Project for CS361
|
|
The main logic behind a recipe
|
|
Last updated 5/12
|
|
"""
|
|
|
|
import json
|
|
from pprint import pprint
|
|
|
|
JSON_FILE = "recipes/recipes.json"
|
|
|
|
|
|
class RecipeBook:
|
|
"""
|
|
Represents a recipe book containing several bread recipes
|
|
"""
|
|
def __init__(self):
|
|
self._recipes = {} # a dictionary of recipe objects, ID as key
|
|
self._id = 0
|
|
self.__build_recipes()
|
|
|
|
def __build_recipes(self):
|
|
"""
|
|
Builds the recipe book from an existing json file
|
|
:return:
|
|
"""
|
|
with open(JSON_FILE, 'rt') as f:
|
|
recipes_dict = json.load(f)
|
|
|
|
for _id in recipes_dict:
|
|
recipe_dict = recipes_dict[_id]
|
|
recipe = Recipe(recipe_dict['name'], recipe_dict['quantity'])
|
|
recipe.set_id(_id)
|
|
ingredients = recipe_dict['ingredients']
|
|
for ingredient in ingredients:
|
|
recipe.add_ingredient(ingredient, ingredients[ingredient])
|
|
recipe.add_ingredient(ingredient, ingredients[ingredient])
|
|
self._recipes[_id] = recipe
|
|
|
|
def get_recipes(self):
|
|
return self._recipes
|
|
|
|
def find_by_id(self, _id: int) -> object:
|
|
"""
|
|
Finds a recipe object by its assigned id
|
|
:param _id: int, the id of the recipe
|
|
:return: recipe object
|
|
"""
|
|
return self._recipes[str(_id)]
|
|
|
|
def find_and_delete(self, _id):
|
|
"""
|
|
Finds a recipe using its ID and deletes it
|
|
:param _id: int of the recipe's ID
|
|
:return: nothing
|
|
"""
|
|
del self._recipes[str(_id)]
|
|
|
|
# remove from JSON file
|
|
with open(JSON_FILE, 'rt') as f:
|
|
json_file = json.load(f)
|
|
|
|
pprint(json_file)
|
|
|
|
del json_file[str(_id)]
|
|
|
|
with open(JSON_FILE, 'wt') as f:
|
|
json.dump(json_file, f, indent=4)
|
|
|
|
def add_recipe(self, recipe):
|
|
"""
|
|
appends a recipe object to the recipe book
|
|
:param recipe: recipe object
|
|
:return: the id of the newly stored recipe
|
|
"""
|
|
with open(JSON_FILE, 'rt') as f:
|
|
keys = json.load(f)
|
|
|
|
while str(self._id) in keys:
|
|
self._id += 1
|
|
|
|
recipe.set_id(self._id)
|
|
saved_id = self._id
|
|
self._recipes[str(self._id)] = recipe
|
|
self._id += 1
|
|
# pprint(self._recipes)
|
|
self.save(recipe)
|
|
|
|
return saved_id
|
|
|
|
@staticmethod
|
|
def save(recipe):
|
|
"""
|
|
appends a recipe dictionary to the JSON file
|
|
:param recipe:
|
|
:return:
|
|
"""
|
|
with open(JSON_FILE, 'rt') as f:
|
|
recipe_dict = json.load(f)
|
|
|
|
recipe_dict[recipe.get_id()] = recipe.get_recipe()
|
|
|
|
with open(JSON_FILE, 'wt') as f:
|
|
json.dump(recipe_dict, f, indent=4)
|
|
|
|
|
|
class Recipe:
|
|
"""
|
|
Represents a bread recipe
|
|
"""
|
|
def __init__(self, name: str, num_loaves: int):
|
|
self._name = name
|
|
self._num_loaves = num_loaves
|
|
self._ingredients = {}
|
|
self._id = None
|
|
|
|
def get_recipe(self) -> dict:
|
|
"""
|
|
builds and returns the whole recipe as a single dictionary
|
|
:return: dictionary
|
|
"""
|
|
recipe_dict = {
|
|
'quantity': self._num_loaves,
|
|
'name': self._name,
|
|
# 'id': self._id,
|
|
'ingredients': {}
|
|
}
|
|
|
|
for ingredient in self._ingredients:
|
|
recipe_dict['ingredients'][ingredient] = self._ingredients[ingredient]
|
|
|
|
return recipe_dict
|
|
|
|
def get_name(self) -> str:
|
|
return self._name
|
|
|
|
def get_num_loaves(self) -> int:
|
|
return self._num_loaves
|
|
|
|
def get_ingredients(self) -> dict:
|
|
return self._ingredients
|
|
|
|
def get_id(self) -> int:
|
|
return self._id
|
|
|
|
def set_id(self, _id):
|
|
self._id = _id
|
|
|
|
def add_ingredient(self, name: str, mass: int) -> None:
|
|
"""
|
|
Adds an ingredient to the recipe. Mass in grams.
|
|
:param name: string, the name of the ingredient
|
|
:param mass: int, the mass of the ingredient, in grams
|
|
:return:
|
|
"""
|
|
self._ingredients[name] = mass
|
|
|
|
def scale(self, new_num) -> object:
|
|
"""
|
|
Scales the recipe by a given factor
|
|
:param new_num: integer, the number of desired loaves
|
|
:return: Recipe object, now scaled
|
|
"""
|
|
scale = int(new_num) / int(self._num_loaves)
|
|
|
|
scaled_recipe = Recipe(f"{self._name} * {scale}", new_num)
|
|
|
|
for ingredient in self._ingredients:
|
|
mass = self._ingredients[ingredient] * scale
|
|
scaled_recipe.add_ingredient(ingredient, round(mass))
|
|
|
|
return scaled_recipe
|
|
|
|
|
|
def default_recipes():
|
|
"""Adds some sample data"""
|
|
recipe_1 = Recipe('Country Brown', 1)
|
|
recipe_2 = Recipe('Conventional White', 2)
|
|
|
|
sample_recipes = [recipe_1, recipe_2]
|
|
flour = 500
|
|
water = 300
|
|
salt = 12
|
|
|
|
for recipe in sample_recipes:
|
|
recipe.add_ingredient("AP Flour", flour)
|
|
flour += 500
|
|
recipe.add_ingredient("Water", water)
|
|
water += 300
|
|
recipe.add_ingredient("salt", salt)
|
|
salt += 12
|
|
|
|
recipe_3 = recipe_2.scale(4)
|
|
|
|
sample_recipes.append(recipe_3)
|
|
|
|
return sample_recipes
|
|
|
|
|
|
if __name__ == "__main__":
|
|
recipes = default_recipes()
|
|
book = RecipeBook()
|
|
for recipe in recipes:
|
|
book.add_recipe(recipe)
|