diff --git a/recipes.py b/recipes.py index 12dcc37..ed68506 100644 --- a/recipes.py +++ b/recipes.py @@ -1,4 +1,5 @@ from abc import abstractmethod +from collections import defaultdict import sys from typing import Dict, List, Any, Optional, Set import os @@ -117,29 +118,54 @@ class Ingredient(Element): conversions.append(conversion) self["conversions"] = conversions - def convert( - self, amount: float, unitfrom: Unit, unitto: Unit, scannedunits: List[Unit] = [] - ) -> Optional[float]: - # TODO: this can not solve conversions when we have kg -> g and g -> piece - if unitto == unitfrom: - return amount - conversions = ( - self["conversions"] + unitfrom["conversions"] + unitto["conversions"] - ) - for conv in conversions: - ratio: float = conv["ratio"] - if ( - conv["from"]["name"] == unitfrom["name"] - and conv["to"]["name"] == unitto["name"] - ): - return amount * ratio - if ( - conv["to"]["name"] == unitfrom["name"] - and conv["from"]["name"] == unitto["name"] - ): - return amount / ratio + def dfs( + self, + conversions: Dict[str, Dict[str, float]], + startname: str, + endname: str, + visited: Optional[List[str]] = None, + ) -> Optional[List[str]]: + if visited is None: + visited = [] + if startname == endname: + return visited + [startname] + + for nextunit in conversions[startname].keys(): + if nextunit in visited: + continue + result = self.dfs(conversions, nextunit, endname, visited+[startname]) + if result is not None: + return result return None + def convert( + self, amount: float, unitfrom: Unit, unitto: Unit + ) -> Optional[float]: + conversions: Dict[str, Dict[str, float]] = defaultdict(dict) + # construct node tree + convs = self["conversions"] + for unit in self.ctx.units.units: + convs += unit["conversions"] + for conv in convs: + fromname = conv["from"]["name"] + toname = conv["to"]["name"] + conversions[fromname][toname] = conv["ratio"] + conversions[toname][fromname] = 1 / conv["ratio"] + + # find path between conversions + path = self.dfs(conversions, unitfrom["name"], unitto["name"]) + if path is None: + print( + f'WARNING: {self["name"]} has a known price, but conversion {unitfrom["name"]} -> {unitto["name"]} not known' + ) + return None + assert len(path) != 0 + oldelem = path[0] + for elem in path[1:]: + amount *= conversions[oldelem][elem] + oldelem = elem + return amount + def getprice(self, amount: float, unit: Unit) -> Optional[float]: if "prices" not in self.dct: return None @@ -190,6 +216,9 @@ class PriceDBs: self.pricedbs.append(pricedb) return self.ctx.issues + def __repr__(self) -> str: + return self.pricedbs.__repr__() + class PriceDB(Element): def load(self, dct: Dict[str, Any]) -> None: @@ -258,6 +287,19 @@ class Recipe(Element): subrecipes.append(rp) self["subrecipes"] = subrecipes + price: Optional[int] = 0 + ingswithprice = 0 + ingswithoutprice = 0 + for ing in ingredients: + if ing["price"] is None: + ingswithoutprice += 1 + continue + ingswithprice += 1 + price += ing["price"] + if ingswithoutprice != 0 or len(ingredients) == 0: + price = None + self["price"] = price + class Builder: def __init__(self) -> None: diff --git a/templates/base.html b/templates/base.html index eb568e5..27e990b 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,3 +1,6 @@ +{% macro price(rec) -%} +{% if rec.price == None %}?{%else%}{{rec.price|round(1)|numprint}}{% endif %} CZK +{%- endmacro %}
@@ -8,4 +11,4 @@ {% block body %}{% endblock %} - \ No newline at end of file + diff --git a/templates/index.html b/templates/index.html index 847803e..ada8bfd 100644 --- a/templates/index.html +++ b/templates/index.html @@ -3,6 +3,6 @@ {%block body %}