use heromodels::db::{Collection, Db}; use heromodels::models::grid4::{NodeGroup, PricingPolicy, SLAPolicy}; use heromodels_core::Model; // Helper function to print nodegroup details fn print_nodegroup_details(nodegroup: &NodeGroup) { println!("\n--- NodeGroup Details ---"); println!("ID: {}", nodegroup.get_id()); println!("Farmer ID: {}", nodegroup.farmerid); println!("Description: {}", nodegroup.description); println!("Secret: {}", nodegroup.secret); println!("Compute Slice Pricing (CC): {:.4}", nodegroup.compute_slice_normalized_pricing_cc); println!("Storage Slice Pricing (CC): {:.4}", nodegroup.storage_slice_normalized_pricing_cc); println!("Signature Farmer: {}", nodegroup.signature_farmer); println!("Created At: {}", nodegroup.base_data.created_at); println!("Modified At: {}", nodegroup.base_data.modified_at); // Print SLA Policy details println!(" SLA Policy:"); println!(" Uptime: {}%", nodegroup.slapolicy.sla_uptime); println!(" Bandwidth: {} Mbit/s", nodegroup.slapolicy.sla_bandwidth_mbit); println!(" Penalty: {}%", nodegroup.slapolicy.sla_penalty); // Print Pricing Policy details println!(" Pricing Policy:"); println!(" Marketplace Year Discounts: {:?}%", nodegroup.pricingpolicy.marketplace_year_discounts); } fn main() { // Create a new DB instance in /tmp/grid4_nodegroups_db, and reset before every run let db = heromodels::db::hero::OurDB::new("/tmp/grid4_nodegroups_db", true).expect("Can create DB"); println!("Grid4 NodeGroup Models - Basic Usage Example"); println!("==========================================="); // Create SLA policies let sla_policy_premium = SLAPolicy { sla_uptime: 99, sla_bandwidth_mbit: 1000, sla_penalty: 200, }; let sla_policy_standard = SLAPolicy { sla_uptime: 95, sla_bandwidth_mbit: 100, sla_penalty: 100, }; let sla_policy_basic = SLAPolicy { sla_uptime: 90, sla_bandwidth_mbit: 50, sla_penalty: 50, }; // Create pricing policies let pricing_policy_aggressive = PricingPolicy { marketplace_year_discounts: vec![40, 50, 60], }; let pricing_policy_standard = PricingPolicy { marketplace_year_discounts: vec![30, 40, 50], }; let pricing_policy_conservative = PricingPolicy { marketplace_year_discounts: vec![20, 30, 40], }; // Create nodegroups with different configurations // NodeGroup 1 - Premium hosting provider let nodegroup1 = NodeGroup::new() .farmerid(501) .secret("encrypted_boot_secret_premium_abc123".to_string()) .description("Premium hosting with 99% uptime SLA and high-speed connectivity".to_string()) .slapolicy(sla_policy_premium.clone()) .pricingpolicy(pricing_policy_aggressive.clone()) .compute_slice_normalized_pricing_cc(0.0450) .storage_slice_normalized_pricing_cc(0.0180) .signature_farmer("farmer_501_premium_signature_xyz789".to_string()); // NodeGroup 2 - Standard business provider let nodegroup2 = NodeGroup::new() .farmerid(502) .secret("encrypted_boot_secret_standard_def456".to_string()) .description("Standard business hosting with reliable performance".to_string()) .slapolicy(sla_policy_standard.clone()) .pricingpolicy(pricing_policy_standard.clone()) .compute_slice_normalized_pricing_cc(0.0350) .storage_slice_normalized_pricing_cc(0.0150) .signature_farmer("farmer_502_standard_signature_uvw012".to_string()); // NodeGroup 3 - Budget-friendly provider let nodegroup3 = NodeGroup::new() .farmerid(503) .secret("encrypted_boot_secret_budget_ghi789".to_string()) .description("Cost-effective hosting for development and testing".to_string()) .slapolicy(sla_policy_basic.clone()) .pricingpolicy(pricing_policy_conservative.clone()) .compute_slice_normalized_pricing_cc(0.0250) .storage_slice_normalized_pricing_cc(0.0120) .signature_farmer("farmer_503_budget_signature_rst345".to_string()); // NodeGroup 4 - Enterprise provider let nodegroup4 = NodeGroup::new() .farmerid(504) .secret("encrypted_boot_secret_enterprise_jkl012".to_string()) .description("Enterprise-grade infrastructure with maximum reliability".to_string()) .slapolicy(sla_policy_premium.clone()) .pricingpolicy(pricing_policy_standard.clone()) .compute_slice_normalized_pricing_cc(0.0500) .storage_slice_normalized_pricing_cc(0.0200) .signature_farmer("farmer_504_enterprise_signature_mno678".to_string()); // Save all nodegroups to database and get their assigned IDs and updated models let (nodegroup1_id, db_nodegroup1) = db .collection() .expect("can open nodegroup collection") .set(&nodegroup1) .expect("can set nodegroup"); let (nodegroup2_id, db_nodegroup2) = db .collection() .expect("can open nodegroup collection") .set(&nodegroup2) .expect("can set nodegroup"); let (nodegroup3_id, db_nodegroup3) = db .collection() .expect("can open nodegroup collection") .set(&nodegroup3) .expect("can set nodegroup"); let (nodegroup4_id, db_nodegroup4) = db .collection() .expect("can open nodegroup collection") .set(&nodegroup4) .expect("can set nodegroup"); println!("NodeGroup 1 assigned ID: {}", nodegroup1_id); println!("NodeGroup 2 assigned ID: {}", nodegroup2_id); println!("NodeGroup 3 assigned ID: {}", nodegroup3_id); println!("NodeGroup 4 assigned ID: {}", nodegroup4_id); // Print all nodegroups retrieved from database println!("\n--- NodeGroups Retrieved from Database ---"); println!("\n1. Premium hosting provider:"); print_nodegroup_details(&db_nodegroup1); println!("\n2. Standard business provider:"); print_nodegroup_details(&db_nodegroup2); println!("\n3. Budget-friendly provider:"); print_nodegroup_details(&db_nodegroup3); println!("\n4. Enterprise provider:"); print_nodegroup_details(&db_nodegroup4); // Demonstrate different ways to retrieve nodegroups from the database // 1. Retrieve by farmer ID index println!("\n--- Retrieving NodeGroups by Different Methods ---"); println!("\n1. By Farmer ID Index (Farmer 502):"); let farmer_nodegroups = db .collection::() .expect("can open nodegroup collection") .get_by_index("farmerid", &502u32) .expect("can load nodegroups by farmer"); assert_eq!(farmer_nodegroups.len(), 1); print_nodegroup_details(&farmer_nodegroups[0]); // 2. Update nodegroup pricing println!("\n2. Updating NodeGroup Pricing:"); let mut updated_nodegroup = db_nodegroup3.clone(); updated_nodegroup.compute_slice_normalized_pricing_cc = 0.0280; updated_nodegroup.storage_slice_normalized_pricing_cc = 0.0130; let (_, price_updated_nodegroup) = db .collection::() .expect("can open nodegroup collection") .set(&updated_nodegroup) .expect("can update nodegroup"); println!("Updated pricing for budget provider:"); println!(" Compute: {:.4} CC", price_updated_nodegroup.compute_slice_normalized_pricing_cc); println!(" Storage: {:.4} CC", price_updated_nodegroup.storage_slice_normalized_pricing_cc); // 3. Update SLA policy println!("\n3. Updating SLA Policy:"); let mut sla_updated_nodegroup = db_nodegroup2.clone(); sla_updated_nodegroup.slapolicy.sla_uptime = 98; sla_updated_nodegroup.slapolicy.sla_bandwidth_mbit = 500; let (_, sla_updated_nodegroup) = db .collection::() .expect("can open nodegroup collection") .set(&sla_updated_nodegroup) .expect("can update nodegroup"); println!("Updated SLA policy for standard provider:"); println!(" Uptime: {}%", sla_updated_nodegroup.slapolicy.sla_uptime); println!(" Bandwidth: {} Mbit/s", sla_updated_nodegroup.slapolicy.sla_bandwidth_mbit); // Show all nodegroups and calculate analytics let all_nodegroups = db .collection::() .expect("can open nodegroup collection") .get_all() .expect("can load all nodegroups"); println!("\n--- NodeGroup Analytics ---"); println!("Total NodeGroups: {}", all_nodegroups.len()); // Calculate pricing statistics let avg_compute_price: f64 = all_nodegroups.iter() .map(|ng| ng.compute_slice_normalized_pricing_cc) .sum::() / all_nodegroups.len() as f64; let avg_storage_price: f64 = all_nodegroups.iter() .map(|ng| ng.storage_slice_normalized_pricing_cc) .sum::() / all_nodegroups.len() as f64; let min_compute_price = all_nodegroups.iter() .map(|ng| ng.compute_slice_normalized_pricing_cc) .fold(f64::INFINITY, f64::min); let max_compute_price = all_nodegroups.iter() .map(|ng| ng.compute_slice_normalized_pricing_cc) .fold(f64::NEG_INFINITY, f64::max); println!("Pricing Statistics:"); println!(" Average Compute Price: {:.4} CC", avg_compute_price); println!(" Average Storage Price: {:.4} CC", avg_storage_price); println!(" Compute Price Range: {:.4} - {:.4} CC", min_compute_price, max_compute_price); // Calculate SLA statistics let avg_uptime: f64 = all_nodegroups.iter() .map(|ng| ng.slapolicy.sla_uptime as f64) .sum::() / all_nodegroups.len() as f64; let avg_bandwidth: f64 = all_nodegroups.iter() .map(|ng| ng.slapolicy.sla_bandwidth_mbit as f64) .sum::() / all_nodegroups.len() as f64; let avg_penalty: f64 = all_nodegroups.iter() .map(|ng| ng.slapolicy.sla_penalty as f64) .sum::() / all_nodegroups.len() as f64; println!("\nSLA Statistics:"); println!(" Average Uptime Guarantee: {:.1}%", avg_uptime); println!(" Average Bandwidth Guarantee: {:.0} Mbit/s", avg_bandwidth); println!(" Average Penalty Rate: {:.0}%", avg_penalty); // Count farmers let unique_farmers: std::collections::HashSet<_> = all_nodegroups.iter() .map(|ng| ng.farmerid) .collect(); println!("\nFarmer Statistics:"); println!(" Unique Farmers: {}", unique_farmers.len()); println!(" NodeGroups per Farmer: {:.1}", all_nodegroups.len() as f64 / unique_farmers.len() as f64); // Analyze discount policies let total_discount_tiers: usize = all_nodegroups.iter() .map(|ng| ng.pricingpolicy.marketplace_year_discounts.len()) .sum(); let avg_discount_tiers: f64 = total_discount_tiers as f64 / all_nodegroups.len() as f64; println!("\nDiscount Policy Statistics:"); println!(" Average Discount Tiers: {:.1}", avg_discount_tiers); // Find best value providers (high SLA, low price) println!("\n--- Provider Rankings ---"); let mut providers_with_scores: Vec<_> = all_nodegroups.iter() .map(|ng| { let value_score = (ng.slapolicy.sla_uptime as f64) / ng.compute_slice_normalized_pricing_cc; (ng, value_score) }) .collect(); providers_with_scores.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap()); println!("Best Value Providers (Uptime/Price ratio):"); for (i, (ng, score)) in providers_with_scores.iter().enumerate() { println!(" {}. Farmer {}: {:.0} ({}% uptime, {:.4} CC)", i + 1, ng.farmerid, score, ng.slapolicy.sla_uptime, ng.compute_slice_normalized_pricing_cc); } println!("\n--- Model Information ---"); println!("NodeGroup DB Prefix: {}", NodeGroup::db_prefix()); }