tiger_lib/vic3/data/
strategic_regions.rs

1use crate::block::Block;
2use crate::db::{Db, DbKind};
3use crate::everything::Everything;
4use crate::game::GameFlags;
5use crate::helpers::TigerHashMap;
6use crate::item::{Item, ItemLoader};
7use crate::report::{ErrorKey, err};
8use crate::token::Token;
9use crate::validate::validate_possibly_named_color;
10use crate::validator::Validator;
11
12#[derive(Clone, Debug)]
13pub struct StrategicRegion {}
14
15inventory::submit! {
16    ItemLoader::Normal(GameFlags::Vic3, Item::StrategicRegion, StrategicRegion::add)
17}
18
19impl StrategicRegion {
20    pub fn add(db: &mut Db, key: Token, block: Block) {
21        db.add(Item::StrategicRegion, key, block, Box::new(Self {}));
22    }
23
24    pub fn crosscheck(data: &Everything) {
25        // Each state must be part of one and only one stategic region.
26        let mut seen = TigerHashMap::default();
27        for (key, block) in data.database.iter_key_block(Item::StrategicRegion) {
28            if let Some(vec) = block.get_field_list("states") {
29                for token in vec {
30                    if let Some(&other) = seen.get(token.as_str()) {
31                        let msg =
32                            format!("state {token} is part of more than one strategic region");
33                        err(ErrorKey::Conflict)
34                            .strong()
35                            .msg(msg)
36                            .loc(key)
37                            .loc_msg(other, "the other one")
38                            .push();
39                    } else {
40                        seen.insert(token.to_string(), key);
41                    }
42                }
43            }
44        }
45        for key in data.database.iter_keys(Item::StateRegion) {
46            if !seen.contains_key(key.as_str()) {
47                let msg = format!("state {key} is not part of any strategic region");
48                err(ErrorKey::Validation).strong().msg(msg).loc(key).push();
49            }
50        }
51    }
52}
53
54impl DbKind for StrategicRegion {
55    fn validate(&self, key: &Token, block: &Block, data: &Everything) {
56        let mut vd = Validator::new(block, data);
57
58        data.verify_exists(Item::Localization, key);
59
60        // TODO capital_province and map_color are required... but not for sea regions
61        // TODO check that capital province is in region
62        vd.field_item("capital_province", Item::Province);
63        vd.field_validated("map_color", validate_possibly_named_color);
64        vd.field_list_items("states", Item::StateRegion);
65        vd.field_value("graphical_culture"); // TODO
66    }
67}