mod render;
mod types;
pub use types::{ComputeBackend, LoadStats, WorkloadType};
use crate::brick::{Brick, BrickAssertion, BrickBudget, BrickScore, BrickVerification};
use presentar_terminal::Theme;
use std::any::Any;
pub struct LoadControlPanelBrick {
pub backend: ComputeBackend,
pub workload: WorkloadType,
pub intensity: f64,
pub problem_size: usize,
pub is_running: bool,
pub stats: LoadStats,
pub error: Option<String>,
pub selected_item: usize,
pub theme: Theme,
pub brick_score: Option<BrickScore>,
pub gflops: f64,
}
impl LoadControlPanelBrick {
pub fn new() -> Self {
Self {
backend: ComputeBackend::default(),
workload: WorkloadType::default(),
intensity: 50.0,
problem_size: 1024,
is_running: false,
stats: LoadStats::default(),
error: None,
selected_item: 0,
theme: Theme::tokyo_night(),
brick_score: None,
gflops: 0.0,
}
}
pub fn next_backend(&mut self) {
let idx = ComputeBackend::ALL
.iter()
.position(|&b| b == self.backend)
.unwrap_or(0);
self.backend = ComputeBackend::ALL[(idx + 1) % ComputeBackend::ALL.len()];
}
pub fn prev_backend(&mut self) {
let idx = ComputeBackend::ALL
.iter()
.position(|&b| b == self.backend)
.unwrap_or(0);
self.backend =
ComputeBackend::ALL[(idx + ComputeBackend::ALL.len() - 1) % ComputeBackend::ALL.len()];
}
pub fn next_workload(&mut self) {
let idx = WorkloadType::ALL
.iter()
.position(|&w| w == self.workload)
.unwrap_or(0);
self.workload = WorkloadType::ALL[(idx + 1) % WorkloadType::ALL.len()];
}
pub fn prev_workload(&mut self) {
let idx = WorkloadType::ALL
.iter()
.position(|&w| w == self.workload)
.unwrap_or(0);
self.workload =
WorkloadType::ALL[(idx + WorkloadType::ALL.len() - 1) % WorkloadType::ALL.len()];
}
pub fn increase_intensity(&mut self) {
self.intensity = (self.intensity + 5.0).min(100.0);
}
pub fn decrease_intensity(&mut self) {
self.intensity = (self.intensity - 5.0).max(0.0);
}
pub fn increase_size(&mut self) {
self.problem_size = (self.problem_size * 2).min(65536);
}
pub fn decrease_size(&mut self) {
self.problem_size = (self.problem_size / 2).max(64);
}
pub fn toggle_running(&mut self) {
self.is_running = !self.is_running;
if self.is_running {
self.stats = LoadStats::default();
self.error = None;
}
}
pub fn update_stats(&mut self, stats: LoadStats) {
self.stats = stats;
}
pub fn update_score(&mut self, score: BrickScore, gflops: f64) {
self.brick_score = Some(score);
self.gflops = gflops;
}
pub fn set_error(&mut self, error: String) {
self.error = Some(error);
self.is_running = false;
}
pub fn next_item(&mut self) {
self.selected_item = (self.selected_item + 1) % 5;
}
pub fn prev_item(&mut self) {
self.selected_item = (self.selected_item + 4) % 5;
}
pub fn handle_left(&mut self) {
match self.selected_item {
0 => self.prev_backend(),
1 => self.prev_workload(),
2 => self.decrease_intensity(),
3 => self.decrease_size(),
4 => {} _ => {}
}
}
pub fn handle_right(&mut self) {
match self.selected_item {
0 => self.next_backend(),
1 => self.next_workload(),
2 => self.increase_intensity(),
3 => self.increase_size(),
4 => {} _ => {}
}
}
pub fn handle_enter(&mut self) {
if self.selected_item == 4 {
self.toggle_running();
}
}
}
impl Default for LoadControlPanelBrick {
fn default() -> Self {
Self::new()
}
}
impl Brick for LoadControlPanelBrick {
fn brick_name(&self) -> &'static str {
"load_control_panel"
}
fn assertions(&self) -> Vec<BrickAssertion> {
vec![
BrickAssertion::MinWidth(50),
BrickAssertion::MinHeight(20),
BrickAssertion::max_latency_ms(8),
]
}
fn budget(&self) -> BrickBudget {
BrickBudget::FRAME_60FPS
}
fn verify(&self) -> BrickVerification {
let mut v = BrickVerification::new();
for assertion in self.assertions() {
v.check(&assertion);
}
v
}
fn as_any(&self) -> &dyn Any {
self
}
}
#[cfg(test)]
mod tests;