From 3e346cf3eb04197410732ed17198bfa0a4083efb Mon Sep 17 00:00:00 2001 From: lucas Date: Fri, 22 Apr 2022 09:30:01 -0700 Subject: [PATCH] Initial commit for MVP --- main.py | 53 +++++++++++- recipe.py | 179 +++++++++++++++++++++++++++++++++++++++ recipes/recipes.json | 1 + static/favicon-16x16.png | Bin 0 -> 405 bytes static/style.css | 62 ++++++++++++++ templates/base.html | 29 +++++++ templates/index.html | 14 +++ templates/new.html | 30 +++++++ templates/recipe.html | 19 +++++ 9 files changed, 386 insertions(+), 1 deletion(-) create mode 100644 recipe.py create mode 100644 recipes/recipes.json create mode 100644 static/favicon-16x16.png create mode 100644 static/style.css create mode 100644 templates/base.html create mode 100644 templates/index.html create mode 100644 templates/new.html create mode 100644 templates/recipe.html diff --git a/main.py b/main.py index d49c7e5..c22931f 100644 --- a/main.py +++ b/main.py @@ -3,5 +3,56 @@ Portfolio Project for CS361 Spring 2022 Written by Lucas Jensen Last updated 3/29/22 for Assignment 1 """ +import json +from flask import Flask, redirect, flash, render_template, request, jsonify +from markupsafe import escape -print("Hello, CS361!") +from recipe import Recipe, RecipeBook, open_json + +app = Flask(__name__) + + +@app.route("/") +def home(): + return render_template("index.html") + + +@app.route('/recipes', methods=['GET']) +def ReturnJSON(): + return render_template("recipe.html", content=open_json()) + + +@app.route('/recipes/<_id>', methods=['GET']) +def recipe_page(_id): + if request.method == 'GET': + # recipe = book.find_by_id(int(_id)) + # return jsonify(recipe.get_recipe()) + recipe = open_json()[_id] + return recipe + + +@app.route('/add', methods=['GET', 'POST']) +def add_recipe(): + if request.method == "POST": + flour = request.form.get("flour_weight") + water = request.form.get("water_weight") + salt = request.form.get("salt_weight") + loaves = request.form.get("yield") + name = request.form.get("name") + + new_recipe = Recipe(name, loaves, flour, water, salt) + book.add_recipes(new_recipe) + + # flash("Recipe Added!") + return redirect("/recipes") + return render_template("new.html") + + +if __name__ == "__main__": + # testing + # recipes = default_recipes() + book = RecipeBook() + # for recipe in recipes: + # book.add_recipes(recipe) + + app.run(debug=True) diff --git a/recipe.py b/recipe.py new file mode 100644 index 0000000..f406aca --- /dev/null +++ b/recipe.py @@ -0,0 +1,179 @@ +""" +Written by Lucas Jensen +Portfolio Project for CS361 +The main logic behind a recipe +""" +import json + + +class RecipeBook: + """ + Represents a recipe book containing several bread recipes + """ + def __init__(self): + self._count = 0 + self._recipes = {} + + def add_recipes(self, recipe: object) -> None: + """ + Adds a recipe to the book + :param recipe: bread recipe object + :return: nothing + """ + keys = open_json() + for key in keys: + if int(key) > self._count: + self._count = int(key) + self._count += 1 + self._recipes[self._count] = recipe + self.save(self._count, recipe) + # self._count += 1 + + def get_recipes(self) -> list: + """ + get the dict of recipes + :return: the dict of recipes + """ + 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[_id] + + def save(self, _id: int, recipe: object) -> None: + """ + Saves a recipe to the JSON file + :param _id: int + :return: nothing + """ + a_dict = {str(_id): recipe.get_recipe()} + + with open('recipes/recipes.json') as f: + data = json.load(f) + + data.update(a_dict) + + with open('recipes/recipes.json', 'w') as f: + json.dump(data, f) + + +class Recipe: + """ + Represents a bread recipe + """ + def __init__(self, name, num_loaves, ap_flour, water, salt): + self._name = name + self._num_loaves = num_loaves + self._ingredients = { + 'ap_flour': ap_flour, + 'water': water, + 'salt': salt + } + + def get_name(self) -> str: + """ + Gets the name of a recipe + :return: + """ + return self._name + + def get_recipe(self) -> dict: + """ + :return: returns the whole recipe as a dict, including quantity + """ + recipe_dict = { + 'quantity': self._num_loaves, + 'name': self._name + } + + for ingredient in self._ingredients: + recipe_dict[ingredient] = self._ingredients[ingredient] + + return recipe_dict + + def get_num_loaves(self) -> int: + """ + :return: int: number of loaves the recipe calls for + """ + return self._num_loaves + + def get_ingredients(self) -> dict: + """ + :return: dictionary of all ingredients + """ + return self._ingredients + + 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: int) -> object: + """ + Scales the recipe by a given factor + :param new_num: integer, the number of desired loaves + :return: Recipe object, now scaled + """ + scale = new_num / self._num_loaves + + ap_flour = self._ingredients['ap_flour'] * scale + water = self._ingredients['water'] * scale + salt = self._ingredients['salt'] * scale + name = f"{self._name} * {scale}" + + scaled_recipe = Recipe(name, new_num, ap_flour, water, salt) + + for ingredient in self._ingredients: + if ingredient not in ['ap_flour', 'water', 'salt']: + mass = self._ingredients[ingredient] * scale + scaled_recipe.add_ingredient(ingredient, mass) + + return scaled_recipe + + +def build_recipe(infile) -> None: + """ + Builds a recipe object from a JSON file + :param infile: filename + :return: nothing + """ + # TODO + pass + + +def default_recipes(): + recipe_1 = Recipe('Country Brown', 1, 600, 300, 13) + recipe_2 = Recipe('Conventional White', 2, 1000, 700, 25) + recipe_3 = recipe_2.scale(4) + + return [recipe_1, recipe_2, recipe_3] + + +def open_json(): + """TODO""" + with open('recipes/recipes.json') as json_file: + data = json.load(json_file) + + return data + + +if __name__ == "__main__": + recipes = default_recipes() + book = RecipeBook() + for recipe in recipes: + book.add_recipes(recipe) + + for recipe in book.get_recipes(): + print(book.get_recipes()[recipe]) + + rec = Recipe('sandwich loaf', 2, 1000, 700, 25) + rec.add_ingredient('ww flour', 500) + # rec.save('recipes.json') diff --git a/recipes/recipes.json b/recipes/recipes.json new file mode 100644 index 0000000..a22dd1a --- /dev/null +++ b/recipes/recipes.json @@ -0,0 +1 @@ +{"0": {"quantity": "1", "name": "bread", "ap_flour": "1", "water": "1", "salt": "1"}, "1": {"quantity": 2, "name": "Conventional White", "ap_flour": 1000, "water": 700, "salt": 25}, "2": {"quantity": 4, "name": "Conventional White * 2.0", "ap_flour": 2000.0, "water": 1400.0, "salt": 50.0}, "3": {"quantity": "1", "name": "sourdough", "ap_flour": "100", "water": "1001", "salt": "1001"}, "4": {"quantity": "11", "name": "milk", "ap_flour": "10101", "water": "10", "salt": "10"}, "5": {"quantity": "1", "name": "white", "ap_flour": "100", "water": "50", "salt": "2"}} \ No newline at end of file diff --git a/static/favicon-16x16.png b/static/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..c7530e91c8ff317780d1caa0706e0e90f01867c1 GIT binary patch literal 405 zcmV;G0c!qPx$Pf0{UR5(xF)6Gf(Q4|O8bFQVO*u+?%;YVhm(8hJpCTd^3K#LYWMQ}q}^ah0( z)B}W1(7v`6&0v({s3~SDLM1x)gyXV15V`AY&pkix|G+_*uyDe8umR$n=~34n0PP}B zlmJ~a7=bKAW(a~pvTR);=K{6-i660F@Gq&GN@M}t-Whv#*dIWz-iA)80VGJ~T@!hB zP&+?5T}*~EY9b^}^U>--^;QRx7zA{N#mnQ)>ULTIbY4g0Mu!n3sjdwqw$ci+zW~@B zM@U67>Pk==;q$!*qaQd%&~n-MY{2&%T~A4Y+MNM!Pc>-|$(6ujj)&cWInxPfK31Up zQkMeE5|RG`Owaqw*v6VPXXD<0Zn^2ag9pytQ!!Rj + + + + + + + {% block title %}{% endblock %} + + {% block html_head %}{% endblock %} + + + +
+ {% block content %}{% endblock %} +
+ + + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..7bba820 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,14 @@ +{% extends "base.html" %} +{% block title %}Home Page{% endblock %} + +{% block html_head %} + +{% endblock %} + +{% block content %} + +

Welcome to the Bread App!

+ +

Add, scale, and convert all your bread recipes here.

+ +{% endblock %} \ No newline at end of file diff --git a/templates/new.html b/templates/new.html new file mode 100644 index 0000000..2c033b5 --- /dev/null +++ b/templates/new.html @@ -0,0 +1,30 @@ +{% extends "base.html" %} +{% block title %}Add Recipe{% endblock %} + +{% block html_head %} + +{% endblock %} + +{% block content %} + +

New Recipe

+ +
+ + + +
+

Enter all values grams.

+ +{% for ing in ['flour', 'water', 'salt'] %} + + +
+{% endfor %} + + + + + + +{% endblock %} \ No newline at end of file diff --git a/templates/recipe.html b/templates/recipe.html new file mode 100644 index 0000000..e94cb5b --- /dev/null +++ b/templates/recipe.html @@ -0,0 +1,19 @@ +{% extends "base.html" %} +{% block title %}Recipes{% endblock %} + +{% block html_head %} + +{% endblock %} + +{% block content %} + +

Bread Recipes

+ + +{% endblock %} \ No newline at end of file