use crate::community::CommunityResult;
use crate::export::WeightedTriple;
use serde::Serialize;
#[derive(Debug, Clone, Serialize)]
pub struct Curriculum {
pub foundation: Vec<WeightedTriple>,
pub bridges: Vec<WeightedTriple>,
pub periphery: Vec<WeightedTriple>,
}
impl Curriculum {
pub fn total(&self) -> usize {
self.foundation.len() + self.bridges.len() + self.periphery.len()
}
pub fn ordered(&self) -> Vec<&WeightedTriple> {
self.foundation.iter()
.chain(self.bridges.iter())
.chain(self.periphery.iter())
.collect()
}
}
pub fn build_curriculum(
triples: &[WeightedTriple],
communities: &CommunityResult,
) -> Curriculum {
if triples.is_empty() {
return Curriculum {
foundation: Vec::new(),
bridges: Vec::new(),
periphery: Vec::new(),
};
}
let mut weights: Vec<f64> = triples.iter().map(|t| t.weight).collect();
weights.sort_by(|a, b| a.partial_cmp(b).unwrap());
let median = weights[weights.len() / 2];
let mut foundation = Vec::new();
let mut bridges = Vec::new();
let mut periphery = Vec::new();
for triple in triples {
let subj_community = communities.assignments.get(&triple.subject);
let obj_community = communities.assignments.get(&triple.object);
match (subj_community, obj_community) {
(Some(sc), Some(oc)) if sc != oc => {
bridges.push(triple.clone());
}
_ => {
if triple.weight > median {
foundation.push(triple.clone());
} else {
periphery.push(triple.clone());
}
}
}
}
foundation.sort_by(|a, b| b.weight.partial_cmp(&a.weight).unwrap_or(std::cmp::Ordering::Equal));
bridges.sort_by(|a, b| b.weight.partial_cmp(&a.weight).unwrap_or(std::cmp::Ordering::Equal));
periphery.sort_by(|a, b| b.weight.partial_cmp(&a.weight).unwrap_or(std::cmp::Ordering::Equal));
Curriculum {
foundation,
bridges,
periphery,
}
}