aboutsummaryrefslogtreecommitdiff
path: root/server/data/src/demands.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/data/src/demands.rs')
-rw-r--r--server/data/src/demands.rs88
1 files changed, 88 insertions, 0 deletions
diff --git a/server/data/src/demands.rs b/server/data/src/demands.rs
new file mode 100644
index 00000000..77e187af
--- /dev/null
+++ b/server/data/src/demands.rs
@@ -0,0 +1,88 @@
+/*
+ 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 <https://www.gnu.org/licenses/>.
+
+*/
+use hurrycurry_protocol::{Demand, ItemIndex, Recipe, TileIndex};
+use std::collections::{HashMap, HashSet};
+
+pub fn generate_demands(
+ tiles: &HashSet<TileIndex>,
+ items: &HashSet<ItemIndex>,
+ raw_demands: &[(ItemIndex, Option<ItemIndex>, f32)],
+ recipes: &[Recipe],
+) -> Vec<Demand> {
+ let recipes = recipes
+ .iter()
+ .filter(|r| r.tile().map(|t| tiles.contains(&t)).unwrap_or(true))
+ .collect::<Vec<_>>();
+
+ 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()
+}