capability_skeleton/
tree_level_skipping_measurer.rs

1// ---------------- [ File: capability-skeleton/src/tree_level_skipping_measurer.rs ]
2crate::ix!();
3
4impl TreeLevelSkippingMeasurer for Skeleton {
5    fn measure_tree_level_skipping(&self) -> HashMap<u8, TreeLevelSkippingStats> {
6        let level_map = build_node_level_map(self);
7
8        #[derive(Default)]
9        struct TempSkipStats {
10            node_count: u64,
11            leaf_count: u64,
12        }
13        let mut level_data = HashMap::<u8, TempSkipStats>::new();
14
15        for node in self.nodes() {
16            if let Some(&lvl) = level_map.get(&node.id()) {
17                let entry = level_data.entry(lvl).or_insert_with(TempSkipStats::default);
18                entry.node_count += 1;
19                if node.child_ids().is_empty() {
20                    entry.leaf_count += 1;
21                }
22            }
23        }
24
25        let mut result = HashMap::new();
26        for (lvl, tmp) in level_data {
27            let stats = TreeLevelSkippingStatsBuilder::default()
28                .level(lvl)
29                .total_node_count(tmp.node_count)
30                .total_leaf_count(tmp.leaf_count)
31                .build()
32                .unwrap();
33            result.insert(lvl, stats);
34        }
35        result
36    }
37}
38
39#[cfg(test)]
40mod skeleton_level_skipping_measurer_assessment {
41    use super::*;
42
43    #[traced_test]
44    fn check_level_skipping_linear() {
45        // 0->1->2 => BFS => level0=>0, level1=>1, level2=>2
46        let n0 = SkeletonNodeBuilder::default()
47            .id(0u16)
48            .child_ids(vec![1u16])
49            .name("root")
50            .original_key("root")
51            .build(NodeKind::Dispatch)
52            .unwrap();
53        let n1 = SkeletonNodeBuilder::default()
54            .id(1u16)
55            .child_ids(vec![2u16])
56            .name("child")
57            .original_key("child")
58            .build(NodeKind::Dispatch)
59            .unwrap();
60        let n2 = SkeletonNodeBuilder::default()
61            .id(2u16)
62            .name("grandchild")
63            .original_key("grandchild")
64            .build(NodeKind::LeafHolder)
65            .unwrap();
66
67        let skel = SkeletonBuilder::default()
68            .nodes(vec![n0, n1, n2])
69            .root_id(Some(0u16))
70            .build()
71            .unwrap();
72
73        let skip_stats = skel.measure_tree_level_skipping();
74
75        // level0 => node_count=1, leaf_count=0
76        // level1 => node_count=1, leaf_count=0
77        // level2 => node_count=1, leaf_count=1
78        let lv0 = skip_stats.get(&0).unwrap();
79        assert_eq!(*lv0.total_node_count(), 1);
80        assert_eq!(*lv0.total_leaf_count(), 0);
81
82        let lv1 = skip_stats.get(&1).unwrap();
83        assert_eq!(*lv1.total_node_count(), 1);
84        assert_eq!(*lv1.total_leaf_count(), 0);
85
86        let lv2 = skip_stats.get(&2).unwrap();
87        assert_eq!(*lv2.total_node_count(), 1);
88        assert_eq!(*lv2.total_leaf_count(), 1);
89    }
90}