rpfm_extensions/startpos/world/
availability.rs1use std::collections::HashSet;
15
16use rpfm_lib::error::Result;
17
18use crate::startpos::tables::StartposTables;
19use crate::startpos::world::FactionEntry;
20
21#[cfg(test)] #[path = "availability_test.rs"] mod availability_test;
22
23pub fn available_chains(tables: &StartposTables, campaign: &str, faction: &FactionEntry) -> Result<Option<HashSet<String>>> {
44 let (Ok(availabilities), Ok(sets)) = (tables.table("building_chain_availabilities"), tables.table("building_chain_availability_sets")) else { return Ok(None) };
45
46 let mut campaign_rows = vec![];
47 let mut generic_rows = vec![];
48 let mut set_ids = HashSet::new();
49 for row in availabilities.rows() {
50 let row_campaign = row.str("campaign")?;
51 if !row_campaign.is_empty() && row_campaign != campaign {
52 continue;
53 }
54
55 let (row_faction, row_subculture, row_culture) = (row.str("faction")?, row.str("sub_culture")?, row.str("culture")?);
56 let set_id = row.str("set_id")?.into_owned();
57 if row_faction.is_empty() && row_subculture.is_empty() && row_culture.is_empty() {
58 set_ids.insert(set_id);
59 continue;
60 }
61
62 let level = if row_faction == *faction.key() {
63 Some(0)
64 } else if row_faction.is_empty() && !row_subculture.is_empty() && row_subculture == *faction.subculture() {
65 Some(1)
66 } else if row_faction.is_empty() && row_subculture.is_empty() && row_culture == *faction.culture() {
67 Some(2)
68 } else {
69 None
70 };
71 if let Some(level) = level {
72 let rows = if row_campaign.is_empty() { &mut generic_rows } else { &mut campaign_rows };
73 rows.push((level, set_id));
74 }
75 }
76
77 let chosen = [campaign_rows, generic_rows].into_iter()
78 .flat_map(|rows| (0..3).map(move |level| rows.iter().filter(|(row_level, _)| *row_level == level).map(|(_, set)| set.to_owned()).collect::<Vec<_>>()))
79 .find(|level_sets| !level_sets.is_empty())
80 .unwrap_or_default();
81 set_ids.extend(chosen);
82
83 let mut chains = HashSet::new();
84 for row in sets.rows() {
85 if set_ids.contains(row.str("id")?.as_ref()) {
86 chains.insert(row.str("building_chain")?.into_owned());
87 }
88 }
89 Ok(Some(chains))
90}