From 15fe8055dd63f92c18d9549653174de716c61e92 Mon Sep 17 00:00:00 2001 From: MohdMohsin97 Date: Wed, 24 Jul 2024 20:10:41 +0530 Subject: [PATCH] structure the project --- Cargo.lock | 238 +++++++++++++++++++++++++++++----- Cargo.toml | 4 +- src/data_collection/cpu.rs | 20 ++- src/data_collection/memory.rs | 23 ++-- src/data_collection/mod.rs | 5 +- src/main.rs | 51 +------- src/tui/main.rs | 167 ++++++++++++++++++++++++ src/tui/mod.rs | 131 +++++++++++++++++++ src/tui/modals.rs | 81 ++++++++++++ src/ui/mod.rs | 138 -------------------- 10 files changed, 617 insertions(+), 241 deletions(-) create mode 100644 src/tui/main.rs create mode 100644 src/tui/mod.rs create mode 100644 src/tui/modals.rs delete mode 100644 src/ui/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 600f838..8fd487e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,24 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + [[package]] name = "autocfg" version = "1.3.0" @@ -38,12 +56,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.6.0" @@ -62,6 +74,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" +[[package]] +name = "castaway" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" +dependencies = [ + "rustversion", +] + [[package]] name = "cc" version = "1.1.5" @@ -75,19 +96,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "crossterm" -version = "0.25.0" +name = "compact_str" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" +checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" dependencies = [ - "bitflags 1.3.2", - "crossterm_winapi", - "libc", - "mio", - "parking_lot", - "signal-hook", - "signal-hook-mio", - "winapi", + "castaway", + "cfg-if", + "itoa", + "ryu", + "static_assertions", ] [[package]] @@ -96,7 +114,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 2.6.0", + "bitflags", "crossterm_winapi", "libc", "mio", @@ -115,18 +133,55 @@ dependencies = [ "winapi", ] +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "gimli" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + [[package]] name = "libc" version = "0.2.155" @@ -149,6 +204,15 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "lru" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +dependencies = [ + "hashbrown", +] + [[package]] name = "memchr" version = "2.7.4" @@ -195,6 +259,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + [[package]] name = "parking_lot" version = "0.12.3" @@ -218,6 +288,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -242,13 +318,34 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "ratatui" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16546c5b5962abf8ce6e2881e722b4e0ae3b6f1a08a26ae3573c55853ca68d3" +dependencies = [ + "bitflags", + "cassowary", + "compact_str", + "crossterm", + "itertools", + "lru", + "paste", + "stability", + "strum", + "strum_macros", + "unicode-segmentation", + "unicode-truncate", + "unicode-width", +] + [[package]] name = "redox_syscall" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 2.6.0", + "bitflags", ] [[package]] @@ -257,6 +354,18 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + [[package]] name = "scopeguard" version = "1.2.0" @@ -309,6 +418,44 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "stability" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "syn" version = "2.0.71" @@ -324,9 +471,8 @@ dependencies = [ name = "system-monitoring-cli" version = "0.1.0" dependencies = [ - "crossterm 0.27.0", + "ratatui", "tokio", - "tui", ] [[package]] @@ -359,19 +505,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tui" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccdd26cbd674007e649a272da4475fb666d3aa0ad0531da7136db6fab0e5bad1" -dependencies = [ - "bitflags 1.3.2", - "cassowary", - "crossterm 0.25.0", - "unicode-segmentation", - "unicode-width", -] - [[package]] name = "unicode-ident" version = "1.0.12" @@ -384,12 +517,29 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "unicode-truncate" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" +dependencies = [ + "itertools", + "unicode-segmentation", + "unicode-width", +] + [[package]] name = "unicode-width" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -556,3 +706,23 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index 486d39f..09d1a76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -tui = "0.19" -crossterm = "0.27.0" tokio = { version = "1", features = ["full"] } -# ratatui = "0.27.0" +ratatui = "0.27.0" diff --git a/src/data_collection/cpu.rs b/src/data_collection/cpu.rs index 32961e4..d5fd98b 100644 --- a/src/data_collection/cpu.rs +++ b/src/data_collection/cpu.rs @@ -4,7 +4,7 @@ use std::thread::sleep; use std::time::Duration; #[derive(Debug)] -pub struct CpuTimes { +struct CpuTimes { cpu: String, user: u64, nice: u64, @@ -18,6 +18,12 @@ pub struct CpuTimes { guest_nice: u64, } +#[derive(Debug)] +pub struct CpuInfo { + pub label: String, + pub percentage: f64 +} + fn read_cpu_times() -> Result> { if let Ok(file) = File::open("/proc/stat") { let reader = io::BufReader::new(file); @@ -56,8 +62,8 @@ fn parse_cputimes(line: String) -> CpuTimes { fn calculate_cpu_usage( prev_times: &Vec, curr_times: &Vec, -) -> Vec<(String, f64)> { - let mut cpu_percentages: Vec<(String, f64)> = Vec::new(); +) -> Vec { + let mut cpu_percentages: Vec = Vec::new(); for i in 0..prev_times.len() { let prev = &prev_times[i]; @@ -79,20 +85,20 @@ fn calculate_cpu_usage( let cpu_percentage = (totald - idled) as f64 / totald as f64 * 100.0; - cpu_percentages.push((prev.cpu.clone(), cpu_percentage)); + cpu_percentages.push(CpuInfo{ label: prev.cpu.clone(), percentage: cpu_percentage}); } cpu_percentages } -pub fn cpu_usage_percentage() -> Result> { +pub fn cpu_usage_percentage() -> Result> { let prev = read_cpu_times().expect("Failed to read CPU times"); // Wait for a second sleep(Duration::new(1, 0)); // Second snapshot let curr = read_cpu_times().expect("Failed to read CPU times"); - let cpu_usage: Vec<(String, f64)> = calculate_cpu_usage(&prev, &curr); + let cpu_usage: Vec = calculate_cpu_usage(&prev, &curr); // for usage in &cpu_usage { // println!("{} usage is {:.2}", usage.0, usage.1); @@ -110,7 +116,7 @@ mod tests { let cpu_usage = cpu_usage_percentage().unwrap(); for usage in cpu_usage { - println!("{} usage is {:.2}", usage.0, usage.1); + println!("{} usage is {:.2}", usage.label, usage.percentage); } } } diff --git a/src/data_collection/memory.rs b/src/data_collection/memory.rs index f431f13..dd9a955 100644 --- a/src/data_collection/memory.rs +++ b/src/data_collection/memory.rs @@ -3,13 +3,15 @@ use std::{ io::{BufRead, BufReader, Error, ErrorKind, Result}, }; -struct MemInfo { - total: u64, - available: u64, - cache: u64, +#[derive(Debug)] +pub struct MemInfo { + pub total: u64, + pub available: u64, + pub cache: u64, + pub percentage: f64, } -fn read_mem_info() -> Result { +pub fn read_mem_info() -> Result { if let Ok(file) = File::open("/proc/meminfo") { let reader = BufReader::new(file); @@ -17,6 +19,7 @@ fn read_mem_info() -> Result { total: 0, available: 0, cache: 0, + percentage: 0.0 }; for line in reader.lines() { let line = line?; @@ -29,19 +32,17 @@ fn read_mem_info() -> Result { } } + mem_info.percentage = mem_usage_percentage(&mem_info); + return Ok(mem_info); } Err(Error::new(ErrorKind::NotFound, "Memory data not found")) } -pub fn mem_usage_percentage() -> f64 { - let mem_info = read_mem_info().unwrap(); +fn mem_usage_percentage(mem_info : &MemInfo) -> f64 { let mem_usage_percentage = (mem_info.total - mem_info.available) as f64 / mem_info.total as f64 * 100 as f64; - // println!("Memory Usage: {:.2}%", mem_usage_percentage); - // println!("Cached: {}", mem_info.cache); - mem_usage_percentage } @@ -51,6 +52,6 @@ mod test { #[test] fn mem_usage() { - mem_usage_percentage(); + read_mem_info(); } } diff --git a/src/data_collection/mod.rs b/src/data_collection/mod.rs index 6f3ff8c..729e59e 100644 --- a/src/data_collection/mod.rs +++ b/src/data_collection/mod.rs @@ -1,4 +1,5 @@ mod cpu; mod memory; -pub use cpu::cpu_usage_percentage; -pub use memory::mem_usage_percentage; +pub use cpu::{cpu_usage_percentage, CpuInfo}; +pub use memory::{read_mem_info, MemInfo}; + diff --git a/src/main.rs b/src/main.rs index dd967a3..35079e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,51 +1,10 @@ -use crossterm::{ - event::{self, Event, KeyCode}, - execute, - terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, -}; -use std::{io, time::Duration}; -use tokio::time::interval; -use tui::{backend::CrosstermBackend, Terminal}; -use ui::{ui, App}; +use std::io::Result; +mod tui; mod data_collection; -mod ui; -#[tokio::main] -async fn main() -> Result<(), io::Error> { - // setup terminal - enable_raw_mode()?; - let mut stdout = io::stdout(); - execute!(stdout, EnterAlternateScreen)?; - let backend = CrosstermBackend::new(stdout); - let mut terminal = Terminal::new(backend)?; - - let mut app = App::new(); - - let mut tick_rate = interval(Duration::from_secs(1)); - - loop { - terminal.draw(|f| { - ui(f, &app); - })?; - - if crossterm::event::poll(Duration::from_millis(100))? { - if let Event::Key(key) = event::read()? { - if key.code == KeyCode::Char('q') { - break; - } - } - } - - app.update(); - - tick_rate.tick().await; - } - - // restore terminal - disable_raw_mode()?; - execute!(terminal.backend_mut(), LeaveAlternateScreen)?; - terminal.show_cursor()?; +fn main() -> Result<()> { + tui::main::main()?; Ok(()) -} +} \ No newline at end of file diff --git a/src/tui/main.rs b/src/tui/main.rs new file mode 100644 index 0000000..41faef6 --- /dev/null +++ b/src/tui/main.rs @@ -0,0 +1,167 @@ +use std::io::{stdout, Result, Stdout}; + +use ratatui::{ + backend::{Backend, CrosstermBackend}, + crossterm::{ + event::{self, KeyCode, KeyEventKind}, + execute, + terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, + }, + layout::{Constraint, Direction, Layout}, + style::{Color, Style}, + symbols, + text::Span, + widgets::{Axis, Block, Chart, Dataset, GraphType}, + Frame, Terminal, +}; + +use crate::tui::modals::App; + +pub fn main() -> Result<()> { + let mut terminal: Terminal> = init()?; + + let app = App::new(); + + run_app(&mut terminal, app)?; + + restore()?; + + Ok(()) +} + +fn run_app(terminal: &mut Terminal, mut app: App) -> Result<()> { + while !app.exit { + terminal.draw(|f| ui(f, &mut app))?; + + if event::poll(std::time::Duration::from_millis(16))? { + if let event::Event::Key(key) = event::read()? { + if key.kind == KeyEventKind::Press { + use KeyCode::*; + match key.code { + Char('q') | Esc => app.exit(), + _ => {} + } + } + } + } + + app.update(); + } + Ok(()) +} + +/// A type alias for the terminal type used in this application +pub type Tui = Terminal>; + +/// Initialize the terminal +fn init() -> Result { + execute!(stdout(), EnterAlternateScreen)?; + enable_raw_mode()?; + Terminal::new(CrosstermBackend::new(stdout())) +} + +/// Restore the terminal to its original state +pub fn restore() -> Result<()> { + execute!(stdout(), LeaveAlternateScreen)?; + disable_raw_mode()?; + Ok(()) +} + +fn ui(f: &mut Frame, app: &mut App) { + let chunks = Layout::default() + .direction(Direction::Vertical) + .margin(1) + .constraints([Constraint::Percentage(50), Constraint::Percentage(50)]) + .split(f.size()); + + let cpu_chart = create_cpu_chart(app); + f.render_widget(cpu_chart, chunks[0]); + + let mem_chart = create_mem_chart(app); + f.render_widget(mem_chart, chunks[1]); +} + +fn create_cpu_chart(app: &mut App) -> Chart { + let cpu_per_dataset = vec![Dataset::default() + .name("CPU") + .marker(symbols::Marker::Braille) + .style(Style::default().fg(Color::Cyan)) + .graph_type(GraphType::Line) + .data(&app.datasets.cpu_percent)]; + + let chart = Chart::new(cpu_per_dataset) + .block(Block::default().title("CPU Usage")) + .x_axis( + Axis::default() + .style(Style::default().fg(Color::White)) + .bounds([0.0, 60.0]) + .labels( + ["60s", "50s", "40s", "30s", "20s", "10s", "0s"] + .iter() + .cloned() + .map(Span::from) + .collect(), + ), + ) + .y_axis( + Axis::default() + .title(Span::styled( + format!("CPU : {:.2}", app.cpu_stats[0].percentage), + Style::default().fg(Color::Red), + )) + .style(Style::default().fg(Color::White)) + .bounds([0.0, 100.0]) + .labels( + ["0%", "20%", "40%", "60%", "80%", "100%"] + .iter() + .cloned() + .map(Span::from) + .collect(), + ), + ); + return chart; +} + +fn create_mem_chart(app: &mut App) -> Chart { + let mem_usage = (app.memory_stats.total - app.memory_stats.available) as f64 / (1024.0 * 1024.0); + let total_mem = app.memory_stats.total as f64 / (1024.0 * 1024.0); + + let mem_per_dataset = vec![Dataset::default() + .name("CPU") + .marker(symbols::Marker::Braille) + .style(Style::default().fg(Color::Cyan)) + .graph_type(GraphType::Line) + .data(&app.datasets.mem_percent)]; + + let chart = Chart::new(mem_per_dataset) + .block(Block::default().title("CPU Usage")) + .x_axis( + Axis::default() + .style(Style::default().fg(Color::White)) + .bounds([0.0, 60.0]) + .labels( + ["60s", "50s", "40s", "30s", "20s", "10s", "0s"] + .iter() + .cloned() + .map(Span::from) + .collect(), + ), + ) + .y_axis( + Axis::default() + .title(Span::styled( + format!("Memory : {:.2}Gb / {:.2}Gb", mem_usage, total_mem), + Style::default().fg(Color::Red), + )) + .style(Style::default().fg(Color::White)) + .bounds([0.0, 100.0]) + .labels( + ["0%", "20%", "40%", "60%", "80%", "100%"] + .iter() + .cloned() + .map(Span::from) + .collect(), + ), + ); + return chart; +} diff --git a/src/tui/mod.rs b/src/tui/mod.rs new file mode 100644 index 0000000..f57404b --- /dev/null +++ b/src/tui/mod.rs @@ -0,0 +1,131 @@ + +pub mod main; +mod modals; + +// pub struct App { +// cpu_percent: Vec<(f64, f64)>, +// mem_percent: Vec<(f64, f64)>, +// } + +// impl App { +// pub fn new() -> App { +// App { +// cpu_percent: vec![(0.0, 0.0); 60], +// mem_percent: vec![(0.0, 0.0); 60], +// } +// } + +// pub fn update(&mut self) { +// let mem_percent = data_collection::mem_usage_percentage(); + +// let cpu_percents = data_collection::cpu_usage_percentage().unwrap(); + +// let cpu_percent = cpu_percents[0].1; + +// let mem_point = (self.cpu_percent.len() as f64, mem_percent); +// self.mem_percent.push(mem_point); + +// let cpu_point = (self.cpu_percent.len() as f64, cpu_percent); +// self.cpu_percent.push(cpu_point); + +// if self.cpu_percent.len() > 60 { +// self.cpu_percent.remove(0); +// } + +// if self.mem_percent.len() > 60 { +// self.mem_percent.remove(0); +// } + +// for (i, point) in self.cpu_percent.iter_mut().enumerate() { +// point.0 = (i + 1) as f64; +// } + +// for (i, point) in self.mem_percent.iter_mut().enumerate() { +// point.0 = (i + 1) as f64; +// } + +// } +// } + + +// pub fn ui(f: &mut Frame, app: &App) { +// let chunks = Layout::default() +// .direction(Direction::Vertical) +// .margin(1) +// .constraints([Constraint::Percentage(50), Constraint::Percentage(50)]) +// .split(f.size()); + +// let cpu_per_dataset = vec![Dataset::default() +// .name("CPU") +// .marker(symbols::Marker::Dot) +// .style(Style::default().fg(Color::Cyan)) +// .graph_type(GraphType::Line) +// .data(&app.cpu_percent)]; + +// let chart = Chart::new(cpu_per_dataset) +// .block(Block::default().title("CPU Usage")) +// .x_axis( +// Axis::default() +// .title(Span::styled("X Axis", Style::default().fg(Color::Red))) +// .style(Style::default().fg(Color::White)) +// .bounds([0.0, 60.0]) +// .labels( +// ["60s", "50s", "40s", "30s", "20s", "10s", "0s"] +// .iter() +// .cloned() +// .map(Span::from) +// .collect(), +// ), +// ) +// .y_axis( +// Axis::default() +// .title(Span::styled("Y Axis", Style::default().fg(Color::Red))) +// .style(Style::default().fg(Color::White)) +// .bounds([0.0, 100.0]) +// .labels( +// ["0%", "20%", "40%", "60%", "80%", "100%"] +// .iter() +// .cloned() +// .map(Span::from) +// .collect(), +// ), +// ); +// f.render_widget(chart, chunks[0]); + +// let mem_per_dataset = vec![Dataset::default() +// .name("Memory") +// .marker(symbols::Marker::Dot) +// .style(Style::default().fg(Color::Cyan)) +// .graph_type(GraphType::Line) +// .data(&app.mem_percent)]; + +// let chart = Chart::new(mem_per_dataset) +// .block(Block::default().title("Memory Usage")) +// .x_axis( +// Axis::default() +// .title(Span::styled("X Axis", Style::default().fg(Color::Red))) +// .style(Style::default().fg(Color::White)) +// .bounds([0.0, 60.0]) +// .labels( +// ["60s", "50s", "40s", "30s", "20s", "10s", "0s"] +// .iter() +// .cloned() +// .map(Span::from) +// .collect(), +// ), +// ) +// .y_axis( +// Axis::default() +// .title(Span::styled("Y Axis", Style::default().fg(Color::Red))) +// .style(Style::default().fg(Color::White)) +// .bounds([0.0, 100.0]) +// .labels( +// ["0%", "20%", "40%", "60%", "80%", "100%"] +// .iter() +// .cloned() +// .map(Span::from) +// .collect(), +// ), +// ); +// f.render_widget(chart, chunks[1]); +// } diff --git a/src/tui/modals.rs b/src/tui/modals.rs new file mode 100644 index 0000000..852b23c --- /dev/null +++ b/src/tui/modals.rs @@ -0,0 +1,81 @@ +use crate::data_collection::{cpu_usage_percentage, read_mem_info, CpuInfo, MemInfo}; + +#[derive(Debug)] +pub struct DataSets { + pub cpu_percent: Vec<(f64, f64)>, + pub mem_percent: Vec<(f64, f64)>, +} + +impl DataSets { + fn new() -> DataSets { + DataSets { + cpu_percent: vec![(0.0, 0.0); 60], + mem_percent: vec![(0.0, 0.0); 60], + } + } +} + +#[derive(Debug)] +pub struct App { + pub cpu_stats: Vec, + pub memory_stats: MemInfo, + pub exit: bool, + pub datasets: DataSets, +} + +impl App { + pub fn new() -> App { + let cpu_stats = cpu_usage_percentage().expect("Not able to fetch cpu stats"); + + let memory_stats = read_mem_info().expect("not able to read mem stats"); + + let datasets = DataSets::new(); + + App { + cpu_stats, + memory_stats, + exit: false, + datasets, + } + } + + pub fn update(&mut self) { + self.cpu_stats = cpu_usage_percentage().expect("Not able to fetch cpu stats"); + + self.memory_stats = read_mem_info().expect("not able to read mem stats"); + + update_cpu_dataset(self, self.cpu_stats[0].percentage); + update_mem_dataset(self, self.memory_stats.percentage); + + } + + pub fn exit(&mut self) { + self.exit = true; + } +} + +fn update_cpu_dataset(app: &mut App, percentage: f64 ) { + let cpu_point = (app.datasets.cpu_percent.len() as f64, percentage); + app.datasets.cpu_percent.push(cpu_point); + + if app.datasets.cpu_percent.len() > 60 { + app.datasets.cpu_percent.remove(0); + } + + for (i, point) in app.datasets.cpu_percent.iter_mut().enumerate() { + point.0 = (i + 1) as f64; + } +} + +fn update_mem_dataset(app: &mut App, percentage: f64 ) { + let mem_point = (app.datasets.mem_percent.len() as f64, percentage); + app.datasets.mem_percent.push(mem_point); + + if app.datasets.mem_percent.len() > 60 { + app.datasets.mem_percent.remove(0); + } + + for (i, point) in app.datasets.mem_percent.iter_mut().enumerate() { + point.0 = (i + 1) as f64; + } +} \ No newline at end of file diff --git a/src/ui/mod.rs b/src/ui/mod.rs deleted file mode 100644 index 8e9668d..0000000 --- a/src/ui/mod.rs +++ /dev/null @@ -1,138 +0,0 @@ -use tui::{ - backend::Backend, - layout::{Constraint, Direction, Layout}, - style::{Color, Style}, - symbols, - text::Span, - widgets::{Axis, Block, Chart, Dataset, GraphType}, - Frame, -}; - -use crate::data_collection; - -pub struct App { - cpu_percent: Vec<(f64, f64)>, - mem_percent: Vec<(f64, f64)>, -} - -impl App { - pub fn new() -> App { - App { - cpu_percent: vec![(0.0, 0.0); 60], - mem_percent: vec![(0.0, 0.0); 60], - } - } - - pub fn update(&mut self) { - let mem_percent = data_collection::mem_usage_percentage(); - - let cpu_percents = data_collection::cpu_usage_percentage().unwrap(); - - let cpu_percent = cpu_percents[0].1; - - let mem_point = (self.cpu_percent.len() as f64, mem_percent); - self.mem_percent.push(mem_point); - - let cpu_point = (self.cpu_percent.len() as f64, cpu_percent); - self.cpu_percent.push(cpu_point); - - if self.cpu_percent.len() > 60 { - self.cpu_percent.remove(0); - } - - if self.mem_percent.len() > 60 { - self.mem_percent.remove(0); - } - - for (i, point) in self.cpu_percent.iter_mut().enumerate() { - point.0 = (i + 1) as f64; - } - - for (i, point) in self.mem_percent.iter_mut().enumerate() { - point.0 = (i + 1) as f64; - } - - } -} - -pub fn ui(f: &mut Frame, app: &App) { - let chunks = Layout::default() - .direction(Direction::Vertical) - .margin(1) - .constraints([Constraint::Percentage(50), Constraint::Percentage(50)]) - .split(f.size()); - - let cpu_per_dataset = vec![Dataset::default() - .name("CPU") - .marker(symbols::Marker::Dot) - .style(Style::default().fg(Color::Cyan)) - .graph_type(GraphType::Line) - .data(&app.cpu_percent)]; - - let chart = Chart::new(cpu_per_dataset) - .block(Block::default().title("CPU Usage")) - .x_axis( - Axis::default() - .title(Span::styled("X Axis", Style::default().fg(Color::Red))) - .style(Style::default().fg(Color::White)) - .bounds([0.0, 60.0]) - .labels( - ["60s", "50s", "40s", "30s", "20s", "10s", "0s"] - .iter() - .cloned() - .map(Span::from) - .collect(), - ), - ) - .y_axis( - Axis::default() - .title(Span::styled("Y Axis", Style::default().fg(Color::Red))) - .style(Style::default().fg(Color::White)) - .bounds([0.0, 100.0]) - .labels( - ["0%", "20%", "40%", "60%", "80%", "100%"] - .iter() - .cloned() - .map(Span::from) - .collect(), - ), - ); - f.render_widget(chart, chunks[0]); - - let mem_per_dataset = vec![Dataset::default() - .name("Memory") - .marker(symbols::Marker::Dot) - .style(Style::default().fg(Color::Cyan)) - .graph_type(GraphType::Line) - .data(&app.mem_percent)]; - - let chart = Chart::new(mem_per_dataset) - .block(Block::default().title("Memory Usage")) - .x_axis( - Axis::default() - .title(Span::styled("X Axis", Style::default().fg(Color::Red))) - .style(Style::default().fg(Color::White)) - .bounds([0.0, 60.0]) - .labels( - ["60s", "50s", "40s", "30s", "20s", "10s", "0s"] - .iter() - .cloned() - .map(Span::from) - .collect(), - ), - ) - .y_axis( - Axis::default() - .title(Span::styled("Y Axis", Style::default().fg(Color::Red))) - .style(Style::default().fg(Color::White)) - .bounds([0.0, 100.0]) - .labels( - ["0%", "20%", "40%", "60%", "80%", "100%"] - .iter() - .cloned() - .map(Span::from) - .collect(), - ), - ); - f.render_widget(chart, chunks[1]); -}