use crate::game::eu4::script::parser::{AstFile, AstStatement, AstValue};
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Geography {
pub superregions: Vec<(String, Vec<String>)>,
pub regions: Vec<(String, Vec<String>)>,
}
impl Geography {
pub fn from_map(superregion: &AstFile, region: &AstFile) -> Self {
let regions = blocks(region)
.map(|(name, items)| {
let areas = items
.iter()
.find_map(|statement| match statement {
AstStatement::Assignment {
key,
value: AstValue::Block { items, .. },
..
} if key == "areas" => Some(names(items)),
_ => None,
})
.unwrap_or_default();
(name, areas)
})
.filter(|(_, areas)| !areas.is_empty())
.collect::<Vec<_>>();
let superregions = blocks(superregion)
.map(|(name, items)| {
let members = names(items)
.into_iter()
.filter(|member| regions.iter().any(|(region, _)| region == member))
.collect::<Vec<_>>();
(name, members)
})
.filter(|(_, members)| !members.is_empty())
.collect();
Self {
superregions,
regions,
}
}
pub fn is_empty(&self) -> bool {
self.superregions.is_empty() && self.regions.is_empty()
}
}
fn blocks(file: &AstFile) -> impl Iterator<Item = (String, &[AstStatement])> {
file.statements
.iter()
.filter_map(|statement| match statement {
AstStatement::Assignment {
key,
value: AstValue::Block { items, .. },
..
} => Some((key.clone(), items.as_slice())),
_ => None,
})
}
fn names(items: &[AstStatement]) -> Vec<String> {
items
.iter()
.filter_map(|statement| match statement {
AstStatement::Item {
value: AstValue::Scalar { value, .. },
..
} => Some(value.as_text()),
_ => None,
})
.collect()
}