pub fn plan(
ctx: &Context,
req: PlanRequest,
) -> Result<Outcome<PantryPlan>, CoreError>Expand description
Work out which ingredients to stock to cook as much of the collection as possible.
The pantry is not consulted. This answers “what should I buy?” from the
recipes under Context::base_path alone, so it needs no pantry
configuration and will happily recommend something already in stock.
The plan is greedy: at each step it takes the ingredient wanted by the most recipes that are not yet cookable, and ties are broken alphabetically. That is an approximation — a greedy set cover is not guaranteed to be the shortest plan — but it is deterministic, which the tie-break is there for.
Only .cook files are considered; .menu files are skipped, and so are
recipes that list no ingredients — and, as in recipes, any that cannot
be read or parsed, each with a warning in Outcome::diagnostics.
Ingredients are those of [required_ingredients] — optional ones are
never worth stocking to make a recipe cookable — compared exactly as
recipes write them, so Flour and flour are two ingredients — unlike
recipes, which lowercases.
§Errors
CoreError::Search if the collection cannot be walked, and
CoreError::Io if a file in it cannot be listed. Never
CoreError::MissingConfig.