capability-skeleton 0.1.0

A Rust library for managing and building complex hierarchical tree structures such as skill trees. Supports serialization, error handling, and deep tree metrics.
Documentation
// ---------------- [ File: capability-skeleton/src/tree_level_skipping_measurer.rs ]
crate::ix!();

impl TreeLevelSkippingMeasurer for Skeleton {
    fn measure_tree_level_skipping(&self) -> HashMap<u8, TreeLevelSkippingStats> {
        let level_map = build_node_level_map(self);

        #[derive(Default)]
        struct TempSkipStats {
            node_count: u64,
            leaf_count: u64,
        }
        let mut level_data = HashMap::<u8, TempSkipStats>::new();

        for node in self.nodes() {
            if let Some(&lvl) = level_map.get(&node.id()) {
                let entry = level_data.entry(lvl).or_insert_with(TempSkipStats::default);
                entry.node_count += 1;
                if node.child_ids().is_empty() {
                    entry.leaf_count += 1;
                }
            }
        }

        let mut result = HashMap::new();
        for (lvl, tmp) in level_data {
            let stats = TreeLevelSkippingStatsBuilder::default()
                .level(lvl)
                .total_node_count(tmp.node_count)
                .total_leaf_count(tmp.leaf_count)
                .build()
                .unwrap();
            result.insert(lvl, stats);
        }
        result
    }
}

#[cfg(test)]
mod skeleton_level_skipping_measurer_assessment {
    use super::*;

    #[traced_test]
    fn check_level_skipping_linear() {
        // 0->1->2 => BFS => level0=>0, level1=>1, level2=>2
        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)
            .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 skip_stats = skel.measure_tree_level_skipping();

        // level0 => node_count=1, leaf_count=0
        // level1 => node_count=1, leaf_count=0
        // level2 => node_count=1, leaf_count=1
        let lv0 = skip_stats.get(&0).unwrap();
        assert_eq!(*lv0.total_node_count(), 1);
        assert_eq!(*lv0.total_leaf_count(), 0);

        let lv1 = skip_stats.get(&1).unwrap();
        assert_eq!(*lv1.total_node_count(), 1);
        assert_eq!(*lv1.total_leaf_count(), 0);

        let lv2 = skip_stats.get(&2).unwrap();
        assert_eq!(*lv2.total_node_count(), 1);
        assert_eq!(*lv2.total_leaf_count(), 1);
    }
}