diff --git a/src/fps_counter.rs b/src/fps_counter.rs new file mode 100644 index 0000000..db3d493 --- /dev/null +++ b/src/fps_counter.rs @@ -0,0 +1,29 @@ +pub struct FpsCounter { + frame_count: u64, + last_tick: std::time::Instant, + pub fps: u64, +} + +impl FpsCounter { + pub fn new() -> Self { + Self { + frame_count: 0, + last_tick: std::time::Instant::now(), + fps: 0, + } + } + pub fn tick(&mut self) { + self.frame_count += 1; + if self.last_tick.elapsed().as_secs() >= 1 { + self.fps = self.frame_count; + self.frame_count = 0; + self.last_tick = std::time::Instant::now(); + } + } +} + +impl Default for FpsCounter { + fn default() -> Self { + Self::new() + } +} \ No newline at end of file diff --git a/src/graphics.rs b/src/graphics.rs index 4e929c3..43753a3 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -7,7 +7,7 @@ use ratatui::{ DefaultTerminal, Frame, }; /// Create a vertical bar chart from the temperatures data. -pub fn vertical_barchart(temperatures: &[u32]) -> BarChart { +pub fn vertical_barchart(temperatures: &[u32], terminal_width: u16) -> BarChart { let bars: Vec = temperatures .iter() .enumerate() @@ -15,7 +15,7 @@ pub fn vertical_barchart(temperatures: &[u32]) -> BarChart { .collect(); BarChart::default() .data(BarGroup::default().bars(&bars)) - .bar_width(1) + .bar_width(terminal_width / temperatures.len() as u16) } pub fn vertical_bar(hour: usize, temperature: &u32) -> Bar { diff --git a/src/main.rs b/src/main.rs index 9a85adb..2b13745 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ use tui::Tui; mod graphics; mod drawableVec; - +mod fps_counter; mod algorithm; mod tui; diff --git a/src/tui.rs b/src/tui.rs index 13a0263..947dce9 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -1,13 +1,10 @@ -use std::time::Duration; +use std::{fmt::format, time::Duration}; use color_eyre::{Result, eyre::Ok}; use crossterm::event::{Event, KeyCode, KeyEventKind, MouseEventKind}; use rand::seq::SliceRandom; use ratatui::{ - Terminal, - layout::{Constraint, Layout}, - prelude::CrosstermBackend, - style::Stylize, + layout::{Constraint, Layout, Margin}, prelude::CrosstermBackend, style::Stylize, widgets::Block, Terminal }; use tokio::{ sync::mpsc::{self, UnboundedReceiver, UnboundedSender}, @@ -32,9 +29,11 @@ pub struct Tui { sorting_tx: UnboundedSender, should_exit: bool, vec: Vec, + fps_counter: FpsCounter, } use crate::{ drawableVec::{self, DrawableVec, SortingMessage}, + fps_counter::FpsCounter, graphics::vertical_barchart, }; @@ -50,7 +49,7 @@ impl Tui { let (event_tx, event_rx): (UnboundedSender, UnboundedReceiver) = mpsc::unbounded_channel(); let (sorting_tx, sorting_rx) = mpsc::unbounded_channel(); - let mut vec = (Vec::from_iter(1..100)); + let mut vec = (Vec::from_iter(1..50)); vec.shuffle(&mut rand::rng()); let drawableVec = DrawableVec::new(event_tx.clone(), sorting_rx, vec.clone()); @@ -58,13 +57,14 @@ impl Tui { Ok(Self { terminal, - tick_rate: 20., - frame_rate: 120., + tick_rate: 30., + frame_rate: 60., event_rx, event_tx, sorting_tx, should_exit: false, vec: vec, + fps_counter: FpsCounter::new(), }) } @@ -111,6 +111,7 @@ impl Tui { Message::Tick => Ok(UpdateCommand::None), Message::Render => { self.view()?; + self.fps_counter.tick(); Ok(UpdateCommand::None) } Message::StartSimulation => todo!(), @@ -127,15 +128,18 @@ impl Tui { fn view(&mut self) -> Result<()> { self.terminal.draw(|frame| { - let [title, vertical, horizontal] = Layout::vertical([ - Constraint::Length(1), - ratatui::layout::Constraint::Fill(1), - Constraint::Fill(1), - ]) - .spacing(1) - .areas(frame.area()); + let [title, vertical] = + Layout::vertical([Constraint::Length(1), Constraint::Fill(1)]) + .spacing(1) + .areas(frame.area()); frame.render_widget("Sorting!".bold().into_centered_line(), title); - frame.render_widget(vertical_barchart(&self.vec), horizontal); + frame.render_widget( + vertical_barchart(&self.vec, vertical.inner(Margin::new(10, 0)).width).block( + Block::bordered() + .title(format!(" Esc to Quit. FPS: {} ", self.fps_counter.fps)), + ), + vertical, + ); })?; Ok(())