312 lines
12 KiB
Rust
312 lines
12 KiB
Rust
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::<f64>() / reputation.nodes.len() as f64;
|
|
let avg_node_uptime: f64 = reputation.nodes.iter()
|
|
.map(|n| n.uptime as f64)
|
|
.sum::<f64>() / 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::<NodeGroupReputation>()
|
|
.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::<NodeGroupReputation>()
|
|
.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::<NodeGroupReputation>()
|
|
.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::<NodeGroupReputation>()
|
|
.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::<f64>() / 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::<f64>() / 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<i32> = all_reps.iter()
|
|
.flat_map(|r| &r.nodes)
|
|
.map(|n| n.reputation)
|
|
.collect();
|
|
let all_node_uptimes: Vec<i32> = 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::<i32>() as f64 / all_node_reps.len() as f64;
|
|
let avg_node_uptime: f64 = all_node_uptimes.iter().sum::<i32>() 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());
|
|
}
|