1use super::{Food, Iron, Resources, Stone, Wood};
5use crate::error::Result;
6use derive_more::Display;
7use nil_util::{ConstDeref, F64Math};
8use serde::{Deserialize, Serialize};
9use std::cmp::Ordering;
10use std::ops::{Add, AddAssign, Sub, SubAssign};
11
12#[derive(Copy, Debug, Deserialize, Serialize)]
13#[derive_const(Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
14#[serde(default, rename_all = "camelCase")]
15#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
16pub struct ResourcesDiff {
17 pub food: FoodDiff,
18 pub iron: IronDiff,
19 pub stone: StoneDiff,
20 pub wood: WoodDiff,
21}
22
23impl TryFrom<Resources> for ResourcesDiff {
24 type Error = crate::error::Error;
25
26 fn try_from(value: Resources) -> Result<Self> {
27 Ok(Self {
28 food: FoodDiff::try_from(value.food)?,
29 iron: IronDiff::try_from(value.iron)?,
30 stone: StoneDiff::try_from(value.stone)?,
31 wood: WoodDiff::try_from(value.wood)?,
32 })
33 }
34}
35
36const impl Add for ResourcesDiff {
37 type Output = Self;
38
39 fn add(self, rhs: Self) -> Self {
40 Self {
41 food: self.food + rhs.food,
42 iron: self.iron + rhs.iron,
43 stone: self.stone + rhs.stone,
44 wood: self.wood + rhs.wood,
45 }
46 }
47}
48
49const impl Add<Resources> for ResourcesDiff {
50 type Output = Self;
51
52 fn add(self, rhs: Resources) -> Self {
53 Self {
54 food: self.food + rhs.food,
55 iron: self.iron + rhs.iron,
56 stone: self.stone + rhs.stone,
57 wood: self.wood + rhs.wood,
58 }
59 }
60}
61
62const impl Add<ResourcesDiff> for Resources {
63 type Output = Self;
64
65 fn add(self, rhs: ResourcesDiff) -> Self {
66 Self {
67 food: self.food + rhs.food,
68 iron: self.iron + rhs.iron,
69 stone: self.stone + rhs.stone,
70 wood: self.wood + rhs.wood,
71 }
72 }
73}
74
75const impl AddAssign for ResourcesDiff {
76 fn add_assign(&mut self, rhs: Self) {
77 *self = Self {
78 food: self.food + rhs.food,
79 iron: self.iron + rhs.iron,
80 stone: self.stone + rhs.stone,
81 wood: self.wood + rhs.wood,
82 };
83 }
84}
85
86const impl AddAssign<Resources> for ResourcesDiff {
87 fn add_assign(&mut self, rhs: Resources) {
88 *self = Self {
89 food: self.food + rhs.food,
90 iron: self.iron + rhs.iron,
91 stone: self.stone + rhs.stone,
92 wood: self.wood + rhs.wood,
93 };
94 }
95}
96
97const impl AddAssign<ResourcesDiff> for Resources {
98 fn add_assign(&mut self, rhs: ResourcesDiff) {
99 *self = Self {
100 food: self.food + rhs.food,
101 iron: self.iron + rhs.iron,
102 stone: self.stone + rhs.stone,
103 wood: self.wood + rhs.wood,
104 };
105 }
106}
107
108const impl Sub for ResourcesDiff {
109 type Output = Self;
110
111 fn sub(self, rhs: Self) -> Self {
112 Self {
113 food: self.food - rhs.food,
114 iron: self.iron - rhs.iron,
115 stone: self.stone - rhs.stone,
116 wood: self.wood - rhs.wood,
117 }
118 }
119}
120
121const impl Sub<ResourcesDiff> for Resources {
122 type Output = Self;
123
124 fn sub(self, rhs: ResourcesDiff) -> Self {
125 Self {
126 food: self.food - rhs.food,
127 iron: self.iron - rhs.iron,
128 stone: self.stone - rhs.stone,
129 wood: self.wood - rhs.wood,
130 }
131 }
132}
133
134const impl SubAssign for ResourcesDiff {
135 fn sub_assign(&mut self, rhs: Self) {
136 *self = Self {
137 food: self.food - rhs.food,
138 iron: self.iron - rhs.iron,
139 stone: self.stone - rhs.stone,
140 wood: self.wood - rhs.wood,
141 };
142 }
143}
144
145const impl SubAssign<Resources> for ResourcesDiff {
146 fn sub_assign(&mut self, rhs: Resources) {
147 *self = Self {
148 food: self.food - rhs.food,
149 iron: self.iron - rhs.iron,
150 stone: self.stone - rhs.stone,
151 wood: self.wood - rhs.wood,
152 };
153 }
154}
155
156const impl SubAssign<ResourcesDiff> for Resources {
157 fn sub_assign(&mut self, rhs: ResourcesDiff) {
158 *self = Self {
159 food: self.food - rhs.food,
160 iron: self.iron - rhs.iron,
161 stone: self.stone - rhs.stone,
162 wood: self.wood - rhs.wood,
163 };
164 }
165}
166
167macro_rules! decl_resource_diff {
168 ($($resource:ident),+ $(,)?) => {
169 paste::paste! {
170 $(
171 #[derive(Copy, Debug, Display, Deserialize, Serialize, ConstDeref, F64Math)]
172 #[derive_const(Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
173 #[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
174 pub struct [<$resource Diff>](i32);
175
176 impl [<$resource Diff>] {
177 #[inline]
178 pub const fn new(value: i32) -> Self {
179 Self(value)
180 }
181
182 #[inline]
183 pub const fn zero() -> Self {
184 Self(0)
185 }
186 }
187
188 const impl From<[<$resource Diff>]> for f64 {
189 fn from(value: [<$resource Diff>]) -> Self {
190 f64::from(value.0)
191 }
192 }
193
194 impl TryFrom<$resource> for [<$resource Diff>] {
195 type Error = $crate::error::Error;
196
197 fn try_from(value: $resource) -> Result<Self> {
198 Ok(Self(value.try_into()?))
199 }
200 }
201
202 const impl PartialEq<i32> for [<$resource Diff>] {
203 fn eq(&self, other: &i32) -> bool {
204 self.0.eq(other)
205 }
206 }
207
208 const impl PartialOrd<i32> for [<$resource Diff>] {
209 fn partial_cmp(&self, other: &i32) -> Option<Ordering> {
210 self.0.partial_cmp(other)
211 }
212 }
213
214 const impl Add for [<$resource Diff>] {
215 type Output = Self;
216
217 fn add(self, rhs: Self) -> Self {
218 Self(self.0.saturating_add(rhs.0))
219 }
220 }
221
222 const impl Add<$resource> for [<$resource Diff>] {
223 type Output = Self;
224
225 fn add(self, rhs: $resource) -> Self {
226 Self(self.0.saturating_add_unsigned(rhs.0))
227 }
228 }
229
230 const impl Add<[<$resource Diff>]> for $resource {
231 type Output = Self;
232
233 fn add(self, rhs: [<$resource Diff>]) -> Self {
234 Self(self.0.saturating_add_signed(rhs.0))
235 }
236 }
237
238 const impl Add<i32> for [<$resource Diff>] {
239 type Output = Self;
240
241 fn add(self, rhs: i32) -> Self {
242 Self(self.0.saturating_add(rhs))
243 }
244 }
245
246 const impl Add<u32> for [<$resource Diff>] {
247 type Output = Self;
248
249 fn add(self, rhs: u32) -> Self {
250 Self(self.0.saturating_add_unsigned(rhs))
251 }
252 }
253
254 const impl AddAssign for [<$resource Diff>] {
255 fn add_assign(&mut self, rhs: Self) {
256 *self = *self + rhs;
257 }
258 }
259
260 const impl AddAssign<$resource> for [<$resource Diff>] {
261 fn add_assign(&mut self, rhs: $resource) {
262 *self = *self + rhs;
263 }
264 }
265
266 const impl AddAssign<[<$resource Diff>]> for $resource {
267 fn add_assign(&mut self, rhs: [<$resource Diff>]) {
268 *self = *self + rhs;
269 }
270 }
271
272 const impl AddAssign<i32> for [<$resource Diff>] {
273 fn add_assign(&mut self, rhs: i32) {
274 *self = *self + rhs;
275 }
276 }
277
278 const impl AddAssign<u32> for [<$resource Diff>] {
279 fn add_assign(&mut self, rhs: u32) {
280 *self = *self + rhs;
281 }
282 }
283
284 const impl Sub for [<$resource Diff>] {
285 type Output = Self;
286
287 fn sub(self, rhs: Self) -> Self {
288 Self(self.0.saturating_sub(rhs.0))
289 }
290 }
291
292 const impl Sub<$resource> for [<$resource Diff>] {
293 type Output = Self;
294
295 fn sub(self, rhs: $resource) -> Self {
296 Self(self.0.saturating_sub_unsigned(rhs.0))
297 }
298 }
299
300 const impl Sub<[<$resource Diff>]> for $resource {
301 type Output = Self;
302
303 fn sub(self, rhs: [<$resource Diff>]) -> Self {
304 Self(self.0.saturating_sub_signed(rhs.0))
305 }
306 }
307
308 const impl Sub<i32> for [<$resource Diff>] {
309 type Output = Self;
310
311 fn sub(self, rhs: i32) -> Self {
312 Self(self.0.saturating_sub(rhs))
313 }
314 }
315
316 const impl Sub<u32> for [<$resource Diff>] {
317 type Output = Self;
318
319 fn sub(self, rhs: u32) -> Self {
320 Self(self.0.saturating_sub_unsigned(rhs))
321 }
322 }
323
324 const impl SubAssign for [<$resource Diff>] {
325 fn sub_assign(&mut self, rhs: Self) {
326 *self = *self - rhs;
327 }
328 }
329
330 const impl SubAssign<$resource> for [<$resource Diff>] {
331 fn sub_assign(&mut self, rhs: $resource) {
332 *self = *self - rhs;
333 }
334 }
335
336 const impl SubAssign<[<$resource Diff>]> for $resource {
337 fn sub_assign(&mut self, rhs: [<$resource Diff>]) {
338 *self = *self - rhs;
339 }
340 }
341
342 const impl SubAssign<i32> for [<$resource Diff>] {
343 fn sub_assign(&mut self, rhs: i32) {
344 *self = *self - rhs;
345 }
346 }
347
348 const impl SubAssign<u32> for [<$resource Diff>] {
349 fn sub_assign(&mut self, rhs: u32) {
350 *self = *self - rhs;
351 }
352 }
353 )+
354 }
355 }
356}
357
358decl_resource_diff!(Food, Iron, Stone, Wood);