update grid4 & heroledger models

This commit is contained in:
Timur Gordon
2025-09-16 14:18:08 +02:00
parent cb1fb0f0ec
commit 53e9a2d4f0
31 changed files with 3216 additions and 399 deletions

View File

@@ -0,0 +1,311 @@
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());
}