1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
//! All core objects that are part of the Dwarf Fortress world

use crate::create_new::CreateNew;
use crate::fillable::{Fillable, Filler};
use df_st_derive::{Fillable, Filler};
use indexmap::IndexMap;
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use std::hash::{BuildHasher, Hash, Hasher};

pub mod artifact;
pub mod creature;
pub mod dance_form;
pub mod entity;
pub mod entity_population;
pub mod historical_era;
pub mod historical_event;
pub mod historical_event_collection;
pub mod historical_figure;
pub mod identity;
pub mod landmass;
pub mod links;
pub mod mountain_peak;
pub mod musical_form;
pub mod poetic_form;
pub mod region;
pub mod river;
pub mod site;
pub mod underground_region;
pub mod world_construction;
pub mod world_info;
pub mod written_content;

pub use artifact::*;
pub use creature::*;
pub use dance_form::*;
pub use entity::*;
pub use entity_population::*;
pub use historical_era::*;
pub use historical_event::*;
pub use historical_event_collection::*;
pub use historical_figure::*;
pub use identity::*;
pub use landmass::*;
pub use links::*;
pub use mountain_peak::*;
pub use musical_form::*;
pub use poetic_form::*;
pub use region::*;
pub use river::*;
pub use site::*;
pub use underground_region::*;
pub use world_construction::*;
pub use world_info::*;
pub use written_content::*;

#[derive(Serialize, Deserialize, Clone, Debug, Fillable, Filler, Default, PartialEq, JsonSchema)]
pub struct DFWorld {
    pub id: i32,
    pub world_info: DFWorldInfo,
    pub regions: IndexMap<u64, Region>,
    pub underground_regions: IndexMap<u64, UndergroundRegion>,
    pub artifacts: IndexMap<u64, Artifact>,
    pub sites: IndexMap<u64, Site>,
    pub world_constructions: IndexMap<u64, WorldConstruction>,
    pub entity_populations: IndexMap<u64, EntityPopulation>,
    pub historical_figures: IndexMap<u64, HistoricalFigure>,
    pub mountain_peaks: IndexMap<u64, MountainPeak>,
    pub landmasses: IndexMap<u64, Landmass>,
    pub dance_forms: IndexMap<u64, DanceForm>,
    pub musical_forms: IndexMap<u64, MusicalForm>,
    pub poetic_forms: IndexMap<u64, PoeticForm>,
    pub written_contents: IndexMap<u64, WrittenContent>,
    pub historical_eras: IndexMap<u64, HistoricalEra>,
    pub rivers: IndexMap<u64, River>,
    pub creatures: IndexMap<u64, Creature>,
    pub identities: IndexMap<u64, Identity>,
    pub entities: IndexMap<u64, Entity>,
    pub historical_events: IndexMap<u64, HistoricalEvent>,
    pub historical_event_collections: IndexMap<u64, HistoricalEventCollection>,

    pub links_he_hf: HashSet<LinkHEHF>,
}

impl DFWorld {
    /// Create a new empty world
    pub fn new() -> Self {
        Self::default()
    }

    /// Display count for all object in the world
    #[rustfmt::skip]
    pub fn list_containt_counts(&self) -> String{
        let mut result = String::new();
        let name = match &self.world_info.name {
            Some(x) => x.clone(),
            None => "".to_owned(),
        };
        let alternative_name = match &self.world_info.alternative_name {
            Some(x) => x.clone(),
            None => "".to_owned(),
        };
        result = format!("{}World: {} ({})\n", result, name, alternative_name);
        result = format!("{}{:<30}: {:>8}\n", result, "Regions", self.regions.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Underground Regions", self.underground_regions.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Sites", self.sites.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Artifacts", self.artifacts.len());
        result = format!("{}{:<30}: {:>8}\n", result, "World Constructions", self.world_constructions.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Entity Populations", self.entity_populations.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Historical Figures", self.historical_figures.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Mountain Peaks", self.mountain_peaks.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Landmasses", self.landmasses.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Dance Forms", self.dance_forms.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Musical Forms", self.musical_forms.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Poetic Forms", self.poetic_forms.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Written Contents", self.written_contents.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Historical Eras", self.historical_eras.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Rivers", self.rivers.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Creatures", self.creatures.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Identities", self.identities.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Entities", self.entities.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Historical Events", self.historical_events.len());
        result = format!("{}{:<30}: {:>8}\n", result, "Historical Event Collections", self.historical_event_collections.len());

        result
    }

    #[rustfmt::skip]
    pub fn add_missing_ids(mut self) -> Self{
        let mut buffer = "Adding missing ID's:\n".to_owned();
        self.regions = Self::add_missing_ids_list_count(self.regions, "Regions", &mut buffer);
        self.underground_regions = Self::add_missing_ids_list_count(self.underground_regions, "Underground Regions", &mut buffer);
        self.sites = Self::add_missing_ids_list_count(self.sites, "Sites", &mut buffer);
        self.artifacts = Self::add_missing_ids_list_count(self.artifacts, "Artifacts", &mut buffer);
        self.world_constructions = Self::add_missing_ids_list_count(self.world_constructions, "World Constructions", &mut buffer);
        self.entity_populations = Self::add_missing_ids_list_count(self.entity_populations, "Entity Populations", &mut buffer);
        self.historical_figures = Self::add_missing_ids_list_count(self.historical_figures, "Historical Figures", &mut buffer);
        self.mountain_peaks = Self::add_missing_ids_list_count(self.mountain_peaks, "Mountain Peaks", &mut buffer);
        self.landmasses = Self::add_missing_ids_list_count(self.landmasses, "Landmasses", &mut buffer);
        self.dance_forms = Self::add_missing_ids_list_count(self.dance_forms, "Dance Forms", &mut buffer);
        self.musical_forms = Self::add_missing_ids_list_count(self.musical_forms, "Musical Forms", &mut buffer);
        self.poetic_forms = Self::add_missing_ids_list_count(self.poetic_forms, "Poetic Forms", &mut buffer);
        self.written_contents = Self::add_missing_ids_list_count(self.written_contents, "Written Contents", &mut buffer);
        self.historical_eras = Self::add_missing_ids_list_count(self.historical_eras, "Historical Eras", &mut buffer);
        self.rivers = Self::add_missing_ids_list_count(self.rivers, "Rivers", &mut buffer);
        self.creatures = Self::add_missing_ids_list_count(self.creatures, "Creatures", &mut buffer);
        self.identities = Self::add_missing_ids_list_count(self.identities, "Identities", &mut buffer);
        self.entities = Self::add_missing_ids_list_count(self.entities, "Entities", &mut buffer);
        self.historical_events = Self::add_missing_ids_list_count(self.historical_events, "Historical Events", &mut buffer);
        self.historical_event_collections = Self::add_missing_ids_list_count(self.historical_event_collections, "Historical Event Collections", &mut buffer);
        debug!("{}", buffer);
        self
    }

    fn add_missing_ids_list_count<T: Hash + CreateNew>(
        mut list: IndexMap<u64, T>,
        label: &str,
        buffer: &mut String,
    ) -> IndexMap<u64, T> {
        let old_amount = list.len();
        list = Self::add_missing_ids_list(list);
        buffer.push_str(format!("{:<30}: {:>8}\n", label, (list.len() - old_amount)).as_str());
        list
    }

    fn add_missing_ids_list<T: Hash + CreateNew>(mut list: IndexMap<u64, T>) -> IndexMap<u64, T> {
        // Use same Hasher for both lists
        let hasher = list.hasher().clone();
        let mut new_list: IndexMap<u64, T> = IndexMap::with_hasher(hasher);
        let mut index: i32 = 0;
        // Loop until all items are copied over or index runs out of numbers
        while !list.is_empty() && index < i32::MAX {
            let index_item = T::new_by_id(index);
            // hash item
            let mut hasher_b = list.hasher().build_hasher();
            index_item.hash(&mut hasher_b);
            let hash = hasher_b.finish();
            // Get existing item
            let item = list.remove(&hash);
            match item {
                Some(item) => {
                    new_list.insert(hash, item);
                }
                None => {
                    new_list.insert(hash, index_item);
                }
            }
            index += 1;
        }
        new_list
    }

    pub fn create_reference_links(mut self) -> Self {
        self.links_he_hf = LinkHEHF::create_links(&self);
        self
    }

    pub fn empty_copy(&self) -> DFWorld {
        let mut world_copy = self.clone();
        world_copy.id = 0;
        world_copy.world_info = DFWorldInfo::default();
        world_copy.regions.clear();
        world_copy.underground_regions.clear();
        world_copy.artifacts.clear();
        world_copy.sites.clear();
        world_copy.world_constructions.clear();
        world_copy.entity_populations.clear();
        world_copy.historical_figures.clear();
        world_copy.mountain_peaks.clear();
        world_copy.landmasses.clear();
        world_copy.dance_forms.clear();
        world_copy.musical_forms.clear();
        world_copy.poetic_forms.clear();
        world_copy.written_contents.clear();
        world_copy.historical_eras.clear();
        world_copy.rivers.clear();
        world_copy.creatures.clear();
        world_copy.identities.clear();
        world_copy.entities.clear();
        world_copy.historical_events.clear();
        world_copy.historical_event_collections.clear();
        world_copy
    }
}