nil_core/infrastructure/
storage.rs1use crate::continent::Coord;
5use crate::error::{Error, Result};
6use crate::infrastructure::building::{Building, BuildingLevel, StorageId};
7use derive_more::{Deref, From, Into};
8use nil_num::growth::growth;
9use serde::{Deserialize, Serialize};
10use std::collections::HashMap;
11use std::ops::{Add, AddAssign, Sub, SubAssign};
12
13pub trait Storage: Building {
15 fn storage_id(&self) -> StorageId;
16 fn capacity(&self, stats: &StorageStatsTable) -> Result<StorageCapacity>;
18 fn min_capacity(&self) -> StorageCapacity;
20 fn max_capacity(&self) -> StorageCapacity;
22}
23
24#[derive(Clone, Debug, Deserialize, Serialize)]
25#[serde(rename_all = "camelCase")]
26pub struct StorageStats {
27 pub level: BuildingLevel,
28 pub capacity: StorageCapacity,
29}
30
31#[derive(Clone, Debug, Deserialize, Serialize)]
32#[serde(rename_all = "camelCase")]
33pub struct StorageStatsTable {
34 id: StorageId,
35 table: HashMap<BuildingLevel, StorageStats>,
36}
37
38impl StorageStatsTable {
39 pub(crate) fn new(storage: &dyn Storage) -> Self {
40 let max_level = *storage.max_level();
41 let mut table = HashMap::with_capacity((max_level).into());
42
43 let mut capacity = f64::from(storage.min_capacity());
44 let capacity_growth = growth()
45 .floor(capacity)
46 .ceil(storage.max_capacity())
47 .max_level(max_level)
48 .call();
49
50 for level in 1..=max_level {
51 let level = BuildingLevel::new(level);
52 table.insert(
53 level,
54 StorageStats {
55 level,
56 capacity: StorageCapacity::from(capacity.ceil()),
57 },
58 );
59
60 debug_assert!(capacity.is_normal());
61
62 capacity += capacity * capacity_growth;
63 }
64
65 table.shrink_to_fit();
66
67 Self { id: storage.storage_id(), table }
68 }
69
70 #[inline]
71 pub fn id(&self) -> StorageId {
72 self.id
73 }
74
75 #[inline]
76 pub fn get(&self, level: BuildingLevel) -> Result<&StorageStats> {
77 self
78 .table
79 .get(&level)
80 .ok_or(Error::StorageStatsNotFoundForLevel(self.id, level))
81 }
82}
83
84#[derive(
86 Clone,
87 Copy,
88 Debug,
89 Deref,
90 Default,
91 From,
92 Into,
93 PartialEq,
94 Eq,
95 PartialOrd,
96 Ord,
97 Deserialize,
98 Serialize,
99)]
100#[into(u32, f64)]
101pub struct StorageCapacity(u32);
102
103impl StorageCapacity {
104 #[inline]
105 pub const fn new(value: u32) -> Self {
106 Self(value)
107 }
108}
109
110impl PartialEq<u32> for StorageCapacity {
111 fn eq(&self, other: &u32) -> bool {
112 self.0.eq(other)
113 }
114}
115
116impl Add for StorageCapacity {
117 type Output = StorageCapacity;
118
119 fn add(self, rhs: Self) -> Self::Output {
120 Self(self.0.saturating_add(rhs.0))
121 }
122}
123
124impl Add<u32> for StorageCapacity {
125 type Output = StorageCapacity;
126
127 fn add(self, rhs: u32) -> Self::Output {
128 Self(self.0.saturating_add(rhs))
129 }
130}
131
132impl AddAssign for StorageCapacity {
133 fn add_assign(&mut self, rhs: Self) {
134 *self = *self + rhs;
135 }
136}
137
138impl AddAssign<u32> for StorageCapacity {
139 fn add_assign(&mut self, rhs: u32) {
140 *self = *self + rhs;
141 }
142}
143
144impl Sub for StorageCapacity {
145 type Output = StorageCapacity;
146
147 fn sub(self, rhs: Self) -> Self::Output {
148 Self(self.0.saturating_sub(rhs.0))
149 }
150}
151
152impl Sub<u32> for StorageCapacity {
153 type Output = StorageCapacity;
154
155 fn sub(self, rhs: u32) -> Self::Output {
156 Self(self.0.saturating_sub(rhs))
157 }
158}
159
160impl SubAssign for StorageCapacity {
161 fn sub_assign(&mut self, rhs: Self) {
162 *self = *self - rhs;
163 }
164}
165
166impl SubAssign<u32> for StorageCapacity {
167 fn sub_assign(&mut self, rhs: u32) {
168 *self = *self - rhs;
169 }
170}
171
172impl From<f64> for StorageCapacity {
173 fn from(value: f64) -> Self {
174 Self::new(value as u32)
175 }
176}
177
178#[derive(Clone, Debug, Default, Deserialize, Serialize)]
179#[serde(rename_all = "camelCase")]
180pub struct OverallStorageCapacity {
181 pub silo: StorageCapacity,
182 pub warehouse: StorageCapacity,
183}
184
185impl Add for OverallStorageCapacity {
186 type Output = OverallStorageCapacity;
187
188 fn add(mut self, rhs: Self) -> Self::Output {
189 self += rhs;
190 self
191 }
192}
193
194impl AddAssign for OverallStorageCapacity {
195 fn add_assign(&mut self, rhs: Self) {
196 self.silo += rhs.silo;
197 self.warehouse += rhs.warehouse;
198 }
199}
200
201#[derive(Clone, Copy, Debug, Default, Deref, From, Into)]
202pub struct StorageCapacityWeight(f64);
203
204#[derive(Clone, Debug)]
205pub struct OverallStorageCapacityWeight {
206 pub coord: Coord,
207 pub silo: StorageCapacityWeight,
208 pub warehouse: StorageCapacityWeight,
209}
210
211impl OverallStorageCapacityWeight {
212 pub fn new(coord: Coord) -> Self {
213 Self {
214 coord,
215 silo: StorageCapacityWeight::default(),
216 warehouse: StorageCapacityWeight::default(),
217 }
218 }
219}