use super::model::{FileResults, ShapeInfo};
use super::sparql_report::GroupReport;
use std::collections::{HashMap, HashSet};
pub fn ttl_group_label(filename: &str) -> &'static str {
if filename.contains("Equipment") {
"Equipment (EQ)"
} else if filename.contains("SteadyStateHypothesis") {
"Steady State Hypothesis (SSH)"
} else if filename.contains("Dynamics") {
"Dynamics (DY)"
} else if filename.contains("StateVariables") {
"State Variables (SV)"
} else if filename.contains("ShortCircuit") {
"Short Circuit (SC)"
} else if filename.contains("Topology") {
"Topology (TP)"
} else if filename.contains("DiagramLayout") {
"DiagramLayout (DL)"
} else if filename.contains("Operation") {
"Operation (OP)"
} else {
"Common / AllProfiles"
}
}
pub const TTL_GROUP_LABEL_ORDER: &[&str] = &[
"Equipment (EQ)",
"Steady State Hypothesis (SSH)",
"Dynamics (DY)",
"State Variables (SV)",
"Short Circuit (SC)",
"Common / AllProfiles",
"Topology (TP)",
"DiagramLayout (DL)",
"Operation (OP)",
];
fn add_name(out: &mut HashSet<String>, s: &str) {
for part in s.split('|') {
if !part.is_empty() {
out.insert(part.to_string());
}
}
}
fn collect(group: &'static str, shape: &ShapeInfo, out: &mut HashMap<&'static str, HashSet<String>>) {
for c in &shape.constraints {
if c.component == "sh:SPARQLConstraintComponent" {
add_name(out.entry(group).or_default(), &shape.name);
break;
}
}
for p in &shape.properties {
collect(group, p, out);
}
}
pub fn ttl_sparql_names(results: &[FileResults]) -> HashMap<&'static str, HashSet<String>> {
let mut out: HashMap<&'static str, HashSet<String>> = HashMap::new();
for fr in results {
let group = ttl_group_label(&fr.file_name);
for shape in &fr.shapes {
collect(group, shape, &mut out);
}
}
out
}
pub struct CoverageRow {
pub label: &'static str,
pub implemented: usize,
pub ttl_total: Option<usize>,
pub missing: Vec<String>,
}
pub fn combine_coverage(
groups: &[GroupReport],
ttl: &HashMap<&'static str, HashSet<String>>,
) -> Vec<CoverageRow> {
groups
.iter()
.map(|g| {
let implemented: HashSet<String> = g.names.iter().cloned().collect();
match ttl.get(g.label) {
None => CoverageRow {
label: g.label,
implemented: implemented.len(),
ttl_total: None,
missing: Vec::new(),
},
Some(set) => {
let mut missing: Vec<String> =
set.difference(&implemented).cloned().collect();
missing.sort();
let implemented_count = set.intersection(&implemented).count();
CoverageRow {
label: g.label,
implemented: implemented_count,
ttl_total: Some(set.len()),
missing,
}
}
}
})
.collect()
}