use crate::app_state::AppState;
use crate::common::config::AppConfig;
pub struct DataAggregator;
impl DataAggregator {
pub fn new() -> Self {
Self
}
pub fn update_utilization_history(&self, state: &mut AppState) {
self.update_cpu_history(state);
self.update_gpu_history(state);
}
fn update_cpu_history(&self, state: &mut AppState) {
if state.cpu_info.is_empty() {
return;
}
let avg_cpu_utilization = state
.cpu_info
.iter()
.map(|cpu| cpu.utilization)
.sum::<f64>()
/ state.cpu_info.len() as f64;
let avg_system_memory_usage = if !state.memory_info.is_empty() {
state
.memory_info
.iter()
.map(|mem| {
if mem.total_bytes > 0 {
(mem.used_bytes as f64 / mem.total_bytes as f64) * 100.0
} else {
0.0
}
})
.sum::<f64>()
/ state.memory_info.len() as f64
} else {
0.0
};
let cpu_temps: Vec<f64> = state
.cpu_info
.iter()
.filter_map(|cpu| cpu.temperature.map(|t| t as f64))
.collect();
let avg_cpu_temperature = if !cpu_temps.is_empty() {
cpu_temps.iter().sum::<f64>() / cpu_temps.len() as f64
} else {
0.0
};
state.cpu_utilization_history.push_back(avg_cpu_utilization);
state
.system_memory_history
.push_back(avg_system_memory_usage);
state.cpu_temperature_history.push_back(avg_cpu_temperature);
if state.cpu_utilization_history.len() > AppConfig::HISTORY_MAX_ENTRIES {
state.cpu_utilization_history.pop_front();
}
if state.system_memory_history.len() > AppConfig::HISTORY_MAX_ENTRIES {
state.system_memory_history.pop_front();
}
if state.cpu_temperature_history.len() > AppConfig::HISTORY_MAX_ENTRIES {
state.cpu_temperature_history.pop_front();
}
}
fn update_gpu_history(&self, state: &mut AppState) {
let has_gpu_data = !state.gpu_info.is_empty();
let is_apple_silicon = state.gpu_info.iter().any(|gpu| {
gpu.detail
.get("Architecture")
.map(|arch| arch == "Apple Silicon")
.unwrap_or(false)
});
if has_gpu_data
&& (state.gpu_info.iter().any(|gpu| gpu.total_memory > 0) || is_apple_silicon)
{
let avg_utilization = state
.gpu_info
.iter()
.map(|gpu| gpu.utilization)
.sum::<f64>()
/ state.gpu_info.len() as f64;
let avg_memory = state
.gpu_info
.iter()
.map(|gpu| {
if gpu.total_memory > 0 {
(gpu.used_memory as f64 / gpu.total_memory as f64) * 100.0
} else {
0.0
}
})
.sum::<f64>()
/ state.gpu_info.len() as f64;
let avg_temperature = state
.gpu_info
.iter()
.map(|gpu| gpu.temperature as f64)
.sum::<f64>()
/ state.gpu_info.len() as f64;
state.utilization_history.push_back(avg_utilization);
state.memory_history.push_back(avg_memory);
state.temperature_history.push_back(avg_temperature);
if state.utilization_history.len() > AppConfig::HISTORY_MAX_ENTRIES {
state.utilization_history.pop_front();
}
if state.memory_history.len() > AppConfig::HISTORY_MAX_ENTRIES {
state.memory_history.pop_front();
}
if state.temperature_history.len() > AppConfig::HISTORY_MAX_ENTRIES {
state.temperature_history.pop_front();
}
} else if !state.cpu_info.is_empty() {
self.update_fallback_history(state);
}
}
fn update_fallback_history(&self, state: &mut AppState) {
let avg_cpu_utilization = state
.cpu_info
.iter()
.map(|cpu| cpu.utilization)
.sum::<f64>()
/ state.cpu_info.len() as f64;
let avg_memory_usage = if !state.memory_info.is_empty() {
state
.memory_info
.iter()
.map(|mem| {
if mem.total_bytes > 0 {
(mem.used_bytes as f64 / mem.total_bytes as f64) * 100.0
} else {
0.0
}
})
.sum::<f64>()
/ state.memory_info.len() as f64
} else {
0.0
};
let cpu_temps: Vec<f64> = state
.cpu_info
.iter()
.filter_map(|cpu| cpu.temperature.map(|t| t as f64))
.collect();
let avg_temperature = if !cpu_temps.is_empty() {
cpu_temps.iter().sum::<f64>() / cpu_temps.len() as f64
} else {
0.0
};
state.utilization_history.push_back(avg_cpu_utilization);
state.memory_history.push_back(avg_memory_usage);
state.temperature_history.push_back(avg_temperature);
if state.utilization_history.len() > AppConfig::HISTORY_MAX_ENTRIES {
state.utilization_history.pop_front();
}
if state.memory_history.len() > AppConfig::HISTORY_MAX_ENTRIES {
state.memory_history.pop_front();
}
if state.temperature_history.len() > AppConfig::HISTORY_MAX_ENTRIES {
state.temperature_history.pop_front();
}
}
#[allow(dead_code)]
pub fn calculate_avg_gpu_utilization(state: &AppState) -> f64 {
if state.gpu_info.is_empty() {
return 0.0;
}
state
.gpu_info
.iter()
.map(|gpu| gpu.utilization)
.sum::<f64>()
/ state.gpu_info.len() as f64
}
#[allow(dead_code)]
pub fn calculate_avg_gpu_memory(state: &AppState) -> f64 {
if state.gpu_info.is_empty() {
return 0.0;
}
state
.gpu_info
.iter()
.map(|gpu| {
if gpu.total_memory > 0 {
(gpu.used_memory as f64 / gpu.total_memory as f64) * 100.0
} else {
0.0
}
})
.sum::<f64>()
/ state.gpu_info.len() as f64
}
#[allow(dead_code)]
pub fn calculate_avg_cpu_utilization(state: &AppState) -> f64 {
if state.cpu_info.is_empty() {
return 0.0;
}
state
.cpu_info
.iter()
.map(|cpu| cpu.utilization)
.sum::<f64>()
/ state.cpu_info.len() as f64
}
#[allow(dead_code)]
pub fn calculate_avg_system_memory(state: &AppState) -> f64 {
if state.memory_info.is_empty() {
return 0.0;
}
state
.memory_info
.iter()
.map(|mem| {
if mem.total_bytes > 0 {
(mem.used_bytes as f64 / mem.total_bytes as f64) * 100.0
} else {
0.0
}
})
.sum::<f64>()
/ state.memory_info.len() as f64
}
}
impl Default for DataAggregator {
fn default() -> Self {
Self::new()
}
}