nil_core/resources/
maintenance.rs1use super::Food;
5use super::diff::FoodDiff;
6use crate::military::unit::UnitChunkSize;
7use derive_more::{Deref, Display, Into};
8use serde::{Deserialize, Serialize};
9use std::cmp::Ordering;
10use std::num::NonZeroU32;
11use std::ops::{Add, AddAssign, Div, Mul, Sub, SubAssign};
12
13#[derive(
19 Clone,
20 Copy,
21 Debug,
22 Default,
23 Deref,
24 Display,
25 Into,
26 Deserialize,
27 Serialize,
28 PartialEq,
29 Eq,
30 PartialOrd,
31 Ord,
32)]
33#[into(u32, f64, Food)]
34pub struct Maintenance(Food);
35
36impl Maintenance {
37 #[inline]
38 pub const fn new(value: u32) -> Self {
39 Self(Food::new(value))
40 }
41}
42
43impl From<u32> for Maintenance {
44 fn from(value: u32) -> Self {
45 Self::new(value)
46 }
47}
48
49impl From<f64> for Maintenance {
50 fn from(value: f64) -> Self {
51 debug_assert!(value.is_finite());
52 Self::new(value as u32)
53 }
54}
55
56impl Add for Maintenance {
57 type Output = Self;
58
59 fn add(self, rhs: Self) -> Self {
60 Self(self.0 + rhs.0)
61 }
62}
63
64impl Add<Food> for Maintenance {
65 type Output = Self;
66
67 fn add(self, rhs: Food) -> Self {
68 Self(self.0 + rhs)
69 }
70}
71
72impl AddAssign for Maintenance {
73 fn add_assign(&mut self, rhs: Self) {
74 *self = Self(self.0 + rhs.0);
75 }
76}
77
78impl AddAssign<Food> for Maintenance {
79 fn add_assign(&mut self, rhs: Food) {
80 *self = Self(self.0 + rhs);
81 }
82}
83
84impl Sub for Maintenance {
85 type Output = Self;
86
87 fn sub(self, rhs: Self) -> Self {
88 Self(self.0 - rhs.0)
89 }
90}
91
92impl Sub<Food> for Maintenance {
93 type Output = Self;
94
95 fn sub(self, rhs: Food) -> Self {
96 Self(self.0 - rhs)
97 }
98}
99
100impl Sub<Maintenance> for Food {
101 type Output = Self;
102
103 fn sub(self, rhs: Maintenance) -> Self {
104 self - rhs.0
105 }
106}
107
108impl Sub<Maintenance> for FoodDiff {
109 type Output = Self;
110
111 fn sub(self, rhs: Maintenance) -> Self {
112 self - rhs.0
113 }
114}
115
116impl SubAssign for Maintenance {
117 fn sub_assign(&mut self, rhs: Self) {
118 *self = Self(self.0 - rhs.0);
119 }
120}
121
122impl SubAssign<Food> for Maintenance {
123 fn sub_assign(&mut self, rhs: Food) {
124 *self = Self(self.0 - rhs);
125 }
126}
127
128impl SubAssign<Maintenance> for Food {
129 fn sub_assign(&mut self, rhs: Maintenance) {
130 *self = *self - rhs.0;
131 }
132}
133
134impl SubAssign<Maintenance> for FoodDiff {
135 fn sub_assign(&mut self, rhs: Maintenance) {
136 *self = *self - rhs.0;
137 }
138}
139
140impl Mul<u32> for Maintenance {
141 type Output = Maintenance;
142
143 fn mul(self, rhs: u32) -> Self::Output {
144 Self(self.0 * rhs)
145 }
146}
147
148impl Mul<NonZeroU32> for Maintenance {
149 type Output = Maintenance;
150
151 fn mul(self, rhs: NonZeroU32) -> Self::Output {
152 Self(self.0 * rhs.get())
153 }
154}
155
156impl Div<UnitChunkSize> for Maintenance {
157 type Output = Maintenance;
158
159 fn div(self, rhs: UnitChunkSize) -> Self::Output {
160 let maintenance = f64::from(self);
161 let chunk_size = f64::from(rhs);
162 Self::from(maintenance / chunk_size)
163 }
164}
165
166impl PartialEq<Food> for Maintenance {
167 fn eq(&self, other: &Food) -> bool {
168 self.0.eq(other)
169 }
170}
171
172impl PartialEq<Maintenance> for Food {
173 fn eq(&self, other: &Maintenance) -> bool {
174 self.eq(&other.0)
175 }
176}
177
178impl PartialOrd<Food> for Maintenance {
179 fn partial_cmp(&self, other: &Food) -> Option<Ordering> {
180 self.0.partial_cmp(other)
181 }
182}
183
184impl PartialOrd<Maintenance> for Food {
185 fn partial_cmp(&self, other: &Maintenance) -> Option<Ordering> {
186 self.partial_cmp(&other.0)
187 }
188}
189
190#[derive(Clone, Copy, Debug, Deref, Into, Deserialize, Serialize)]
192pub struct MaintenanceRatio(f64);
193
194impl MaintenanceRatio {
195 #[inline]
196 pub const fn new(ratio: f64) -> Self {
197 debug_assert!(ratio.is_finite());
198 debug_assert!(!ratio.is_subnormal());
199 Self(ratio.clamp(0.0, 1.0))
200 }
201}
202
203#[derive(Clone, Debug, Deserialize, Serialize)]
204#[serde(rename_all = "camelCase")]
205pub struct MaintenanceBalance {
206 pub maintenance: Maintenance,
207 pub production: Food,
208}
209
210impl MaintenanceBalance {
211 #[inline]
213 pub fn is_sustainable(&self) -> bool {
214 self.production >= self.maintenance
215 }
216}
217
218impl Add<Maintenance> for MaintenanceBalance {
219 type Output = Self;
220
221 fn add(self, rhs: Maintenance) -> Self::Output {
222 Self {
223 maintenance: self.maintenance + rhs,
224 production: self.production,
225 }
226 }
227}