/*
Hurry Curry! - a game about cooking
Copyright (C) 2025 Hurry Curry! Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, version 3 of the License only.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
use hurrycurry_protocol::{Demand, ItemIndex, Recipe, TileIndex};
use std::collections::{HashMap, HashSet};
pub fn generate_demands(
tiles: &HashSet,
items: &HashSet,
raw_demands: &[(ItemIndex, Option, f32)],
recipes: &[Recipe],
) -> Vec {
let recipes = recipes
.iter()
.filter(|r| r.tile().map(|t| tiles.contains(&t)).unwrap_or(true))
.collect::>();
let mut producable = HashMap::new();
for i in items {
producable.insert(*i, 0.0);
}
loop {
let prod_count = producable.len();
for r in &recipes {
let output_count = r.outputs().iter().filter(|o| !items.contains(o)).count();
let Some(ingred_cost) = r
.inputs()
.iter()
.map(|i| producable.get(i).copied())
.reduce(|a, b| {
if let (Some(a), Some(b)) = (a, b) {
Some(a + b)
} else {
None
}
})
.unwrap_or(Some(0.))
else {
continue;
};
let base_cost = match r {
Recipe::Passive { speed, .. } => 2. + (1. / speed) * 0.1,
Recipe::Active { speed, .. } => 2. + (1. / speed),
Recipe::Instant { .. } => 1.,
};
let output_cost = (ingred_cost + base_cost) / output_count as f32;
for o in r.outputs() {
let cost = producable.entry(o).or_insert(f32::INFINITY);
*cost = cost.min(output_cost);
}
}
if prod_count == producable.len() {
break;
}
}
raw_demands
.iter()
.filter_map(|(i, o, d)| {
producable.get(i).map(|cost| Demand {
input: *i,
output: *o,
duration: *d,
points: *cost as i64,
})
})
.collect()
}