use crate::frontend::tui_app::TuiApp;
use crate::t;
use ratatui::layout::Rect;
use ratatui::style::{Modifier, Style};
use ratatui::widgets::{BarChart, Block, BorderType, Borders};
use ratatui::Frame;
use std::collections::BTreeMap;
use std::time::Duration;
pub fn render(f: &mut Frame<'_>, app: &TuiApp, rect: Rect) {
let selected_hop = app.selected_hop_or_target();
let freq_data = sample_frequency(selected_hop.samples());
let freq_data_ref: Vec<_> = freq_data.iter().map(|(b, c)| (b.as_str(), *c)).collect();
let barchart = BarChart::default()
.block(
Block::default()
.title(format!("{} #{}", t!("title_frequency"), selected_hop.ttl()))
.style(
Style::default()
.bg(app.tui_config.theme.bg)
.fg(app.tui_config.theme.text),
)
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.border_style(Style::default().fg(app.tui_config.theme.border)),
)
.data(freq_data_ref.as_slice())
.bar_width(4)
.bar_gap(1)
.bar_style(Style::default().fg(app.tui_config.theme.frequency_chart_bar))
.value_style(
Style::default()
.bg(app.tui_config.theme.frequency_chart_bar)
.fg(app.tui_config.theme.frequency_chart_text)
.add_modifier(Modifier::BOLD),
);
f.render_widget(barchart, rect);
}
fn sample_frequency(samples: &[Duration]) -> Vec<(String, u64)> {
let sample_count = samples.len();
let mut count_by_duration: BTreeMap<u128, u64> = BTreeMap::new();
for sample in samples {
if !sample.is_zero() {
*count_by_duration.entry(sample.as_millis()).or_default() += 1;
}
}
count_by_duration
.iter()
.map(|(ping, count)| {
let ping = format!("{ping}");
let freq_pct = ((*count as f64 / sample_count as f64) * 100_f64) as u64;
(ping, freq_pct)
})
.collect()
}