Files
boehmitools-main/plugins/tandoor-ai-import/app/quality.py
T
2026-07-24 21:37:03 +02:00

119 lines
3.8 KiB
Python

from __future__ import annotations
import re
from typing import Any
from .models import RecipeSpec
FORBIDDEN_UNIT_NAMES = {
"bis",
"oder",
"und",
"limette",
"zitrone",
"saft",
"abrieb",
}
SUSPICIOUS_FOOD_PREFIXES = (
"saft von",
"abrieb von",
"schale von",
)
UNIT_PREFIX_PATTERN = re.compile(
r"^\s*\d+(?:[.,/]\d+)?\s*(?:g|kg|ml|l|tl|el|cup|oz)\b",
re.IGNORECASE,
)
def local_quality_warnings(recipe: RecipeSpec) -> list[dict[str, Any]]:
warnings: list[dict[str, Any]] = []
for step_index, step in enumerate(recipe.steps):
for ingredient_index, ingredient in enumerate(step.ingredients):
location = (
f"Schritt {step_index + 1}, Zutat {ingredient_index + 1} "
f"({ingredient.food_name})"
)
food_folded = ingredient.food_name.strip().casefold()
unit_folded = (ingredient.unit_name or "").strip().casefold()
if unit_folded in FORBIDDEN_UNIT_NAMES:
warnings.append(
{
"severity": "blocking",
"code": "suspicious_unit",
"message": (
f"{location}: Die Einheit „{ingredient.unit_name}“ "
"wirkt wie ein Parsingfehler."
),
}
)
if food_folded.startswith(SUSPICIOUS_FOOD_PREFIXES):
warnings.append(
{
"severity": "blocking",
"code": "suspicious_food_prefix",
"message": (
f"{location}: Der Food-Name wirkt unvollständig "
"oder falsch geparst."
),
}
)
if UNIT_PREFIX_PATTERN.search(ingredient.food_name):
warnings.append(
{
"severity": "blocking",
"code": "amount_inside_food",
"message": (
f"{location}: Menge oder Einheit steckt noch im Food-Namen."
),
}
)
if " oder " in food_folded or " und " in food_folded:
warnings.append(
{
"severity": "warning",
"code": "composite_food",
"message": (
f"{location}: Alternative oder zusammengesetzte Zutat "
"sollte meist als Haupt-Food plus Notiz erfasst werden."
),
}
)
if ingredient.amount_max is not None and ingredient.amount_max > ingredient.amount:
warnings.append(
{
"severity": "info",
"code": "amount_range",
"message": (
f"{location}: Mengenbereich "
f"{ingredient.amount:g} bis {ingredient.amount_max:g} "
"wird in Tandoor über Mindestmenge plus Notiz abgebildet."
),
}
)
if not ingredient.original_text.strip():
warnings.append(
{
"severity": "warning",
"code": "missing_original_text",
"message": f"{location}: original_text fehlt.",
}
)
if not recipe.steps:
warnings.append(
{
"severity": "blocking",
"code": "missing_steps",
"message": "Das Rezept enthält keine Schritte.",
}
)
return warnings