Update recipe converter into an object.

This commit is contained in:
gamerdonkey 2025-09-13 03:12:28 +00:00
parent fbd2222e1a
commit b3be5fa90d

204
recipe.py
View File

@ -4,13 +4,78 @@ from anytree.importer import DictImporter
from sys import argv from sys import argv
def build_table_depth_first(node, rows=None): class TableCell:
def __init__(self, name, rowspan="", colspan="", description="", is_header=False):
self.name = name
self.rowspan = rowspan
self.colspan = colspan
self.description = description
self.is_header = is_header
def to_html(self):
if self.is_header:
html = f"<th title={self.description}>{self.name}</th>"
elif not self.name:
html = f'<td colspan="{self.colspan}" class="filler"></td>'
else:
html = f"<td rowspan='{self.rowspan}' colspan='{self.colspan}' title='{self.description}'>{self.name}</td>"
return html
class Recipe:
def __init__(self, json_filename: str):
with open(json_filename, 'r') as f:
recipe_dict = json.loads(f.read())
self.name = recipe_dict.get("name")
self.desc = recipe_dict.get("description")
importer = DictImporter()
self.sub_recipes = [importer.import_(data) for data in recipe_dict["sub_recipes"]]
def generate_ingredient_list(self):
ingredients = []
for sub_recipe in self.sub_recipes:
for ingredient in sub_recipe.leaves:
if ingredient.description:
ingredients.append(f"{ingredient.name} -- {ingredient.description}")
else:
ingredients.append(ingredient.name)
return ingredients
def generate_task_list(self):
tasks = []
for sub_recipe in self.sub_recipes:
tasks.extend(self.generate_steps_depth_first(sub_recipe, steps=[]))
return tasks
def generate_steps_depth_first(self, node, steps=[]):
for child in sorted(node.children, key=lambda x: x.height, reverse=True):
steps = self.generate_steps_depth_first(child, steps)
if not node.is_leaf:
steps.append(node.description if node.description else node.name)
return steps
def generate_tables(self):
tables = []
for sub_recipe in self.sub_recipes:
tables.append(self.build_table_rows_depth_first(sub_recipe))
return tables
def build_table_rows_depth_first(self, node, rows=None):
if rows is None: if rows is None:
rows = [] rows = []
for child in sorted(node.children, key=lambda x: x.height, reverse=True): for child in sorted(node.children, key=lambda x: x.height, reverse=True):
rows = build_table_depth_first(child, rows) rows = self.build_table_rows_depth_first(child, rows)
colspan = 0 colspan = 0
if node.siblings: if node.siblings:
@ -20,106 +85,69 @@ def build_table_depth_first(node, rows=None):
colspan = max_sibling_height - node.height + 1 colspan = max_sibling_height - node.height + 1
if node.is_leaf: if node.is_leaf:
rows.append([f'<th>{node.name}</th>']) rows.append([TableCell(node.name, description=node.description, is_header=True)])
if colspan > 1: if colspan > 1:
rows[-1].append(f'<td colspan="{colspan-1}" class="filler"></td>') rows[-1].append(TableCell("", colspan=colspan-1))
else: else:
child_leaves = len(node.leaves) child_leaves = len(node.leaves)
cur_row = len(rows) - child_leaves cur_row = len(rows) - child_leaves
rows[cur_row].append(f"<td rowspan='{child_leaves}' colspan='{colspan}' title='{node.description}'>{node.name}</td>") rows[cur_row].append(TableCell(node.name, rowspan=child_leaves, colspan=colspan, description=node.description))
return rows return rows
def to_html(self):
return f"""<!DOCTYPE html>
<html lang='en'>
<head><title>{self.name}</title>
<link rel='stylesheet' type='text/css' href='style.css'>
<meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1'>
</head>
<body>
def generate_steps_depth_first(node, steps=[]): <header>
for child in sorted(node.children, key=lambda x: x.height, reverse=True): <nav><a href='./'>Recipe Index</a></nav>
steps = generate_steps_depth_first(child, steps) <h1>{self.name}</h1>
<p>{self.desc}</p>
</header>
if not node.is_leaf: <main>
steps.append(node.description if node.description else node.name) <div id='needs'>
<h2>Needs</h2>
<ul>
{"\n".join([f" <li>{ingredient}</li>" for ingredient in self.generate_ingredient_list()])}
</ul>
</div>
return steps <div id='preparation'>
<h2>Preparation</h2>
<ol>
{"\n".join([f" <li>{task}</li>" for task in self.generate_task_list()])}
</ol>
</div>
</main>
<summary>
<h2>Tabular Layout</h2>
{"\n".join(
[f"<table cellspacing=0 border=true>\n{"".join(
[f"<tr>\n{"".join(
[f" {cell.to_html()}\n" for cell in row]
)}</tr>\n" for row in table]
)}</table>" for table in self.generate_tables()]
)}
</summary>
</body>
</html>
"""
if len(argv) < 2: if __name__ == "__main__":
if len(argv) < 2:
print(f"usage: {argv[0]} <json file>") print(f"usage: {argv[0]} <json file>")
exit() exit(1)
with open(argv[1], 'r') as f: print(Recipe(argv[1]).to_html())
recipe = json.loads(f.read())
recipe_name = recipe.get("name")
recipe_desc = recipe.get("description")
importer = DictImporter()
sub_recipes = [importer.import_(data) for data in recipe["sub_recipes"]]
print("<!DOCTYPE html>")
print("<html lang='en'>")
print(f"<head><title>{recipe_name}</title>")
print("<link rel='stylesheet' type='text/css' href='style.css'>")
print("<meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1'>")
print("</head>")
print("<body>")
print("<header>")
print("<div id='title'>")
print(f"<h1>{recipe_name}</h1>")
print("</div>")
print("<div id='description'>")
print(f"<p>{recipe_desc}</p>")
print("</div>")
print("</header>")
print("<main>")
print("<div id='needs'>")
print("<h2>Needs</h2>")
print("<ul>")
for sub_recipe in sub_recipes:
for ingredient in sub_recipe.leaves:
if ingredient.description:
print(f" <li>{ingredient.name} -- {ingredient.description}</li>")
else:
print(f" <li>{ingredient.name}</li>")
print("</ul>")
print("</div>")
print("<div id='preparation'>")
print("<h2>Preparation</h2>")
print("<ol>")
for sub_recipe in sub_recipes:
tasks = generate_steps_depth_first(sub_recipe, steps=[])
for task in tasks:
print(f" <li>{task}</li>")
print("</ol>")
print("</div>")
print("</main>")
print("<summary>")
print("<h2>Tabular Layout</h2>")
for sub_recipe in sub_recipes:
print("<p>")
print("<table cellspacing='0' border=true>")
output_rows = build_table_depth_first(sub_recipe)
for row in output_rows:
print("<tr>")
for cell in row:
print(f" {cell}")
print("</tr>")
print("</table>")
print("</p>")
print("</summary>")
print("</body>")
print("</html>")