Add Doris Kitchen household recipe app

This commit is contained in:
Fizzlepoof
2026-05-16 20:22:45 +00:00
parent 19f1f8c5e3
commit 9f614ca0e7
30 changed files with 2009 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
from __future__ import annotations
import re
from typing import Any
def normalize_token(value: str) -> str:
value = re.sub(r"[^a-z0-9]+", " ", value.lower())
return " ".join(part for part in value.split() if part)
def extract_ingredients(payload: dict[str, Any]) -> list[str]:
out: list[str] = []
seen: set[str] = set()
for item in payload.get("items") or []:
name = normalize_token(str(item.get("name") or ""))
if not name or name in seen:
continue
seen.add(name)
out.append(name)
return out
def extract_tags(payload: dict[str, Any]) -> list[str]:
return [normalize_token(str(tag)) for tag in (payload.get("tags") or []) if normalize_token(str(tag))]
def score_recipe(query: str, payload: dict[str, Any], profile: dict[str, Any]) -> tuple[int, list[str]]:
score = 50
reasons: list[str] = []
haystack = " ".join(
[
normalize_token(str(payload.get("name") or "")),
normalize_token(str(payload.get("description") or "")),
" ".join(extract_ingredients(payload)),
" ".join(extract_tags(payload)),
]
)
query_terms = [term for term in normalize_token(query).split() if len(term) > 2]
if query_terms:
matched = sum(1 for term in query_terms if term in haystack)
score += matched * 6
if matched:
reasons.append(f"Matches query terms: {matched}")
ingredients = extract_ingredients(payload)
tags = extract_tags(payload)
approved_ingredients = {normalize_token(k): int(v) for k, v in (profile.get("approved_ingredients") or {}).items()}
rejected_ingredients = {normalize_token(k): int(v) for k, v in (profile.get("rejected_ingredients") or {}).items()}
approved_tags = {normalize_token(k): int(v) for k, v in (profile.get("approved_tags") or {}).items()}
rejected_tags = {normalize_token(k): int(v) for k, v in (profile.get("rejected_tags") or {}).items()}
soft_blacklist = {normalize_token(item.get("name", "")) for item in (profile.get("soft_blacklist") or []) if item.get("enabled")}
for term in sorted(soft_blacklist):
if term and term in haystack:
score -= 30
reasons.append(f"Soft blacklist term: {term}")
liked_hits = 0
for ingredient in ingredients:
liked_hits += approved_ingredients.get(ingredient, 0)
score -= min(rejected_ingredients.get(ingredient, 0) * 7, 18)
for tag in tags:
liked_hits += approved_tags.get(tag, 0)
score -= min(rejected_tags.get(tag, 0) * 5, 12)
if liked_hits:
score += min(liked_hits * 3, 18)
reasons.append("Aligned with prior approvals")
title = str(payload.get("name") or "")
if len(title.split()) <= 10:
score += 3
reasons.append("Clear short title")
total_time = payload.get("time")
if isinstance(total_time, int):
if total_time <= 45:
score += 6
reasons.append("Weeknight-friendly time")
elif total_time >= 120:
score -= 6
description = str(payload.get("description") or "")
if description.count("\n") >= 3:
score += 4
reasons.append("Structured instructions")
return max(0, min(100, score)), reasons