use super::buffers::Buffers;
use crate::router::Message;
use crate::tui::Frame;
use itertools::Itertools;
use itertools::MinMaxResult::{MinMax, NoElements, OneElement};
use ratatui::{
prelude::*,
widgets::{Axis, Block, Borders, Chart, Dataset},
};
use ringbuffer::RingBuffer;
use tokio::sync::mpsc;
#[derive(Debug)]
pub struct RenderFps {
pub message_tx_to_self: mpsc::UnboundedSender<Message>, }
impl RenderFps {
pub fn chart(data: &Vec<(f64, f64)>) -> Chart<'_> {
let current_fps = match data.first() {
Some((_, x)) => *x,
None => 0.0,
};
let (min_fps, max_fps) = match data.iter().map(|(_i, x)| x).minmax() {
NoElements => (0.0, 0.0),
MinMax(min, max) => (*min, *max),
OneElement(x) => (0.0, *x),
};
Chart::new(vec![Dataset::default()
.name("FPS")
.marker(symbols::Marker::Braille)
.style(Style::default().fg(Color::Green))
.data(data)])
.block(
Block::default()
.title("Render frames per second".bold())
.borders(Borders::ALL),
)
.x_axis(
Axis::default()
.style(Style::default().fg(Color::Gray))
.bounds([0.0, data.len() as f64]),
)
.y_axis(
Axis::default()
.style(Style::default().fg(Color::Gray))
.labels(vec![
if min_fps < current_fps {
format!("{min_fps:.4}").not_bold()
} else {
format!("{min_fps:.4}").bold().light_yellow()
},
format!("{current_fps:.4}").bold(),
if max_fps > current_fps {
format!("{max_fps:.4}").not_bold()
} else {
format!("{max_fps:.4}").bold().light_green()
},
])
.bounds([0.99 * min_fps, 1.01 * max_fps]),
)
}
fn layer(area: Rect) -> Rect {
area
}
pub fn render(actions: &Buffers, area: Rect, f: &mut Frame<'_>) {
let layer = Self::layer(area);
let data = actions
.render_fps
.iter()
.rev()
.enumerate()
.map(|(x, &y)| (x as f64, y))
.collect::<Vec<(f64, f64)>>();
f.render_widget(Self::chart(&data), layer);
}
}