capability_skeleton/
tree_level_specific_measurer.rs

1// ---------------- [ File: capability-skeleton/src/tree_level_specific_measurer.rs ]
2crate::ix!();
3
4impl TreeLevelSpecificMeasurer for Skeleton {
5    fn measure_tree_level_stats(&self) -> HashMap<u8, TreeLevelAggregate> {
6        let level_map = build_node_level_map(self);
7
8        #[derive(Default)]
9        struct TempLevelStats {
10            node_count: u64,
11            child_count: u64,
12            leaf_count: u64,
13        }
14        let mut accum = HashMap::<u8, TempLevelStats>::new();
15
16        for node in self.nodes() {
17            if let Some(&lvl) = level_map.get(&node.id()) {
18                let entry = accum.entry(lvl).or_insert_with(TempLevelStats::default);
19                entry.node_count += 1;
20                entry.child_count += node.child_ids().len() as u64;
21                if node.child_ids().is_empty() {
22                    entry.leaf_count += node.leaf_count() as u64;
23                }
24            }
25        }
26
27        let mut result = HashMap::new();
28        for (lvl, tmp) in accum {
29            let built = TreeLevelAggregateBuilder::default()
30                .total_node_count(tmp.node_count)
31                .total_child_count(tmp.child_count)
32                .total_leaf_count(tmp.leaf_count)
33                .build()
34                .unwrap();
35            result.insert(lvl, built);
36        }
37        result
38    }
39}
40
41#[cfg(test)]
42mod skeleton_level_specific_measurer_assessment {
43    use super::*;
44
45    #[traced_test]
46    fn check_level_stats_with_branching() {
47        // root->(childA, childB), childA->(childC), childB->leaf_count=2, childC=3
48        let root = SkeletonNodeBuilder::default()
49            .id(0_u16)
50            .child_ids(vec![1,2])
51            .name("root")
52            .original_key("root")
53            .build(NodeKind::Dispatch)
54            .unwrap();
55        let child_a = SkeletonNodeBuilder::default()
56            .id(1_u16)
57            .child_ids(vec![3])
58            .name("childA")
59            .original_key("childA")
60            .build(NodeKind::Dispatch)
61            .unwrap();
62        let child_b = SkeletonNodeBuilder::default()
63            .id(2_u16)
64            .leaf_count(2_u16)
65            .name("childB")
66            .original_key("childB")
67            .build(NodeKind::LeafHolder)
68            .unwrap();
69        let child_c = SkeletonNodeBuilder::default()
70            .id(3_u16)
71            .leaf_count(3_u16)
72            .name("childC")
73            .original_key("childC")
74            .build(NodeKind::LeafHolder)
75            .unwrap();
76
77        let skel = SkeletonBuilder::default()
78            .nodes(vec![root, child_a, child_b, child_c])
79            .root_id(Some(0))
80            .build()
81            .unwrap();
82
83        let level_stats = skel.measure_tree_level_stats();
84
85        // level0 => node_count=1, child_count=2, leaf_count=0
86        // level1 => node_count=2 => (childA has 1 child, childB=leaf), leaf_count=2
87        // level2 => node_count=1 => childC => leaf_count=3
88
89        let agg0 = level_stats.get(&0).unwrap();
90        assert_eq!(*agg0.total_node_count(), 1);
91        assert_eq!(*agg0.total_child_count(), 2);
92        assert_eq!(*agg0.total_leaf_count(), 0);
93
94        let agg1 = level_stats.get(&1).unwrap();
95        assert_eq!(*agg1.total_node_count(), 2);
96        assert_eq!(*agg1.total_child_count(), 1);  // childA->(3), childB->(none)
97        assert_eq!(*agg1.total_leaf_count(), 2);
98
99        let agg2 = level_stats.get(&2).unwrap();
100        assert_eq!(*agg2.total_node_count(), 1);
101        assert_eq!(*agg2.total_child_count(), 0);
102        assert_eq!(*agg2.total_leaf_count(), 3);
103    }
104
105    #[traced_test]
106    fn check_level_stats_in_linear_chain() {
107        // 0->1->2 => BFS => level0=>0, level1=>1, level2=>2
108        // node(2) => leaf_count=4
109        let n0 = SkeletonNodeBuilder::default()
110            .id(0u16)
111            .child_ids(vec![1u16])
112            .name("root")
113            .original_key("root")
114            .build(NodeKind::Dispatch)
115            .unwrap();
116        let n1 = SkeletonNodeBuilder::default()
117            .id(1u16)
118            .child_ids(vec![2u16])
119            .name("child")
120            .original_key("child")
121            .build(NodeKind::Dispatch)
122            .unwrap();
123        let n2 = SkeletonNodeBuilder::default()
124            .id(2u16)
125            .leaf_count(4u16)
126            .name("grandchild")
127            .original_key("grandchild")
128            .build(NodeKind::LeafHolder)
129            .unwrap();
130
131        let skel = SkeletonBuilder::default()
132            .nodes(vec![n0, n1, n2])
133            .root_id(Some(0u16))
134            .build()
135            .unwrap();
136
137        let level_stats = skel.measure_tree_level_stats();
138
139        // level0 => node_count=1, child_count=1, leaf_count=0
140        // level1 => node_count=1, child_count=1, leaf_count=0
141        // level2 => node_count=1, child_count=0, leaf_count=4
142        let agg0 = level_stats.get(&0).unwrap();
143        assert_eq!(*agg0.total_node_count(), 1);
144        assert_eq!(*agg0.total_child_count(), 1);
145        assert_eq!(*agg0.total_leaf_count(), 0);
146
147        let agg1 = level_stats.get(&1).unwrap();
148        assert_eq!(*agg1.total_node_count(), 1);
149        assert_eq!(*agg1.total_child_count(), 1);
150        assert_eq!(*agg1.total_leaf_count(), 0);
151
152        let agg2 = level_stats.get(&2).unwrap();
153        assert_eq!(*agg2.total_node_count(), 1);
154        assert_eq!(*agg2.total_child_count(), 0);
155        assert_eq!(*agg2.total_leaf_count(), 4);
156    }
157}