fix(simulation): replace HashMap/HashSet with BTreeMap/BTreeSet in generate_corporations

Project Clippy config disallows std::collections::HashMap and HashSet.
Replaced all usages with BTreeMap/BTreeSet. Also fixed:
- Unnecessary if-let on iterator rows (use flatten() instead)
- contains_key + insert on BTreeMap (use entry().or_insert_with())

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-07 22:44:23 +02:00
co-authored by Claude Sonnet 4.6
parent b19bfb3239
commit 822fe488d6
+48 -74
View File
@@ -17,7 +17,7 @@
//! cargo run --bin generate_corporations -- --seed 42 --min-corps 5000 //! cargo run --bin generate_corporations -- --seed 42 --min-corps 5000
//! ``` //! ```
use std::collections::{BTreeMap, HashMap, HashSet}; use std::collections::{BTreeMap, BTreeSet};
use std::path::PathBuf; use std::path::PathBuf;
use std::process; use std::process;
@@ -246,11 +246,7 @@ fn load_locations(conn: &Connection) -> Vec<Location> {
}) })
}) })
.unwrap(); .unwrap();
for row in body_rows { locations.extend(body_rows.flatten());
if let Ok(loc) = row {
locations.push(loc);
}
}
// Stations with population // Stations with population
let mut stmt = conn let mut stmt = conn
@@ -275,11 +271,7 @@ fn load_locations(conn: &Connection) -> Vec<Location> {
}) })
}) })
.unwrap(); .unwrap();
for row in station_rows { locations.extend(station_rows.flatten());
if let Ok(loc) = row {
locations.push(loc);
}
}
locations locations
} }
@@ -305,7 +297,7 @@ fn load_existing_corps(conn: &Connection) -> Vec<ExistingCorp> {
.collect() .collect()
} }
fn load_commodity_ids(conn: &Connection) -> HashSet<String> { fn load_commodity_ids(conn: &Connection) -> BTreeSet<String> {
let mut stmt = conn let mut stmt = conn
.prepare("SELECT commodity_id FROM commodities") .prepare("SELECT commodity_id FROM commodities")
.unwrap(); .unwrap();
@@ -469,7 +461,7 @@ fn assign_brands(
} }
// Pick 1-4 brands weighted by relevance to the lore archetype's commodities // Pick 1-4 brands weighted by relevance to the lore archetype's commodities
let all_commodities: HashSet<&str> = lore_arch let all_commodities: BTreeSet<&str> = lore_arch
.primary_commodities .primary_commodities
.iter() .iter()
.chain(lore_arch.secondary_commodities.iter()) .chain(lore_arch.secondary_commodities.iter())
@@ -530,9 +522,9 @@ fn make_corp_id(name: &str) -> String {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
struct CoverageReport { struct CoverageReport {
commodity_coverage: HashMap<String, usize>, commodity_coverage: BTreeMap<String, usize>,
uncovered_commodities: Vec<String>, uncovered_commodities: Vec<String>,
system_coverage: HashMap<String, usize>, system_coverage: BTreeMap<String, usize>,
uncovered_systems: Vec<String>, uncovered_systems: Vec<String>,
total_generated: usize, total_generated: usize,
} }
@@ -540,17 +532,17 @@ struct CoverageReport {
fn validate_coverage( fn validate_coverage(
generated: &BTreeMap<String, GeneratedCorp>, generated: &BTreeMap<String, GeneratedCorp>,
lore_archetypes: &BTreeMap<String, LoreArchetype>, lore_archetypes: &BTreeMap<String, LoreArchetype>,
commodity_ids: &HashSet<String>, commodity_ids: &BTreeSet<String>,
conn: &Connection, conn: &Connection,
) -> CoverageReport { ) -> CoverageReport {
// Track which commodities have at least one producer // Track which commodities have at least one producer
let mut commodity_coverage: HashMap<String, usize> = HashMap::new(); let mut commodity_coverage: BTreeMap<String, usize> = BTreeMap::new();
for cid in commodity_ids { for cid in commodity_ids {
commodity_coverage.insert(cid.clone(), 0); commodity_coverage.insert(cid.clone(), 0);
} }
// Track system presence // Track system presence
let mut system_coverage: HashMap<String, usize> = HashMap::new(); let mut system_coverage: BTreeMap<String, usize> = BTreeMap::new();
for corp in generated.values() { for corp in generated.values() {
// Count commodity coverage from lore archetype // Count commodity coverage from lore archetype
@@ -593,22 +585,19 @@ fn validate_coverage(
// Also check body-level population since system_economy only has 10 systems > 100K // Also check body-level population since system_economy only has 10 systems > 100K
// but 146 bodies > 100K // but 146 bodies > 100K
let mut body_systems: HashSet<String> = HashSet::new();
let mut stmt2 = conn let mut stmt2 = conn
.prepare( .prepare(
"SELECT DISTINCT system_id FROM bodies "SELECT DISTINCT system_id FROM bodies
WHERE inhabited = 1 AND population > 100000", WHERE inhabited = 1 AND population > 100000",
) )
.unwrap(); .unwrap();
for row in stmt2 let body_systems: BTreeSet<String> = stmt2
.query_map([], |row| row.get::<_, String>(0)) .query_map([], |row| row.get::<_, String>(0))
.unwrap() .unwrap()
.filter_map(|r| r.ok()) .filter_map(|r| r.ok())
{ .collect();
body_systems.insert(row);
}
let mut all_high_pop: HashSet<String> = high_pop_systems.into_iter().collect(); let mut all_high_pop: BTreeSet<String> = high_pop_systems.into_iter().collect();
all_high_pop.extend(body_systems); all_high_pop.extend(body_systems);
let uncovered_systems: Vec<String> = all_high_pop let uncovered_systems: Vec<String> = all_high_pop
@@ -634,7 +623,7 @@ fn validate_coverage(
fn fill_coverage_gaps( fn fill_coverage_gaps(
generated: &mut BTreeMap<String, GeneratedCorp>, generated: &mut BTreeMap<String, GeneratedCorp>,
lore_archetypes: &BTreeMap<String, LoreArchetype>, lore_archetypes: &BTreeMap<String, LoreArchetype>,
commodity_ids: &HashSet<String>, commodity_ids: &BTreeSet<String>,
conn: &Connection, conn: &Connection,
rng: &mut ChaCha8Rng, rng: &mut ChaCha8Rng,
) { ) {
@@ -679,21 +668,16 @@ fn fill_coverage_gaps(
let name = names::generate_name(rng, &sector, &lore.category); let name = names::generate_name(rng, &sector, &lore.category);
let corp_id = make_corp_id(&name); let corp_id = make_corp_id(&name);
if !generated.contains_key(&corp_id) { generated.entry(corp_id).or_insert_with(|| GeneratedCorp {
generated.insert( proper_name: name,
corp_id, lore_archetype: lore_id.to_string(),
GeneratedCorp { behavioral_archetype: behavioral,
proper_name: name, location_id: loc_id,
lore_archetype: lore_id.to_string(), location_type: loc_type,
behavioral_archetype: behavioral, system_id: sys_id.clone(),
location_id: loc_id, geographic_sector: sector,
location_type: loc_type, brands: vec![],
system_id: sys_id.clone(), });
geographic_sector: sector,
brands: vec![],
},
);
}
} }
} }
@@ -757,41 +741,31 @@ fn fill_coverage_gaps(
for _ in current_count..3 { for _ in current_count..3 {
let n = names::generate_name(rng, sector, &lore.category); let n = names::generate_name(rng, sector, &lore.category);
let cid = make_corp_id(&n); let cid = make_corp_id(&n);
if !generated.contains_key(&cid) { generated.entry(cid).or_insert_with(|| GeneratedCorp {
generated.insert( proper_name: n,
cid, lore_archetype: arch_id.to_string(),
GeneratedCorp { behavioral_archetype: pick_behavioral_archetype(
proper_name: n, rng,
lore_archetype: arch_id.to_string(), &lore.behavioral_affinity,
behavioral_archetype: pick_behavioral_archetype( ),
rng, location_id: loc_id.clone(),
&lore.behavioral_affinity, location_type: "body".to_string(),
), system_id: sys_id.clone(),
location_id: loc_id.clone(), geographic_sector: sector.to_string(),
location_type: "body".to_string(), brands: vec![],
system_id: sys_id.clone(), });
geographic_sector: sector.to_string(),
brands: vec![],
},
);
}
} }
if !generated.contains_key(&corp_id) { generated.entry(corp_id).or_insert_with(|| GeneratedCorp {
generated.insert( proper_name: name,
corp_id, lore_archetype: arch_id.to_string(),
GeneratedCorp { behavioral_archetype: behavioral,
proper_name: name, location_id: loc_id,
lore_archetype: arch_id.to_string(), location_type: "body".to_string(),
behavioral_archetype: behavioral, system_id: sys_id,
location_id: loc_id, geographic_sector: sector.to_string(),
location_type: "body".to_string(), brands: vec![],
system_id: sys_id, });
geographic_sector: sector.to_string(),
brands: vec![],
},
);
}
} }
} }
} }
@@ -983,7 +957,7 @@ fn main() {
report.system_coverage.len() report.system_coverage.len()
); );
let mut by_sector: HashMap<String, usize> = HashMap::new(); let mut by_sector: BTreeMap<String, usize> = BTreeMap::new();
for corp in generated.values() { for corp in generated.values() {
*by_sector.entry(corp.geographic_sector.clone()).or_insert(0) += 1; *by_sector.entry(corp.geographic_sector.clone()).or_insert(0) += 1;
} }