1use indexmap::IndexMap;
2use serde::Deserialize;
6use std::collections::HashMap;
7
8use crate::Cost;
9
10#[derive(Debug, Deserialize, Default)]
12pub struct GalaxyConfig {
13 pub system_count: usize,
15
16 pub size: GalaxySize,
18
19 pub systems: SystemConfig,
21}
22
23#[derive(Debug, Deserialize, Default)]
24pub struct GalaxySize {
25 pub x: usize,
26 pub y: usize,
27}
28
29#[derive(Debug, Default, Deserialize)]
31pub struct SystemConfig {
32 pub structures: IndexMap<String, StructureConfig>,
34
35 pub resources: HashMap<String, usize>,
37}
38
39#[derive(Clone, Debug, Default, Deserialize)]
43pub struct ProductionConfig {
44 pub metal: Option<usize>,
45 pub crew: Option<usize>,
46 pub water: Option<usize>,
47}
48
49pub type StorageConfig = ProductionConfig;
53
54#[derive(Debug, Default, Deserialize)]
55pub struct StructureConfig {
56 pub description: Option<String>,
58
59 pub starting_level: Option<usize>,
62
63 pub production: Option<Vec<ProductionConfig>>,
67
68 pub production_multiplier: Option<f64>,
72
73 pub storage: Option<Vec<StorageConfig>>,
75
76 pub storage_multiplier: Option<f64>,
78
79 pub cost: Vec<HashMap<String, usize>>,
83
84 pub cost_multiplier: Option<f64>,
88}
89
90impl GalaxyConfig {
91 pub fn get_structure_production(&self, structure: &str, level: usize) -> ProductionConfig {
93 if let Some(structure) = self.systems.structures.get(&structure.to_lowercase()) {
94 structure.get_production(level)
95 } else {
96 ProductionConfig::default()
97 }
98 }
99
100 pub fn get_structure_storage(&self, structure: &str, level: usize) -> StorageConfig {
102 if let Some(structure) = self.systems.structures.get(&structure.to_lowercase()) {
103 structure.get_storage(level)
104 } else {
105 StorageConfig::default()
106 }
107 }
108}
109
110impl StructureConfig {
111 pub fn get_cost(&self, level: usize) -> Cost {
113 let index = if let Some(lvl) = self.starting_level {
115 level - lvl
116 } else {
117 level
118 };
119 if index < self.cost.len() {
120 Cost::from_map(&self.cost[index])
121 } else if let Some(multiplier) = self.cost_multiplier {
122 let (last_level, last_cost) = self.cost.iter().enumerate().last().unwrap();
124 let exponent = index - last_level;
125 let multiplier = multiplier.powi(exponent as i32);
126 let mut cost = last_cost.clone();
127 for (_, value) in cost.iter_mut() {
128 *value = (*value as f64 * multiplier) as usize;
129 }
130 Cost::from_map(&cost)
131 } else {
132 panic!("No cost found for level {}", level);
133 }
134 }
135
136 pub fn get_production(&self, level: usize) -> ProductionConfig {
138 let index = if let Some(lvl) = self.starting_level {
140 level - lvl
141 } else {
142 level
143 };
144 if let Some(production) = &self.production {
145 if index < production.len() {
146 production[index].clone()
147 } else if let Some(multiplier) = self.production_multiplier {
148 let (last_level, last_production) = production.iter().enumerate().last().unwrap();
150 let exponent = index - last_level;
151 let multiplier = multiplier.powi(exponent as i32);
152 let mut production = last_production.clone();
153 if let Some(metal) = production.metal {
154 production.metal = Some((metal as f64 * multiplier) as usize);
155 }
156 if let Some(crew) = production.crew {
157 production.crew = Some((crew as f64 * multiplier) as usize);
158 }
159 if let Some(water) = production.water {
160 production.water = Some((water as f64 * multiplier) as usize);
161 }
162 production.clone()
163 } else {
164 panic!("No production found for level {}", level);
165 }
166 } else {
167 ProductionConfig::default()
168 }
169 }
170
171 pub fn get_storage(&self, level: usize) -> StorageConfig {
173 let index = if let Some(lvl) = self.starting_level {
175 level - lvl
176 } else {
177 level
178 };
179 if let Some(storage) = &self.storage {
180 if index < storage.len() {
181 storage[index].clone()
182 } else if let Some(multiplier) = self.storage_multiplier {
183 let (last_level, last_storage) = storage.iter().enumerate().last().unwrap();
185 let exponent = index - last_level;
186 let multiplier = multiplier.powi(exponent as i32);
187 let mut storage = last_storage.clone();
188 if let Some(metal) = storage.metal {
189 storage.metal = Some((metal as f64 * multiplier) as usize);
190 }
191 if let Some(crew) = storage.crew {
192 storage.crew = Some((crew as f64 * multiplier) as usize);
193 }
194 if let Some(water) = storage.water {
195 storage.water = Some((water as f64 * multiplier) as usize);
196 }
197 storage.clone()
198 } else {
199 panic!("No storage found for level {}", level);
200 }
201 } else {
202 StorageConfig::default()
203 }
204 }
205}