veloren_world/site/economy/
map_types.rs1use crate::{
2 assets::{self, AssetExt},
3 util::map_array::{GenericIndex, NotFound, enum_from_index, index_from_enum},
4};
5use common::{terrain::BiomeKind, trade::Good};
6use lazy_static::lazy_static;
7use serde::{Deserialize, Serialize};
8use std::{
9 convert::{TryFrom, TryInto},
10 fmt,
11 marker::PhantomData,
12 ops::{Index, IndexMut},
13};
14
15use Good::*;
16
17#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
19pub struct GoodIndex {
20 idx: usize,
21}
22
23impl GenericIndex<Good, 24> for GoodIndex {
24 const VALUES: [Good; GoodIndex::LENGTH] = [
26 Territory(BiomeKind::Grassland),
28 Territory(BiomeKind::Forest),
29 Territory(BiomeKind::Lake),
30 Territory(BiomeKind::Ocean),
31 Territory(BiomeKind::Mountain),
32 RoadSecurity,
33 Ingredients,
34 Flour,
36 Meat,
37 Wood,
38 Stone,
39 Food,
40 Tools,
41 Armor,
42 Potions,
43 Transportation,
44 Recipe,
45 Coin,
47 Terrain(BiomeKind::Lake),
49 Terrain(BiomeKind::Mountain),
50 Terrain(BiomeKind::Grassland),
51 Terrain(BiomeKind::Forest),
52 Terrain(BiomeKind::Desert),
53 Terrain(BiomeKind::Ocean),
54 ];
55
56 fn from_usize(idx: usize) -> Self { Self { idx } }
57
58 fn into_usize(self) -> usize { self.idx }
59}
60
61impl TryFrom<Good> for GoodIndex {
62 type Error = NotFound;
63
64 fn try_from(e: Good) -> Result<Self, NotFound> { index_from_enum(e) }
65}
66
67impl From<GoodIndex> for Good {
68 fn from(gi: GoodIndex) -> Good { enum_from_index(gi) }
69}
70
71impl fmt::Debug for GoodIndex {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { GoodIndex::VALUES[self.idx].fmt(f) }
73}
74
75#[derive(Copy, Clone)]
77pub struct GoodMap<V> {
78 data: [V; GoodIndex::LENGTH],
79}
80
81impl<V: Default + Copy> Default for GoodMap<V> {
82 fn default() -> Self {
83 GoodMap {
84 data: [V::default(); GoodIndex::LENGTH],
85 }
86 }
87}
88
89impl<V: Default + Copy + PartialEq + fmt::Debug> fmt::Debug for GoodMap<V> {
90 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91 f.debug_map()
92 .entries(
93 self.iter()
94 .filter(|i| *i.1 != V::default())
95 .map(|i| (Good::from(i.0), i.1)),
96 )
97 .finish()
98 }
99}
100
101impl<V> Index<GoodIndex> for GoodMap<V> {
102 type Output = V;
103
104 fn index(&self, index: GoodIndex) -> &Self::Output { &self.data[index.idx] }
105}
106
107impl<V> IndexMut<GoodIndex> for GoodMap<V> {
108 fn index_mut(&mut self, index: GoodIndex) -> &mut Self::Output { &mut self.data[index.idx] }
109}
110
111impl<V> GoodMap<V> {
112 pub fn iter(&self) -> impl Iterator<Item = (GoodIndex, &V)> + '_ {
113 self.data
114 .iter()
115 .enumerate()
116 .map(|(idx, v)| (GoodIndex { idx }, v))
117 }
118
119 pub fn iter_mut(&mut self) -> impl Iterator<Item = (GoodIndex, &mut V)> + '_ {
120 self.data
121 .iter_mut()
122 .enumerate()
123 .map(|(idx, v)| (GoodIndex { idx }, v))
124 }
125}
126
127impl<V: Copy> GoodMap<V> {
128 pub fn from_default(default: V) -> Self {
129 GoodMap {
130 data: [default; GoodIndex::LENGTH],
131 }
132 }
133
134 pub fn from_iter(i: impl Iterator<Item = (GoodIndex, V)>, default: V) -> Self {
135 let mut result = Self::from_default(default);
136 for j in i {
137 result.data[j.0.idx] = j.1;
138 }
139 result
140 }
141
142 pub fn map<U: Default + Copy>(self, mut f: impl FnMut(GoodIndex, V) -> U) -> GoodMap<U> {
143 let mut result = GoodMap::<U>::from_default(U::default());
144 for j in self.data.iter().enumerate() {
145 result.data[j.0] = f(GoodIndex::from_usize(j.0), *j.1);
146 }
147 result
148 }
149
150 pub fn from_list<'a>(i: impl IntoIterator<Item = &'a (GoodIndex, V)>, default: V) -> Self
151 where
152 V: 'a,
153 {
154 let mut result = Self::from_default(default);
155 for j in i {
156 result.data[j.0.idx] = j.1;
157 }
158 result
159 }
160}
161
162#[derive(Debug, Serialize, Deserialize)]
163struct RawProfession {
164 pub name: String,
165 pub orders: Vec<(Good, f32)>,
166 pub products: Vec<(Good, f32)>,
167}
168
169#[derive(Debug)]
170pub struct Profession {
171 pub name: String,
172 pub orders: Vec<(GoodIndex, f32)>,
173 pub products: (GoodIndex, f32),
174}
175
176#[derive(Clone, Copy, Eq, Hash, PartialEq)]
178pub struct Labor(u8, PhantomData<Profession>);
179
180pub type LaborIndex = Labor;
183
184impl LaborIndex {
185 fn from_usize(idx: usize) -> Self { Self(idx as u8, PhantomData) }
186
187 fn into_usize(self) -> usize { self.0 as usize }
188}
189
190#[derive(Clone)]
192pub struct LaborMap<V> {
193 data: Vec<V>,
194}
195
196impl<V: Default + Clone> Default for LaborMap<V> {
197 fn default() -> Self {
198 LaborMap {
199 data: std::iter::repeat_n(V::default(), *LABOR_COUNT).collect(),
200 }
201 }
202}
203
204impl<V: Default + Copy + PartialEq + fmt::Debug> fmt::Debug for LaborMap<V> {
205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 f.debug_map()
207 .entries(
208 self.iter()
209 .filter(|i| *i.1 != V::default())
210 .map(|i| (i.0, i.1)),
211 )
212 .finish()
213 }
214}
215
216impl<V> Index<LaborIndex> for LaborMap<V> {
217 type Output = V;
218
219 fn index(&self, index: LaborIndex) -> &Self::Output { &self.data[index.into_usize()] }
220}
221
222impl<V> IndexMut<LaborIndex> for LaborMap<V> {
223 fn index_mut(&mut self, index: LaborIndex) -> &mut Self::Output {
224 &mut self.data[index.into_usize()]
225 }
226}
227
228impl<V> LaborMap<V> {
229 pub fn iter(&self) -> impl Iterator<Item = (LaborIndex, &V)> + '_ {
230 self.data
231 .iter()
232 .enumerate()
233 .map(|(idx, v)| (LaborIndex::from_usize(idx), v))
234 }
235
236 pub fn iter_mut(&mut self) -> impl Iterator<Item = (LaborIndex, &mut V)> + '_ {
237 self.data
238 .iter_mut()
239 .enumerate()
240 .map(|(idx, v)| (LaborIndex::from_usize(idx), v))
241 }
242}
243
244impl<V: Copy + Default> LaborMap<V> {
245 pub fn from_default(default: V) -> Self {
246 LaborMap {
247 data: std::iter::repeat_n(default, *LABOR_COUNT).collect(),
248 }
249 }
250}
251
252impl<V: Copy + Default> LaborMap<V> {
253 pub fn from_iter(i: impl Iterator<Item = (LaborIndex, V)>, default: V) -> Self {
254 let mut result = Self::from_default(default);
255 for j in i {
256 result.data[j.0.into_usize()] = j.1;
257 }
258 result
259 }
260
261 pub fn map<U: Default + Copy>(&self, f: impl Fn(LaborIndex, &V) -> U) -> LaborMap<U> {
262 LaborMap {
263 data: self.iter().map(|i| f(i.0, i.1)).collect(),
264 }
265 }
266}
267
268#[derive(Debug, Default)]
269pub struct AreaResources {
270 pub resource_sum: GoodMap<f32>,
271 pub resource_chunks: GoodMap<f32>,
272 pub chunks: u32,
273}
274
275#[derive(Debug, Default)]
276pub struct NaturalResources {
277 pub per_area: Vec<AreaResources>,
279
280 pub chunks_per_resource: GoodMap<f32>,
282 pub average_yield_per_chunk: GoodMap<f32>,
283}
284
285#[derive(Debug, Deserialize)]
286pub struct RawProfessions(Vec<RawProfession>);
287
288impl assets::Asset for RawProfessions {
289 type Loader = assets::RonLoader;
290
291 const EXTENSION: &'static str = "ron";
292}
293
294pub fn default_professions() -> Vec<Profession> {
295 RawProfessions::load_expect("common.professions")
296 .read()
297 .0
298 .iter()
299 .map(|r| Profession {
300 name: r.name.clone(),
301 orders: r
302 .orders
303 .iter()
304 .map(|i| (i.0.try_into().unwrap_or_default(), i.1))
305 .collect(),
306 products: r
307 .products
308 .first()
309 .map(|p| (p.0.try_into().unwrap_or_default(), p.1))
310 .unwrap_or_default(),
311 })
312 .collect()
313}
314
315lazy_static! {
316 static ref LABOR: Vec<Profession> = default_professions();
317 static ref DUMMY_LABOR: Labor = Labor(
319 LABOR
320 .iter()
321 .position(|a| a.name == "_")
322 .unwrap_or(0) as u8,
323 PhantomData
324 );
325 static ref LABOR_COUNT: usize = LABOR.len()-1;
327}
328
329impl fmt::Debug for Labor {
330 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
331 if (self.0 as usize) < *LABOR_COUNT {
332 f.write_str(&LABOR[self.0 as usize].name)
333 } else {
334 f.write_str("?")
335 }
336 }
337}
338
339impl Default for Labor {
340 fn default() -> Self { *DUMMY_LABOR }
341}
342
343impl Labor {
344 pub fn list() -> impl Iterator<Item = Self> {
345 (0..LABOR.len())
346 .filter(|&i| i != (DUMMY_LABOR.0 as usize))
347 .map(|i| Self(i as u8, PhantomData))
348 }
349
350 pub fn list_full() -> impl Iterator<Item = Self> {
351 (0..LABOR.len()).map(|i| Self(i as u8, PhantomData))
352 }
353
354 pub fn is_everyone(&self) -> bool { self.0 == DUMMY_LABOR.0 }
355
356 pub fn orders_everyone() -> impl Iterator<Item = &'static (GoodIndex, f32)> {
357 LABOR
358 .get(DUMMY_LABOR.0 as usize)
359 .map_or([].iter(), |l| l.orders.iter())
360 }
361
362 pub fn orders(&self) -> impl Iterator<Item = &'static (GoodIndex, f32)> + use<> {
363 LABOR
364 .get(self.0 as usize)
365 .map_or([].iter(), |l| l.orders.iter())
366 }
367
368 pub fn products(&self) -> (GoodIndex, f32) {
369 LABOR
370 .get(self.0 as usize)
371 .map_or((GoodIndex::default(), 0.0), |l| l.products)
372 }
373}