Skip to content

Commit

Permalink
feat: graphs in statistics (#108)
Browse files Browse the repository at this point in the history
  • Loading branch information
micielski authored Aug 27, 2024
1 parent 168aa25 commit 2c82f69
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 6 deletions.
3 changes: 3 additions & 0 deletions rm-main/src/tui/tabs/torrents/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ impl Component for TorrentsTab {
fn handle_update_action(&mut self, action: UpdateAction) {
match action {
UpdateAction::SessionStats(stats) => {
if let Some(CurrentPopup::Stats(popup)) = &mut self.popup_manager.current_popup {
popup.update_stats(&stats)
}
self.bottom_stats.set_stats(stats);
}
UpdateAction::FreeSpace(free_space) => {
Expand Down
2 changes: 1 addition & 1 deletion rm-main/src/tui/tabs/torrents/popups/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub mod stats;

pub struct PopupManager {
ctx: app::Ctx,
current_popup: Option<CurrentPopup>,
pub current_popup: Option<CurrentPopup>,
}

pub enum CurrentPopup {
Expand Down
74 changes: 69 additions & 5 deletions rm-main/src/tui/tabs/torrents/popups/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ use std::sync::Arc;

use ratatui::{
prelude::*,
widgets::{Clear, Paragraph},
widgets::{BarChart, Block, Clear, Paragraph},
};
use rm_config::CONFIG;
use transmission_rpc::types::SessionStats;

use rm_shared::{action::Action, utils::bytes_to_human_format};
Expand All @@ -14,11 +15,37 @@ use crate::tui::components::{

pub struct StatisticsPopup {
stats: Arc<SessionStats>,
upload_data: Vec<(&'static str, u64)>,
download_data: Vec<(&'static str, u64)>,
max_up: i64,
max_down: i64,
}

impl StatisticsPopup {
pub const fn new(stats: Arc<SessionStats>) -> Self {
Self { stats }
pub fn new(stats: Arc<SessionStats>) -> Self {
Self {
upload_data: vec![("", stats.upload_speed as u64)],
download_data: vec![("", stats.download_speed as u64)],
max_up: stats.upload_speed,
max_down: stats.download_speed,
stats,
}
}

pub fn update_stats(&mut self, stats: &SessionStats) {
let up = stats.upload_speed;
let down = stats.download_speed;

if up > self.max_up {
self.max_up = up;
}

if down > self.max_down {
self.max_down = down;
}

self.upload_data.insert(0, ("", up as u64));
self.download_data.insert(0, ("", down as u64));
}
}

Expand All @@ -33,20 +60,57 @@ impl Component for StatisticsPopup {
}

fn render(&mut self, f: &mut Frame, rect: Rect) {
let (popup_rect, block_rect, text_rect) = popup_rects(rect, 50, 50);
let (popup_rect, block_rect, text_rect) = popup_rects(rect, 75, 50);

let [text_rect, _, upload_rect, download_rect] = Layout::vertical([
Constraint::Length(3),
Constraint::Length(1),
Constraint::Percentage(50),
Constraint::Percentage(50),
])
.areas(text_rect);

let block = popup_block_with_close_highlight(" Statistics ");

let upload_barchart = make_barchart("Upload", self.max_up as u64, &self.upload_data);
let download_barchart =
make_barchart("Download", self.max_down as u64, &self.download_data);

let uploaded_bytes = self.stats.cumulative_stats.uploaded_bytes;
let downloaded_bytes = self.stats.cumulative_stats.downloaded_bytes;
let uploaded = bytes_to_human_format(uploaded_bytes);
let downloaded = bytes_to_human_format(downloaded_bytes);
let ratio = uploaded_bytes as f64 / downloaded_bytes as f64;
let text = format!("Uploaded: {uploaded}\nDownloaded: {downloaded}\nRatio: {ratio:.2}");
let text = format!(
"Total uploaded: {uploaded}\nTotal downloaded: {downloaded}\nRatio: {ratio:.2}"
);
let paragraph = Paragraph::new(text);

f.render_widget(Clear, popup_rect);
f.render_widget(block, block_rect);
f.render_widget(paragraph, text_rect);
f.render_widget(upload_barchart, upload_rect);
f.render_widget(download_barchart, download_rect);
}
}

fn make_barchart<'a>(
name: &'static str,
max: u64,
data: &'a [(&'static str, u64)],
) -> BarChart<'a> {
let avg = bytes_to_human_format(
(data.iter().fold(0, |acc, x| acc + x.1) / u64::try_from(data.len()).unwrap()) as i64,
);

BarChart::default()
.block(Block::new().title(format!(
"{name} (avg {avg}/sec - max {})",
bytes_to_human_format(max as i64)
)))
.bar_width(1)
.bar_gap(0)
.bar_style(Style::new().fg(CONFIG.general.accent_color))
.data(data)
.max(max)
}

0 comments on commit 2c82f69

Please sign in to comment.