1use crate::error::Result;
4use crate::resources::{ResourceType, ResourceAmount, CapabilityLevel};
5use crate::types::{SystemProfile, WorkloadRequirements};
6use serde::{Deserialize, Serialize};
7use std::time::{Duration, Instant};
8
9pub struct BenchmarkRunner {
11 timeout: Duration,
12 #[allow(dead_code)]
13 iterations: u32,
14}
15
16impl BenchmarkRunner {
17 pub fn new(timeout: Duration, iterations: u32) -> Self {
19 Self { timeout, iterations }
20 }
21
22 pub fn run_cpu_benchmark(&self) -> Result<BenchmarkResult> {
24 let start = Instant::now();
25 let mut operations = 0u64;
26
27 while start.elapsed() < self.timeout {
28 for _ in 0..10000 {
30 operations += 1;
31 let _ = (operations as f64).sqrt();
32 }
33 }
34
35 Ok(BenchmarkResult {
36 benchmark_type: BenchmarkType::CPU,
37 duration: start.elapsed(),
38 operations,
39 score: self.calculate_cpu_score(operations, start.elapsed()),
40 })
41 }
42
43 pub fn run_memory_benchmark(&self) -> Result<BenchmarkResult> {
45 let start = Instant::now();
46 let mut operations = 0u64;
47 let mut data = vec![0u8; 1024 * 1024]; while start.elapsed() < self.timeout {
50 for chunk in data.chunks_mut(1024) {
52 chunk.fill(operations as u8);
53 operations += 1;
54 }
55 }
56
57 Ok(BenchmarkResult {
58 benchmark_type: BenchmarkType::Memory,
59 duration: start.elapsed(),
60 operations,
61 score: self.calculate_memory_score(operations, start.elapsed()),
62 })
63 }
64
65 fn calculate_cpu_score(&self, operations: u64, duration: Duration) -> f64 {
67 let ops_per_sec = operations as f64 / duration.as_secs_f64();
68 (ops_per_sec / 100_000.0).min(10.0)
70 }
71
72 fn calculate_memory_score(&self, operations: u64, duration: Duration) -> f64 {
74 let ops_per_sec = operations as f64 / duration.as_secs_f64();
75 (ops_per_sec / 50_000.0).min(10.0)
77 }
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct BenchmarkResult {
83 pub benchmark_type: BenchmarkType,
84 pub duration: Duration,
85 pub operations: u64,
86 pub score: f64,
87}
88
89#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
91pub enum BenchmarkType {
92 CPU,
93 Memory,
94 Storage,
95 Network,
96 GPU,
97}
98
99pub struct SystemFingerprinter;
101
102impl SystemFingerprinter {
103 pub fn generate_fingerprint() -> String {
105 use std::collections::hash_map::DefaultHasher;
106 use std::hash::{Hash, Hasher};
107
108 let mut hasher = DefaultHasher::new();
109
110 std::env::consts::OS.hash(&mut hasher);
112 std::env::consts::ARCH.hash(&mut hasher);
113
114 if let Ok(hostname) = std::env::var("COMPUTERNAME") {
116 hostname.hash(&mut hasher);
117 } else if let Ok(hostname) = std::env::var("HOSTNAME") {
118 hostname.hash(&mut hasher);
119 }
120
121 format!("{:x}", hasher.finish())
122 }
123
124 pub fn has_system_changed(last_fingerprint: &str) -> bool {
126 let current_fingerprint = Self::generate_fingerprint();
127 current_fingerprint != last_fingerprint
128 }
129}
130
131pub struct PerformanceOptimizer;
133
134impl PerformanceOptimizer {
135 pub fn suggest_optimizations(
137 system_profile: &SystemProfile,
138 _workload_requirements: &WorkloadRequirements,
139 ) -> Vec<OptimizationSuggestion> {
140 let mut suggestions = Vec::new();
141
142 if system_profile.cpu_score() < 7.0 {
144 suggestions.push(OptimizationSuggestion {
145 resource_type: ResourceType::CPU,
146 suggestion: "Consider enabling CPU performance mode".to_string(),
147 expected_improvement: "5-15% performance increase".to_string(),
148 difficulty: OptimizationDifficulty::Easy,
149 });
150 }
151
152 if system_profile.memory_score() < 6.0 {
154 suggestions.push(OptimizationSuggestion {
155 resource_type: ResourceType::Memory,
156 suggestion: "Close unnecessary applications to free memory".to_string(),
157 expected_improvement: "10-20% memory availability increase".to_string(),
158 difficulty: OptimizationDifficulty::Easy,
159 });
160 }
161
162 if system_profile.storage_score() < 5.0 {
164 suggestions.push(OptimizationSuggestion {
165 resource_type: ResourceType::Storage,
166 suggestion: "Enable storage optimization and defragmentation".to_string(),
167 expected_improvement: "10-30% I/O performance increase".to_string(),
168 difficulty: OptimizationDifficulty::Medium,
169 });
170 }
171
172 if system_profile.gpu_score() < 4.0 {
174 suggestions.push(OptimizationSuggestion {
175 resource_type: ResourceType::GPU,
176 suggestion: "Update GPU drivers and enable GPU scheduling".to_string(),
177 expected_improvement: "5-25% graphics performance increase".to_string(),
178 difficulty: OptimizationDifficulty::Medium,
179 });
180 }
181
182 suggestions
183 }
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct OptimizationSuggestion {
189 pub resource_type: ResourceType,
190 pub suggestion: String,
191 pub expected_improvement: String,
192 pub difficulty: OptimizationDifficulty,
193}
194
195#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
197pub enum OptimizationDifficulty {
198 Easy,
199 Medium,
200 Hard,
201 Expert,
202}
203
204pub struct ResourceComparator;
206
207impl ResourceComparator {
208 pub fn compare_systems(
210 system_a: &SystemProfile,
211 system_b: &SystemProfile,
212 ) -> SystemComparison {
213 let cpu_diff = system_b.cpu_score() - system_a.cpu_score();
214 let gpu_diff = system_b.gpu_score() - system_a.gpu_score();
215 let memory_diff = system_b.memory_score() - system_a.memory_score();
216 let storage_diff = system_b.storage_score() - system_a.storage_score();
217 let network_diff = system_b.network_score() - system_a.network_score();
218
219 let overall_diff = system_b.overall_score() - system_a.overall_score();
220
221 SystemComparison {
222 cpu_difference: cpu_diff,
223 gpu_difference: gpu_diff,
224 memory_difference: memory_diff,
225 storage_difference: storage_diff,
226 network_difference: network_diff,
227 overall_difference: overall_diff,
228 winner: if overall_diff > 0.0 {
229 ComparisonResult::SystemB
230 } else if overall_diff < 0.0 {
231 ComparisonResult::SystemA
232 } else {
233 ComparisonResult::Tie
234 },
235 }
236 }
237
238 pub fn compare_resource_amounts(
240 amount_a: &ResourceAmount,
241 amount_b: &ResourceAmount,
242 ) -> Option<f64> {
243 match (amount_a, amount_b) {
244 (ResourceAmount::Score(a), ResourceAmount::Score(b)) => Some(b - a),
245 (ResourceAmount::Gigabytes(a), ResourceAmount::Gigabytes(b)) => Some(b - a),
246 (ResourceAmount::Megahertz(a), ResourceAmount::Megahertz(b)) => Some(b - a),
247 (ResourceAmount::Units(a), ResourceAmount::Units(b)) => Some(*b as f64 - *a as f64),
248 (ResourceAmount::Percentage(a), ResourceAmount::Percentage(b)) => Some(b - a),
249 (ResourceAmount::Level(a), ResourceAmount::Level(b)) => {
250 let a_score: f64 = (*a).into();
251 let b_score: f64 = (*b).into();
252 Some(b_score - a_score)
253 }
254 _ => None, }
256 }
257}
258
259#[derive(Debug, Clone, Serialize, Deserialize)]
261pub struct SystemComparison {
262 pub cpu_difference: f64,
263 pub gpu_difference: f64,
264 pub memory_difference: f64,
265 pub storage_difference: f64,
266 pub network_difference: f64,
267 pub overall_difference: f64,
268 pub winner: ComparisonResult,
269}
270
271#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
273pub enum ComparisonResult {
274 SystemA,
275 SystemB,
276 Tie,
277}
278
279pub struct ConfigValidator;
281
282impl ConfigValidator {
283 pub fn validate_workload_requirements(
285 workload_requirements: &WorkloadRequirements,
286 ) -> Result<Vec<ValidationIssue>> {
287 let mut issues = Vec::new();
288
289 let mut resource_types = std::collections::HashSet::new();
291 for req in &workload_requirements.resource_requirements {
292 if resource_types.contains(&req.resource_type) {
293 issues.push(ValidationIssue {
294 severity: ValidationSeverity::Warning,
295 message: format!("Duplicate resource requirement for {:?}", req.resource_type),
296 suggestion: "Merge duplicate requirements".to_string(),
297 });
298 }
299 resource_types.insert(req.resource_type);
300 }
301
302 for req in &workload_requirements.resource_requirements {
304 match &req.minimum {
305 ResourceAmount::Gigabytes(gb) if *gb > 1000.0 => {
306 issues.push(ValidationIssue {
307 severity: ValidationSeverity::Warning,
308 message: format!("Very high {} requirement: {:.1}GB", req.resource_type, gb),
309 suggestion: "Verify this requirement is realistic".to_string(),
310 });
311 }
312 ResourceAmount::Score(score) if *score > 10.0 => {
313 issues.push(ValidationIssue {
314 severity: ValidationSeverity::Error,
315 message: format!("Invalid score for {}: {:.1} (max 10.0)", req.resource_type, score),
316 suggestion: "Adjust score to be within 0-10 range".to_string(),
317 });
318 }
319 _ => {}
320 }
321 }
322
323 if let Some(workload) = &workload_requirements.workload {
325 if let Err(e) = workload.validate() {
326 issues.push(ValidationIssue {
327 severity: ValidationSeverity::Error,
328 message: format!("Workload validation failed: {}", e),
329 suggestion: "Fix workload configuration".to_string(),
330 });
331 }
332 }
333
334 Ok(issues)
335 }
336
337 pub fn validate_system_profile(system_profile: &SystemProfile) -> Result<Vec<ValidationIssue>> {
339 let mut issues = Vec::new();
340
341 let scores = [
343 ("CPU", system_profile.cpu_score()),
344 ("GPU", system_profile.gpu_score()),
345 ("Memory", system_profile.memory_score()),
346 ("Storage", system_profile.storage_score()),
347 ("Network", system_profile.network_score()),
348 ];
349
350 for (name, score) in scores {
351 if score < 0.0 || score > 10.0 {
352 issues.push(ValidationIssue {
353 severity: ValidationSeverity::Error,
354 message: format!("Invalid {} score: {:.1} (should be 0-10)", name, score),
355 suggestion: "Recalibrate scoring algorithm".to_string(),
356 });
357 }
358 }
359
360 let memory_gb = system_profile.system_info.memory_info.total_ram as f64 / 1024.0;
362 if memory_gb > 1000.0 {
363 issues.push(ValidationIssue {
364 severity: ValidationSeverity::Warning,
365 message: format!("Very high memory amount detected: {:.1}GB", memory_gb),
366 suggestion: "Verify memory detection is accurate".to_string(),
367 });
368 }
369
370 Ok(issues)
371 }
372}
373
374#[derive(Debug, Clone, Serialize, Deserialize)]
376pub struct ValidationIssue {
377 pub severity: ValidationSeverity,
378 pub message: String,
379 pub suggestion: String,
380}
381
382#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
384pub enum ValidationSeverity {
385 Info,
386 Warning,
387 Error,
388}
389
390pub struct HardwareDetector;
392
393impl HardwareDetector {
394 pub fn detect_hardware_changes(
396 last_system_info: &crate::types::SystemInfo,
397 current_system_info: &crate::types::SystemInfo,
398 ) -> Vec<HardwareChange> {
399 let mut changes = Vec::new();
400
401 if last_system_info.cpu_info.brand != current_system_info.cpu_info.brand {
403 changes.push(HardwareChange {
404 component: HardwareComponent::CPU,
405 change_type: HardwareChangeType::Replaced,
406 details: format!("CPU changed from '{}' to '{}'",
407 last_system_info.cpu_info.brand,
408 current_system_info.cpu_info.brand),
409 });
410 }
411
412 if last_system_info.memory_info.total_ram != current_system_info.memory_info.total_ram {
414 changes.push(HardwareChange {
415 component: HardwareComponent::Memory,
416 change_type: if current_system_info.memory_info.total_ram > last_system_info.memory_info.total_ram {
417 HardwareChangeType::Upgraded
418 } else {
419 HardwareChangeType::Downgraded
420 },
421 details: format!("Memory changed from {}MB to {}MB",
422 last_system_info.memory_info.total_ram,
423 current_system_info.memory_info.total_ram),
424 });
425 }
426
427 if last_system_info.gpu_info.len() != current_system_info.gpu_info.len() {
429 changes.push(HardwareChange {
430 component: HardwareComponent::GPU,
431 change_type: if current_system_info.gpu_info.len() > last_system_info.gpu_info.len() {
432 HardwareChangeType::Added
433 } else {
434 HardwareChangeType::Removed
435 },
436 details: format!("GPU count changed from {} to {}",
437 last_system_info.gpu_info.len(),
438 current_system_info.gpu_info.len()),
439 });
440 }
441
442 if last_system_info.storage_info.len() != current_system_info.storage_info.len() {
444 changes.push(HardwareChange {
445 component: HardwareComponent::Storage,
446 change_type: if current_system_info.storage_info.len() > last_system_info.storage_info.len() {
447 HardwareChangeType::Added
448 } else {
449 HardwareChangeType::Removed
450 },
451 details: format!("Storage device count changed from {} to {}",
452 last_system_info.storage_info.len(),
453 current_system_info.storage_info.len()),
454 });
455 }
456
457 changes
458 }
459}
460
461#[derive(Debug, Clone, Serialize, Deserialize)]
463pub struct HardwareChange {
464 pub component: HardwareComponent,
465 pub change_type: HardwareChangeType,
466 pub details: String,
467}
468
469#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
471pub enum HardwareComponent {
472 CPU,
473 GPU,
474 Memory,
475 Storage,
476 Network,
477}
478
479#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
481pub enum HardwareChangeType {
482 Added,
483 Removed,
484 Replaced,
485 Upgraded,
486 Downgraded,
487}
488
489pub struct TrendAnalyzer;
491
492impl TrendAnalyzer {
493 pub fn analyze_trends(
495 historical_profiles: &[SystemProfile],
496 ) -> PerformanceTrends {
497 if historical_profiles.is_empty() {
498 return PerformanceTrends::default();
499 }
500
501 let mut cpu_scores = Vec::new();
502 let mut gpu_scores = Vec::new();
503 let mut memory_scores = Vec::new();
504 let mut storage_scores = Vec::new();
505 let mut network_scores = Vec::new();
506
507 for profile in historical_profiles {
508 cpu_scores.push(profile.cpu_score());
509 gpu_scores.push(profile.gpu_score());
510 memory_scores.push(profile.memory_score());
511 storage_scores.push(profile.storage_score());
512 network_scores.push(profile.network_score());
513 }
514
515 PerformanceTrends {
516 cpu_trend: Self::calculate_trend(&cpu_scores),
517 gpu_trend: Self::calculate_trend(&gpu_scores),
518 memory_trend: Self::calculate_trend(&memory_scores),
519 storage_trend: Self::calculate_trend(&storage_scores),
520 network_trend: Self::calculate_trend(&network_scores),
521 overall_trend: Self::calculate_trend(&historical_profiles.iter()
522 .map(|p| p.overall_score())
523 .collect::<Vec<_>>()),
524 }
525 }
526
527 fn calculate_trend(values: &[f64]) -> TrendDirection {
529 if values.len() < 2 {
530 return TrendDirection::Stable;
531 }
532
533 let first_half = &values[..values.len() / 2];
534 let second_half = &values[values.len() / 2..];
535
536 let first_avg = first_half.iter().sum::<f64>() / first_half.len() as f64;
537 let second_avg = second_half.iter().sum::<f64>() / second_half.len() as f64;
538
539 let diff = second_avg - first_avg;
540
541 if diff > 0.5 {
542 TrendDirection::Improving
543 } else if diff < -0.5 {
544 TrendDirection::Declining
545 } else {
546 TrendDirection::Stable
547 }
548 }
549}
550
551#[derive(Debug, Clone, Serialize, Deserialize)]
553pub struct PerformanceTrends {
554 pub cpu_trend: TrendDirection,
555 pub gpu_trend: TrendDirection,
556 pub memory_trend: TrendDirection,
557 pub storage_trend: TrendDirection,
558 pub network_trend: TrendDirection,
559 pub overall_trend: TrendDirection,
560}
561
562impl Default for PerformanceTrends {
563 fn default() -> Self {
564 Self {
565 cpu_trend: TrendDirection::Stable,
566 gpu_trend: TrendDirection::Stable,
567 memory_trend: TrendDirection::Stable,
568 storage_trend: TrendDirection::Stable,
569 network_trend: TrendDirection::Stable,
570 overall_trend: TrendDirection::Stable,
571 }
572 }
573}
574
575#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
577pub enum TrendDirection {
578 Improving,
579 Stable,
580 Declining,
581}
582
583pub mod common {
585 use super::*;
586
587 pub fn capability_level_to_string(level: CapabilityLevel) -> &'static str {
589 match level {
590 CapabilityLevel::VeryLow => "Very Low",
591 CapabilityLevel::Low => "Low",
592 CapabilityLevel::Medium => "Medium",
593 CapabilityLevel::High => "High",
594 CapabilityLevel::VeryHigh => "Very High",
595 CapabilityLevel::Exceptional => "Exceptional",
596 }
597 }
598
599 pub fn format_resource_amount(amount: &ResourceAmount) -> String {
601 match amount {
602 ResourceAmount::Level(level) => capability_level_to_string(*level).to_string(),
603 ResourceAmount::Gigabytes(gb) => format!("{:.1} GB", gb),
604 ResourceAmount::Megahertz(mhz) => format!("{:.0} MHz", mhz),
605 ResourceAmount::Score(score) => format!("{:.1}/10", score),
606 ResourceAmount::Units(units) => format!("{} units", units),
607 ResourceAmount::Percentage(pct) => format!("{:.1}%", pct),
608 ResourceAmount::Custom { value, unit } => format!("{:.1} {}", value, unit),
609 }
610 }
611
612 pub fn percentage_difference(old_value: f64, new_value: f64) -> f64 {
614 if old_value == 0.0 {
615 if new_value == 0.0 { 0.0 } else { 100.0 }
616 } else {
617 ((new_value - old_value) / old_value) * 100.0
618 }
619 }
620
621 pub fn round_to_decimal(value: f64, decimal_places: u32) -> f64 {
623 let factor = 10.0_f64.powi(decimal_places as i32);
624 (value * factor).round() / factor
625 }
626}