use heromodels::db::{Collection, Db}; use heromodels::models::grid4::{NodeGroupReputation, NodeReputation}; use heromodels_core::Model; // Helper function to print nodegroup reputation details fn print_nodegroup_reputation_details(reputation: &NodeGroupReputation) { println!("\n--- NodeGroup Reputation Details ---"); println!("ID: {}", reputation.get_id()); println!("NodeGroup ID: {}", reputation.nodegroup_id); println!("Reputation Score: {}/100", reputation.reputation); println!("Uptime: {}%", reputation.uptime); println!("Node Count: {}", reputation.nodes.len()); println!("Created At: {}", reputation.base_data.created_at); println!("Modified At: {}", reputation.base_data.modified_at); // Print individual node reputations if !reputation.nodes.is_empty() { println!(" Individual Node Reputations:"); for (i, node_rep) in reputation.nodes.iter().enumerate() { println!(" {}. Node {}: Reputation {}/100, Uptime {}%", i + 1, node_rep.node_id, node_rep.reputation, node_rep.uptime); } // Calculate average node reputation and uptime let avg_node_reputation: f64 = reputation.nodes.iter() .map(|n| n.reputation as f64) .sum::() / reputation.nodes.len() as f64; let avg_node_uptime: f64 = reputation.nodes.iter() .map(|n| n.uptime as f64) .sum::() / reputation.nodes.len() as f64; println!(" Average Node Reputation: {:.1}/100", avg_node_reputation); println!(" Average Node Uptime: {:.1}%", avg_node_uptime); } } fn main() { // Create a new DB instance in /tmp/grid4_reputation_db, and reset before every run let db = heromodels::db::hero::OurDB::new("/tmp/grid4_reputation_db", true).expect("Can create DB"); println!("Grid4 Reputation Models - Basic Usage Example"); println!("============================================"); // Create individual node reputations // High-performing nodes let node_rep1 = NodeReputation::new() .node_id(1001) .reputation(85) .uptime(99); let node_rep2 = NodeReputation::new() .node_id(1002) .reputation(92) .uptime(98); let node_rep3 = NodeReputation::new() .node_id(1003) .reputation(78) .uptime(97); // Medium-performing nodes let node_rep4 = NodeReputation::new() .node_id(2001) .reputation(65) .uptime(94); let node_rep5 = NodeReputation::new() .node_id(2002) .reputation(72) .uptime(96); // Lower-performing nodes let node_rep6 = NodeReputation::new() .node_id(3001) .reputation(45) .uptime(88); let node_rep7 = NodeReputation::new() .node_id(3002) .reputation(38) .uptime(85); // New nodes with default reputation let node_rep8 = NodeReputation::new() .node_id(4001) .reputation(50) // default .uptime(0); // just started let node_rep9 = NodeReputation::new() .node_id(4002) .reputation(50) // default .uptime(0); // just started // Create nodegroup reputations with different performance profiles // NodeGroup 1 - High-performance provider let nodegroup_rep1 = NodeGroupReputation::new() .nodegroup_id(1001) .reputation(85) // high reputation earned over time .uptime(98) // excellent uptime .add_node_reputation(node_rep1.clone()) .add_node_reputation(node_rep2.clone()) .add_node_reputation(node_rep3.clone()); // NodeGroup 2 - Medium-performance provider let nodegroup_rep2 = NodeGroupReputation::new() .nodegroup_id(1002) .reputation(68) // decent reputation .uptime(95) // good uptime .add_node_reputation(node_rep4.clone()) .add_node_reputation(node_rep5.clone()); // NodeGroup 3 - Struggling provider let nodegroup_rep3 = NodeGroupReputation::new() .nodegroup_id(1003) .reputation(42) // below average reputation .uptime(87) // poor uptime .add_node_reputation(node_rep6.clone()) .add_node_reputation(node_rep7.clone()); // NodeGroup 4 - New provider (default reputation) let nodegroup_rep4 = NodeGroupReputation::new() .nodegroup_id(1004) .reputation(50) // default starting reputation .uptime(0) // no history yet .add_node_reputation(node_rep8.clone()) .add_node_reputation(node_rep9.clone()); // Save all nodegroup reputations to database and get their assigned IDs and updated models let (rep1_id, db_rep1) = db .collection() .expect("can open reputation collection") .set(&nodegroup_rep1) .expect("can set reputation"); let (rep2_id, db_rep2) = db .collection() .expect("can open reputation collection") .set(&nodegroup_rep2) .expect("can set reputation"); let (rep3_id, db_rep3) = db .collection() .expect("can open reputation collection") .set(&nodegroup_rep3) .expect("can set reputation"); let (rep4_id, db_rep4) = db .collection() .expect("can open reputation collection") .set(&nodegroup_rep4) .expect("can set reputation"); println!("NodeGroup Reputation 1 assigned ID: {}", rep1_id); println!("NodeGroup Reputation 2 assigned ID: {}", rep2_id); println!("NodeGroup Reputation 3 assigned ID: {}", rep3_id); println!("NodeGroup Reputation 4 assigned ID: {}", rep4_id); // Print all reputation records retrieved from database println!("\n--- Reputation Records Retrieved from Database ---"); println!("\n1. High-performance provider:"); print_nodegroup_reputation_details(&db_rep1); println!("\n2. Medium-performance provider:"); print_nodegroup_reputation_details(&db_rep2); println!("\n3. Struggling provider:"); print_nodegroup_reputation_details(&db_rep3); println!("\n4. New provider:"); print_nodegroup_reputation_details(&db_rep4); // Demonstrate different ways to retrieve reputation records from the database // 1. Retrieve by nodegroup ID index println!("\n--- Retrieving Reputation by Different Methods ---"); println!("\n1. By NodeGroup ID Index (NodeGroup 1002):"); let nodegroup_reps = db .collection::() .expect("can open reputation collection") .get_by_index("nodegroup_id", &1002u32) .expect("can load reputation by nodegroup"); assert_eq!(nodegroup_reps.len(), 1); print_nodegroup_reputation_details(&nodegroup_reps[0]); // 2. Update reputation scores (simulate performance improvement) println!("\n2. Updating Reputation Scores (Performance Improvement):"); let mut improved_rep = db_rep3.clone(); improved_rep.reputation = 55; // improved from 42 improved_rep.uptime = 92; // improved from 87 // Also improve individual node reputations for node_rep in &mut improved_rep.nodes { node_rep.reputation += 10; // boost each node's reputation node_rep.uptime += 5; // improve uptime } let (_, updated_rep) = db .collection::() .expect("can open reputation collection") .set(&improved_rep) .expect("can update reputation"); println!("Updated reputation for struggling provider:"); print_nodegroup_reputation_details(&updated_rep); // 3. Add new node to existing nodegroup reputation println!("\n3. Adding New Node to Existing NodeGroup:"); let new_node_rep = NodeReputation::new() .node_id(1004) .reputation(88) .uptime(99); let mut expanded_rep = db_rep1.clone(); expanded_rep.add_node_reputation(new_node_rep); // Recalculate nodegroup reputation based on node average let total_node_rep: i32 = expanded_rep.nodes.iter().map(|n| n.reputation).sum(); expanded_rep.reputation = total_node_rep / expanded_rep.nodes.len() as i32; let (_, expanded_rep) = db .collection::() .expect("can open reputation collection") .set(&expanded_rep) .expect("can update reputation"); println!("Added new high-performing node to top provider:"); print_nodegroup_reputation_details(&expanded_rep); // Show all reputation records and calculate analytics let all_reps = db .collection::() .expect("can open reputation collection") .get_all() .expect("can load all reputations"); println!("\n--- Reputation Analytics ---"); println!("Total NodeGroup Reputations: {}", all_reps.len()); // Calculate overall statistics let avg_nodegroup_reputation: f64 = all_reps.iter() .map(|r| r.reputation as f64) .sum::() / all_reps.len() as f64; let avg_nodegroup_uptime: f64 = all_reps.iter() .filter(|r| r.uptime > 0) // exclude new providers with 0 uptime .map(|r| r.uptime as f64) .sum::() / all_reps.iter().filter(|r| r.uptime > 0).count() as f64; println!("Overall Statistics:"); println!(" Average NodeGroup Reputation: {:.1}/100", avg_nodegroup_reputation); println!(" Average NodeGroup Uptime: {:.1}%", avg_nodegroup_uptime); // Count reputation tiers let excellent_reps = all_reps.iter().filter(|r| r.reputation >= 80).count(); let good_reps = all_reps.iter().filter(|r| r.reputation >= 60 && r.reputation < 80).count(); let average_reps = all_reps.iter().filter(|r| r.reputation >= 40 && r.reputation < 60).count(); let poor_reps = all_reps.iter().filter(|r| r.reputation < 40).count(); println!("\nReputation Distribution:"); println!(" Excellent (80-100): {}", excellent_reps); println!(" Good (60-79): {}", good_reps); println!(" Average (40-59): {}", average_reps); println!(" Poor (0-39): {}", poor_reps); // Calculate total nodes and their statistics let total_nodes: usize = all_reps.iter().map(|r| r.nodes.len()).sum(); let all_node_reps: Vec = all_reps.iter() .flat_map(|r| &r.nodes) .map(|n| n.reputation) .collect(); let all_node_uptimes: Vec = all_reps.iter() .flat_map(|r| &r.nodes) .filter(|n| n.uptime > 0) .map(|n| n.uptime) .collect(); let avg_node_reputation: f64 = all_node_reps.iter().sum::() as f64 / all_node_reps.len() as f64; let avg_node_uptime: f64 = all_node_uptimes.iter().sum::() as f64 / all_node_uptimes.len() as f64; println!("\nNode-Level Statistics:"); println!(" Total Nodes: {}", total_nodes); println!(" Average Node Reputation: {:.1}/100", avg_node_reputation); println!(" Average Node Uptime: {:.1}%", avg_node_uptime); // Find best and worst performing nodegroups let best_nodegroup = all_reps.iter().max_by_key(|r| r.reputation).unwrap(); let worst_nodegroup = all_reps.iter().min_by_key(|r| r.reputation).unwrap(); println!("\nPerformance Leaders:"); println!(" Best NodeGroup: {} (Reputation: {}, Uptime: {}%)", best_nodegroup.nodegroup_id, best_nodegroup.reputation, best_nodegroup.uptime); println!(" Worst NodeGroup: {} (Reputation: {}, Uptime: {}%)", worst_nodegroup.nodegroup_id, worst_nodegroup.reputation, worst_nodegroup.uptime); // Rank nodegroups by reputation let mut ranked_nodegroups: Vec<_> = all_reps.iter().collect(); ranked_nodegroups.sort_by(|a, b| b.reputation.cmp(&a.reputation)); println!("\nNodeGroup Rankings (by Reputation):"); for (i, rep) in ranked_nodegroups.iter().enumerate() { let status = match rep.reputation { 80..=100 => "Excellent", 60..=79 => "Good", 40..=59 => "Average", _ => "Poor", }; println!(" {}. NodeGroup {}: {} ({}/100, {}% uptime)", i + 1, rep.nodegroup_id, status, rep.reputation, rep.uptime); } println!("\n--- Model Information ---"); println!("NodeGroupReputation DB Prefix: {}", NodeGroupReputation::db_prefix()); }