Desynth page and improved item info api. Added string substitution to utils.

This commit is contained in:
Aodhan
2025-07-10 03:20:33 +01:00
parent b9b47c96f6
commit ef9b64adfe
38 changed files with 5703 additions and 4489 deletions

View File

@@ -15,6 +15,7 @@ from .database import get_session
# Map craft names -> table names in Postgres
ALLOWED_CRAFTS = {
"desynthesis": "recipes_desynthesis",
"woodworking": "recipes_woodworking",
"smithing": "recipes_smithing",
"alchemy": "recipes_alchemy",
@@ -33,6 +34,17 @@ class RecipeUsageSummary(BaseModel):
name: str
level: int
class DesynthRecipe(BaseModel):
id: int
craft: str
cap: Optional[int] | None = None
item: str
crystal: str
ingredients: str # raw text, quantity assumed 1 each
hq1: Optional[str] | None = None
hq2: Optional[str] | None = None
hq3: Optional[str] | None = None
class ItemRecipeUsage(BaseModel):
crafted: list[RecipeUsageSummary] = []
ingredient: list[RecipeUsageSummary] = []
@@ -60,6 +72,29 @@ def _craft_table(craft: str) -> str:
return ALLOWED_CRAFTS[craft_lower]
@router.get("/recipes/desynthesis", response_model=List[DesynthRecipe])
async def list_desynth_recipes(session: AsyncSession = Depends(get_session)):
q = text("SELECT * FROM recipes_desynthesis ORDER BY item")
result = await session.execute(q)
rows = result.fetchall()
out: list[DesynthRecipe] = []
for r in rows:
out.append(
DesynthRecipe(
id=r.id,
craft=r.craft,
cap=r.cap,
item=r.item,
crystal=r.crystal,
ingredients=r.ingredients,
hq1=r.hq1,
hq2=r.hq2,
hq3=r.hq3,
)
)
return out
@router.get("/recipes/{craft}", response_model=List[RecipeDetail])
async def list_recipes(
craft: str = Path(..., description="Craft name, e.g. woodworking"),
@@ -134,10 +169,15 @@ async def item_recipe_usage(item_name: str, session: AsyncSession = Depends(get_
)
# As ingredient (simple text match in JSON/array column)
# Match exact ingredient name by looking for the item quoted in the JSON text.
# Using the surrounding double quotes prevents partial matches, e.g. "Chestnut" will not
# match the ingredient string "Chestnut Lumber".
quoted = f'"{item_name}"'
q2 = text(
f"SELECT id, name, level FROM {table} WHERE ingredients::text ILIKE :pat LIMIT 50"
f"SELECT id, name, level FROM {table} "
f"WHERE ingredients::text ILIKE :pat LIMIT 50"
)
res2 = await session.execute(q2, {"pat": f"%{item_name}%"})
res2 = await session.execute(q2, {"pat": f"%{quoted}%"})
for r in res2.fetchall():
if not any(c.id == r.id and c.craft == craft for c in crafted) and not any(
i.id == r.id and i.craft == craft for i in ingredient