/* 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() }