2024-02-02 13:49:39 +00:00
|
|
|
from concurrent.futures import Future
|
2024-01-30 17:07:28 +00:00
|
|
|
from datetime import timedelta, datetime
|
|
|
|
from typing import Callable, Optional
|
|
|
|
|
|
|
|
from sqlalchemy import select
|
2024-01-30 17:28:35 +00:00
|
|
|
from sqlalchemy.orm import Session as AlchemySession
|
2024-01-30 17:07:28 +00:00
|
|
|
|
|
|
|
from .models import Resource, Recipe, ResourceFlow
|
|
|
|
|
|
|
|
|
|
|
|
def resource_needs_update(resource: Resource | None, recipe_info_timeout: Optional[timedelta] = None) -> bool:
|
|
|
|
if recipe_info_timeout is None:
|
|
|
|
recipe_info_timeout = timedelta(days=30)
|
|
|
|
return (
|
|
|
|
resource is None
|
|
|
|
or resource.recipes_populated_at is None
|
|
|
|
or datetime.utcnow() - resource.recipes_populated_at > recipe_info_timeout
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2024-02-02 13:49:39 +00:00
|
|
|
def chose_resource(session: AlchemySession, resource_label: str, prompt: Callable) -> Future[Resource | None]:
|
2024-01-30 17:07:28 +00:00
|
|
|
matching_resources = session.scalars(Resource.by_label(resource_label)).all()
|
2024-02-02 13:49:39 +00:00
|
|
|
ret = Future()
|
2024-01-30 17:07:28 +00:00
|
|
|
if len(matching_resources) == 0:
|
2024-02-02 13:49:39 +00:00
|
|
|
print("Could not find any resource matching the search string…")
|
|
|
|
ret.set_result(None)
|
2024-01-30 17:07:28 +00:00
|
|
|
else:
|
|
|
|
options = {(idx + 1): str(matching_resources[idx].label) for idx in range(len(matching_resources))}
|
2024-02-02 13:49:39 +00:00
|
|
|
options[0] = "Continue with wiki search…"
|
2024-01-30 17:07:28 +00:00
|
|
|
|
2024-02-02 13:49:39 +00:00
|
|
|
def resource_selected_cb(res_future: Future[int | None]):
|
|
|
|
selected_res = res_future.result()
|
|
|
|
if selected_res is not None and selected_res != 0:
|
|
|
|
ret.set_result(matching_resources[selected_res - 1])
|
|
|
|
else:
|
|
|
|
ret.set_result(None)
|
2024-01-30 17:07:28 +00:00
|
|
|
|
2024-02-02 13:49:39 +00:00
|
|
|
prompt(options=options, text="Chose a resource", default=1).add_done_callback(resource_selected_cb)
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
2024-02-02 18:02:09 +00:00
|
|
|
def chose_recipe(
|
|
|
|
session: AlchemySession, resource: Resource, prompt: Callable, ingredient: bool = False
|
|
|
|
) -> Future[Recipe | None]:
|
|
|
|
stmt = select(Recipe).distinct()
|
|
|
|
if ingredient:
|
|
|
|
stmt = stmt.join(Recipe.ingredients).filter(ResourceFlow.resource_id == resource.id)
|
|
|
|
else:
|
|
|
|
stmt = stmt.join(Recipe.results).filter(ResourceFlow.resource_id == resource.id)
|
2024-01-30 17:07:28 +00:00
|
|
|
recipes = session.scalars(stmt).all()
|
2024-02-02 13:49:39 +00:00
|
|
|
ret = Future()
|
2024-01-30 17:07:28 +00:00
|
|
|
if len(recipes) == 0:
|
|
|
|
print("No recipes found for resource")
|
2024-02-02 13:49:39 +00:00
|
|
|
ret.set_result(None)
|
2024-01-30 17:07:28 +00:00
|
|
|
elif len(recipes) > 1:
|
|
|
|
options = {(idx + 1): recipes[idx].describe() for idx in range(len(recipes))}
|
2024-02-02 13:49:39 +00:00
|
|
|
|
|
|
|
def user_choice_cb(choice_future: Future[int | None]):
|
|
|
|
user_choice = choice_future.result()
|
|
|
|
if user_choice is None:
|
|
|
|
ret.set_result(None)
|
|
|
|
else:
|
|
|
|
ret.set_result(recipes[user_choice - 1])
|
|
|
|
|
|
|
|
prompt(options=options, text="Select recipe", default=1).add_done_callback(user_choice_cb)
|
2024-01-30 17:07:28 +00:00
|
|
|
else:
|
2024-02-02 13:49:39 +00:00
|
|
|
ret.set_result(recipes[0])
|
|
|
|
return ret
|