1use cimdecoder::CimDataset;
2use crate::Config;
3
4const PROF_EQ: &str = "http://iec.ch/TC57/ns/CIM/CoreEquipment-EU/3.0";
5const PROF_EQBD: &str = "http://iec.ch/TC57/ns/CIM/EquipmentBoundary-EU/3.0";
6const PROF_DY: &str = "http://iec.ch/TC57/ns/CIM/Dynamics-EU/1.0";
7const PROF_DL: &str = "http://iec.ch/TC57/ns/CIM/DiagramLayout-EU/3.0";
8const PROF_SC: &str = "http://iec.ch/TC57/ns/CIM/ShortCircuit-EU/3.0";
9const PROF_OP: &str = "http://iec.ch/TC57/ns/CIM/Operation-EU/3.0";
10const PROF_GL: &str = "http://iec.ch/TC57/ns/CIM/GeographicalLocation-EU/3.0";
11const PROF_SV: &str = "http://iec.ch/TC57/ns/CIM/StateVariables-EU/3.0";
12const PROF_TP: &str = "http://iec.ch/TC57/ns/CIM/Topology-EU/3.0";
13const PROF_SSH: &str = "http://iec.ch/TC57/ns/CIM/SteadyStateHypothesis-EU/3.0";
14
15fn uri_to_short_name(uri: &str) -> Option<&'static str> {
16 match uri {
17 PROF_EQ => Some("EQ"),
18 PROF_SSH => Some("SSH"),
19 PROF_TP => Some("TP"),
20 PROF_SV => Some("SV"),
21 PROF_DY => Some("DY"),
22 PROF_SC => Some("SC"),
23 PROF_DL => Some("DL"),
24 PROF_GL => Some("GL"),
25 PROF_OP => Some("OP"),
26 PROF_EQBD => Some("EQBD"),
27 _ => None,
28 }
29}
30
31fn collect_profiles_from_type(dataset: &CimDataset, type_name: &str, seen: &mut std::collections::HashSet<&'static str>) {
32 for mrid in dataset.by_type.get(type_name).into_iter().flatten() {
33 let entry = match dataset.entries.get(mrid) { Some(e) => e, None => continue };
34 let profiles: &[String] = if let Some(fm) = entry.element.as_any().downcast_ref::<cimstructs::FullModel>() {
35 &fm.base.profile
36 } else if let Some(dm) = entry.element.as_any().downcast_ref::<cimstructs::DifferenceModel>() {
37 &dm.base.profile
38 } else {
39 continue;
40 };
41 for p in profiles {
42 let p = p.trim();
43 if !p.is_empty() {
44 if let Some(short) = uri_to_short_name(p) {
45 seen.insert(short);
46 }
47 }
48 }
49 }
50}
51
52pub fn detect_config(dataset: &CimDataset) -> Config {
54 let mut seen: std::collections::HashSet<&'static str> = std::collections::HashSet::new();
55 collect_profiles_from_type(dataset, "FullModel", &mut seen);
56 collect_profiles_from_type(dataset, "DifferenceModel", &mut seen);
57
58 let mut profiles: Vec<String> = seen.iter().map(|s| s.to_string()).collect();
59 profiles.sort();
60
61 let is_solved = seen.contains("SV");
62 Config {
63 profiles,
64 solved: is_solved,
65 not_solved: !is_solved,
66 ..Config::default()
67 }
68}