crate::ix!();
impl TreeLevelSpecificMeasurer for Skeleton {
fn measure_tree_level_stats(&self) -> HashMap<u8, TreeLevelAggregate> {
let level_map = build_node_level_map(self);
#[derive(Default)]
struct TempLevelStats {
node_count: u64,
child_count: u64,
leaf_count: u64,
}
let mut accum = HashMap::<u8, TempLevelStats>::new();
for node in self.nodes() {
if let Some(&lvl) = level_map.get(&node.id()) {
let entry = accum.entry(lvl).or_insert_with(TempLevelStats::default);
entry.node_count += 1;
entry.child_count += node.child_ids().len() as u64;
if node.child_ids().is_empty() {
entry.leaf_count += node.leaf_count() as u64;
}
}
}
let mut result = HashMap::new();
for (lvl, tmp) in accum {
let built = TreeLevelAggregateBuilder::default()
.total_node_count(tmp.node_count)
.total_child_count(tmp.child_count)
.total_leaf_count(tmp.leaf_count)
.build()
.unwrap();
result.insert(lvl, built);
}
result
}
}
#[cfg(test)]
mod skeleton_level_specific_measurer_assessment {
use super::*;
#[traced_test]
fn check_level_stats_with_branching() {
let root = SkeletonNodeBuilder::default()
.id(0_u16)
.child_ids(vec![1,2])
.name("root")
.original_key("root")
.build(NodeKind::Dispatch)
.unwrap();
let child_a = SkeletonNodeBuilder::default()
.id(1_u16)
.child_ids(vec![3])
.name("childA")
.original_key("childA")
.build(NodeKind::Dispatch)
.unwrap();
let child_b = SkeletonNodeBuilder::default()
.id(2_u16)
.leaf_count(2_u16)
.name("childB")
.original_key("childB")
.build(NodeKind::LeafHolder)
.unwrap();
let child_c = SkeletonNodeBuilder::default()
.id(3_u16)
.leaf_count(3_u16)
.name("childC")
.original_key("childC")
.build(NodeKind::LeafHolder)
.unwrap();
let skel = SkeletonBuilder::default()
.nodes(vec![root, child_a, child_b, child_c])
.root_id(Some(0))
.build()
.unwrap();
let level_stats = skel.measure_tree_level_stats();
let agg0 = level_stats.get(&0).unwrap();
assert_eq!(*agg0.total_node_count(), 1);
assert_eq!(*agg0.total_child_count(), 2);
assert_eq!(*agg0.total_leaf_count(), 0);
let agg1 = level_stats.get(&1).unwrap();
assert_eq!(*agg1.total_node_count(), 2);
assert_eq!(*agg1.total_child_count(), 1); assert_eq!(*agg1.total_leaf_count(), 2);
let agg2 = level_stats.get(&2).unwrap();
assert_eq!(*agg2.total_node_count(), 1);
assert_eq!(*agg2.total_child_count(), 0);
assert_eq!(*agg2.total_leaf_count(), 3);
}
#[traced_test]
fn check_level_stats_in_linear_chain() {
let n0 = SkeletonNodeBuilder::default()
.id(0u16)
.child_ids(vec![1u16])
.name("root")
.original_key("root")
.build(NodeKind::Dispatch)
.unwrap();
let n1 = SkeletonNodeBuilder::default()
.id(1u16)
.child_ids(vec![2u16])
.name("child")
.original_key("child")
.build(NodeKind::Dispatch)
.unwrap();
let n2 = SkeletonNodeBuilder::default()
.id(2u16)
.leaf_count(4u16)
.name("grandchild")
.original_key("grandchild")
.build(NodeKind::LeafHolder)
.unwrap();
let skel = SkeletonBuilder::default()
.nodes(vec![n0, n1, n2])
.root_id(Some(0u16))
.build()
.unwrap();
let level_stats = skel.measure_tree_level_stats();
let agg0 = level_stats.get(&0).unwrap();
assert_eq!(*agg0.total_node_count(), 1);
assert_eq!(*agg0.total_child_count(), 1);
assert_eq!(*agg0.total_leaf_count(), 0);
let agg1 = level_stats.get(&1).unwrap();
assert_eq!(*agg1.total_node_count(), 1);
assert_eq!(*agg1.total_child_count(), 1);
assert_eq!(*agg1.total_leaf_count(), 0);
let agg2 = level_stats.get(&2).unwrap();
assert_eq!(*agg2.total_node_count(), 1);
assert_eq!(*agg2.total_child_count(), 0);
assert_eq!(*agg2.total_leaf_count(), 4);
}
}