From 1ff3d6e3a7df7360e3af11c5ebfef9bf082c5b3f Mon Sep 17 00:00:00 2001 From: Mike Shoup Date: Wed, 3 Jul 2019 17:31:11 -0600 Subject: [PATCH] Add filters for og & fg --- src/humulus/app.py | 4 ++ src/humulus/filters.py | 68 +++++++++++++++++++++++++ src/humulus/templates/recipes/info.html | 4 ++ tests/conftest.py | 65 +++++++++++++++++++++++ tests/test_filters.py | 24 +++++++++ 5 files changed, 165 insertions(+) create mode 100644 src/humulus/filters.py create mode 100644 tests/test_filters.py diff --git a/src/humulus/app.py b/src/humulus/app.py index 171b6ba..5bf78c5 100644 --- a/src/humulus/app.py +++ b/src/humulus/app.py @@ -46,4 +46,8 @@ def create_app(test_config=None): from . import auth app.register_blueprint(auth.bp) + # Register custom filters + from . import filters + filters.create_filters(app) + return app diff --git a/src/humulus/filters.py b/src/humulus/filters.py new file mode 100644 index 0000000..010a927 --- /dev/null +++ b/src/humulus/filters.py @@ -0,0 +1,68 @@ +"""This module contains filters used in rendering of Jinja templates.""" + +# Copyright 2019 Mike Shoup +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +def recipe_og(recipe): + """Returns a recipe's Original Gravity""" + points = 0 + grain_points = 0 + # Loop through fermentables, adding up points + for fermentable in recipe['fermentables']: + if fermentable['type'] == 'Grain': + grain_points += ( + float(fermentable['amount']) * float(fermentable['ppg']) + ) + else: + points += ( + float(fermentable['amount']) * float(fermentable['ppg']) + ) + points += grain_points * float(recipe['efficiency']) / 100 + return '{:.3f}'.format( + round(1 + points / (1000 * float(recipe['volume'])), 3) + ) + + +def recipe_fg(recipe): + """Returns a recipe's final gravity""" + if 'yeast' not in recipe: + return 0.0 + og = float(recipe_og(recipe)) + og_delta = 0.0 + # Adjust original gravity by removing nonfermentables (i.e., Lactose) + for fermentable in recipe['fermentables']: + if fermentable['type'] == 'Non-fermentable': + og_delta += ( + float(fermentable['amount']) * float(fermentable['ppg']) / + (1000 * float(recipe['volume'])) + ) + attenuation = ( + ( + float(recipe['yeast']['low_attenuation']) + + float(recipe['yeast']['high_attenuation']) + ) / 200 + ) + print(og - 1 - og_delta) + print(attenuation) + print(og_delta) + return '{:.3f}'.format( + round(1 + (og - 1 - og_delta)*(1 - attenuation) + og_delta, 3) + ) + + + +def create_filters(app): + app.add_template_filter(recipe_og) + app.add_template_filter(recipe_fg) diff --git a/src/humulus/templates/recipes/info.html b/src/humulus/templates/recipes/info.html index 08b70b2..4c9ab2d 100644 --- a/src/humulus/templates/recipes/info.html +++ b/src/humulus/templates/recipes/info.html @@ -32,6 +32,10 @@
{{ recipe.efficiency|int }}%
Batch Volume
{{ recipe.volume|float|round(1) }} gal.
+
OG
+
{{ recipe|recipe_og }}
+
FG
+
{{ recipe|recipe_fg }}
diff --git a/tests/conftest.py b/tests/conftest.py index a53c14c..1176a1b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -152,3 +152,68 @@ class AuthActions(object): @pytest.fixture def auth(client): return AuthActions(client) + + +@pytest.fixture +def sample_recipes(): + """These sample recipes are useful for testing filters.""" + return { + 'blonde-ale': { + 'efficiency': '68.00', + 'fermentables': [ + { + 'amount': '8.50', + 'color': '1.80', + 'name': 'Pale Malt, 2-row (Rahr) (US)', + 'ppg': '37.00', + 'type': 'Grain' + }, + { + 'amount': '0.50', + 'color': '10.00', + 'name': 'Munich Malt 10L (Briess) (US)', + 'ppg': '35.00', + 'type': 'Grain' + } + ], + 'hops': [ + { + 'alpha': '9.30', + 'amount': '0.50', + 'duration': '30.00', + 'name': 'Cascade (US)', + 'use': 'Boil' + }, + { + 'alpha': '9.30', + 'amount': '0.50', + 'duration': '15.00', + 'name': 'Cascade (US)', + 'use': 'Boil' + }, + { + 'alpha': '9.30', + 'amount': '1.00', + 'duration': '5.00', + 'name': 'Cascade (US)', + 'use': 'Boil' + } + ], + 'name': 'Blonde Ale Base', + 'notes': "This is a base recipe. It's okay on its own, but" + 'better with other things, like fruits.', + 'volume': '5.50', + 'yeast': { + 'abv_tolerance': '15.00', + 'code': 'WLP090', + 'flocculation': 'High', + 'high_attenuation': '83.00', + 'lab': 'White Labs', + 'low_attenuation': '76.00', + 'max_temperature': '68.00', + 'min_temperature': '65.00', + 'name': 'San Diego Super Yeast', + 'type': 'Liquid' + } + } + } diff --git a/tests/test_filters.py b/tests/test_filters.py new file mode 100644 index 0000000..71fa9fa --- /dev/null +++ b/tests/test_filters.py @@ -0,0 +1,24 @@ +# Copyright 2019 Mike Shoup +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from humulus.filters import * + + +def test_recipe_og(sample_recipes): + assert recipe_og(sample_recipes['blonde-ale']) == '1.041' + + +def test_recipe_fg(sample_recipes): + assert recipe_fg(sample_recipes['blonde-ale']) == '1.008'