proper recursive finding of conversions

This commit is contained in:
Emi Vasilek 2023-11-14 13:36:49 +01:00
parent 5fd453759b
commit ffa0253193
4 changed files with 71 additions and 25 deletions

View file

@ -1,4 +1,5 @@
from abc import abstractmethod from abc import abstractmethod
from collections import defaultdict
import sys import sys
from typing import Dict, List, Any, Optional, Set from typing import Dict, List, Any, Optional, Set
import os import os
@ -117,29 +118,54 @@ class Ingredient(Element):
conversions.append(conversion) conversions.append(conversion)
self["conversions"] = conversions self["conversions"] = conversions
def convert( def dfs(
self, amount: float, unitfrom: Unit, unitto: Unit, scannedunits: List[Unit] = [] self,
) -> Optional[float]: conversions: Dict[str, Dict[str, float]],
# TODO: this can not solve conversions when we have kg -> g and g -> piece startname: str,
if unitto == unitfrom: endname: str,
return amount visited: Optional[List[str]] = None,
conversions = ( ) -> Optional[List[str]]:
self["conversions"] + unitfrom["conversions"] + unitto["conversions"] if visited is None:
) visited = []
for conv in conversions: if startname == endname:
ratio: float = conv["ratio"] return visited + [startname]
if (
conv["from"]["name"] == unitfrom["name"] for nextunit in conversions[startname].keys():
and conv["to"]["name"] == unitto["name"] if nextunit in visited:
): continue
return amount * ratio result = self.dfs(conversions, nextunit, endname, visited+[startname])
if ( if result is not None:
conv["to"]["name"] == unitfrom["name"] return result
and conv["from"]["name"] == unitto["name"]
):
return amount / ratio
return None 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]: def getprice(self, amount: float, unit: Unit) -> Optional[float]:
if "prices" not in self.dct: if "prices" not in self.dct:
return None return None
@ -190,6 +216,9 @@ class PriceDBs:
self.pricedbs.append(pricedb) self.pricedbs.append(pricedb)
return self.ctx.issues return self.ctx.issues
def __repr__(self) -> str:
return self.pricedbs.__repr__()
class PriceDB(Element): class PriceDB(Element):
def load(self, dct: Dict[str, Any]) -> None: def load(self, dct: Dict[str, Any]) -> None:
@ -258,6 +287,19 @@ class Recipe(Element):
subrecipes.append(rp) subrecipes.append(rp)
self["subrecipes"] = subrecipes 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: class Builder:
def __init__(self) -> None: def __init__(self) -> None:

View file

@ -1,3 +1,6 @@
{% macro price(rec) -%}
{% if rec.price == None %}?{%else%}{{rec.price|round(1)|numprint}}{% endif %} CZK
{%- endmacro %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>

View file

@ -3,6 +3,6 @@
{%block body %} {%block body %}
<h1>Recipes</h1> <h1>Recipes</h1>
{% for recipe in recipes %} {% for recipe in recipes %}
<li><a href="{{ recipe.outpath }}">{{ recipe.title }}</a></li> <li>{{price(recipe)}} <a href="{{ recipe.outpath }}">{{ recipe.title }}</a></li>
{% endfor %} {% endfor %}
{%endblock%} {%endblock%}

View file

@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% macro ingredientpart(ing) -%} {% macro ingredientpart(ing) -%}
{% if ing.price != None %}{{ing.price|round(1)|numprint}}{%else%} ?{%endif%} {{ing.amount|amountprint}} {{ing["unit"].name}} {{ ing.name }} {{price(ing)}} {{ing.amount|amountprint}} {{ing["unit"].name}} {{ ing.name }} {{ing.note}}
{%- endmacro %} {%- endmacro %}
{% macro ingredient(ing) -%} {% macro ingredient(ing) -%}
@ -22,6 +22,7 @@
{% for ing in rec.ingredients %} {% for ing in rec.ingredients %}
<li>{{ingredient(ing)}}</li> <li>{{ingredient(ing)}}</li>
{% endfor %} {% endfor %}
price: {{ price(rec) }}
{% endif %} {% endif %}
{% if rec.steps|length != 0 %} {% if rec.steps|length != 0 %}
<h3>Steps</h3> <h3>Steps</h3>