use indexmap::IndexMap;
use serde::Deserialize;
use std::collections::HashMap;
use crate::Cost;
#[derive(Debug, Deserialize, Default)]
pub struct GalaxyConfig {
pub system_count: usize,
pub size: GalaxySize,
pub systems: SystemConfig,
}
#[derive(Debug, Deserialize, Default)]
pub struct GalaxySize {
pub x: usize,
pub y: usize,
}
#[derive(Debug, Default, Deserialize)]
pub struct SystemConfig {
pub structures: IndexMap<String, StructureConfig>,
pub resources: HashMap<String, usize>,
}
#[derive(Clone, Debug, Default, Deserialize)]
pub struct ProductionConfig {
pub metal: Option<usize>,
pub crew: Option<usize>,
pub water: Option<usize>,
}
pub type StorageConfig = ProductionConfig;
#[derive(Debug, Default, Deserialize)]
pub struct StructureConfig {
pub description: Option<String>,
pub starting_level: Option<usize>,
pub production: Option<Vec<ProductionConfig>>,
pub production_multiplier: Option<f64>,
pub storage: Option<Vec<StorageConfig>>,
pub storage_multiplier: Option<f64>,
pub cost: Vec<HashMap<String, usize>>,
pub cost_multiplier: Option<f64>,
}
impl GalaxyConfig {
pub fn get_structure_production(&self, structure: &str, level: usize) -> ProductionConfig {
if let Some(structure) = self.systems.structures.get(&structure.to_lowercase()) {
structure.get_production(level)
} else {
ProductionConfig::default()
}
}
pub fn get_structure_storage(&self, structure: &str, level: usize) -> StorageConfig {
if let Some(structure) = self.systems.structures.get(&structure.to_lowercase()) {
structure.get_storage(level)
} else {
StorageConfig::default()
}
}
}
impl StructureConfig {
pub fn get_cost(&self, level: usize) -> Cost {
let index = if let Some(lvl) = self.starting_level {
level - lvl
} else {
level
};
if index < self.cost.len() {
Cost::from_map(&self.cost[index])
} else if let Some(multiplier) = self.cost_multiplier {
let (last_level, last_cost) = self.cost.iter().enumerate().last().unwrap();
let exponent = index - last_level;
let multiplier = multiplier.powi(exponent as i32);
let mut cost = last_cost.clone();
for (_, value) in cost.iter_mut() {
*value = (*value as f64 * multiplier) as usize;
}
Cost::from_map(&cost)
} else {
panic!("No cost found for level {}", level);
}
}
pub fn get_production(&self, level: usize) -> ProductionConfig {
let index = if let Some(lvl) = self.starting_level {
level - lvl
} else {
level
};
if let Some(production) = &self.production {
if index < production.len() {
production[index].clone()
} else if let Some(multiplier) = self.production_multiplier {
let (last_level, last_production) = production.iter().enumerate().last().unwrap();
let exponent = index - last_level;
let multiplier = multiplier.powi(exponent as i32);
let mut production = last_production.clone();
if let Some(metal) = production.metal {
production.metal = Some((metal as f64 * multiplier) as usize);
}
if let Some(crew) = production.crew {
production.crew = Some((crew as f64 * multiplier) as usize);
}
if let Some(water) = production.water {
production.water = Some((water as f64 * multiplier) as usize);
}
production.clone()
} else {
panic!("No production found for level {}", level);
}
} else {
ProductionConfig::default()
}
}
pub fn get_storage(&self, level: usize) -> StorageConfig {
let index = if let Some(lvl) = self.starting_level {
level - lvl
} else {
level
};
if let Some(storage) = &self.storage {
if index < storage.len() {
storage[index].clone()
} else if let Some(multiplier) = self.storage_multiplier {
let (last_level, last_storage) = storage.iter().enumerate().last().unwrap();
let exponent = index - last_level;
let multiplier = multiplier.powi(exponent as i32);
let mut storage = last_storage.clone();
if let Some(metal) = storage.metal {
storage.metal = Some((metal as f64 * multiplier) as usize);
}
if let Some(crew) = storage.crew {
storage.crew = Some((crew as f64 * multiplier) as usize);
}
if let Some(water) = storage.water {
storage.water = Some((water as f64 * multiplier) as usize);
}
storage.clone()
} else {
panic!("No storage found for level {}", level);
}
} else {
StorageConfig::default()
}
}
}