use crate::state::State;
use crate::stats::Stats;
use std::net::IpAddr;
struct SymbolTableElement {
fg: &'static str,
bg: &'static str,
character: &'static str,
}
const GREEN_FG: &str = "\x1b[32m";
const ORANGE_FG: &str = "\x1b[38;5;208m";
const RED_FG: &str = "\x1b[31m";
const BLACK_BG: &str = "\x1b[40m";
const GREEN_BG: &str = "\x1b[42m";
const ORANGE_BG: &str = "\x1b[48;5;208m";
const ERASE_LINE_END: &str = "\x1b[0K";
const RESET: &str = "\x1b[0m";
const CHARS_TABLE: [SymbolTableElement; 25] = [
SymbolTableElement {
fg: GREEN_FG,
bg: BLACK_BG,
character: "▁",
},
SymbolTableElement {
fg: GREEN_FG,
bg: BLACK_BG,
character: "▂",
},
SymbolTableElement {
fg: GREEN_FG,
bg: BLACK_BG,
character: "▃",
},
SymbolTableElement {
fg: GREEN_FG,
bg: BLACK_BG,
character: "▄",
},
SymbolTableElement {
fg: GREEN_FG,
bg: BLACK_BG,
character: "▅",
},
SymbolTableElement {
fg: GREEN_FG,
bg: BLACK_BG,
character: "▆",
},
SymbolTableElement {
fg: GREEN_FG,
bg: BLACK_BG,
character: "▇",
},
SymbolTableElement {
fg: GREEN_FG,
bg: BLACK_BG,
character: "█",
},
SymbolTableElement {
fg: ORANGE_FG,
bg: GREEN_BG,
character: "▁",
},
SymbolTableElement {
fg: ORANGE_FG,
bg: GREEN_BG,
character: "▂",
},
SymbolTableElement {
fg: ORANGE_FG,
bg: GREEN_BG,
character: "▃",
},
SymbolTableElement {
fg: ORANGE_FG,
bg: GREEN_BG,
character: "▄",
},
SymbolTableElement {
fg: ORANGE_FG,
bg: GREEN_BG,
character: "▅",
},
SymbolTableElement {
fg: ORANGE_FG,
bg: GREEN_BG,
character: "▆",
},
SymbolTableElement {
fg: ORANGE_FG,
bg: GREEN_BG,
character: "▇",
},
SymbolTableElement {
fg: ORANGE_FG,
bg: GREEN_BG,
character: "█",
},
SymbolTableElement {
fg: RED_FG,
bg: ORANGE_BG,
character: "▁",
},
SymbolTableElement {
fg: RED_FG,
bg: ORANGE_BG,
character: "▂",
},
SymbolTableElement {
fg: RED_FG,
bg: ORANGE_BG,
character: "▃",
},
SymbolTableElement {
fg: RED_FG,
bg: ORANGE_BG,
character: "▄",
},
SymbolTableElement {
fg: RED_FG,
bg: ORANGE_BG,
character: "▅",
},
SymbolTableElement {
fg: RED_FG,
bg: ORANGE_BG,
character: "▆",
},
SymbolTableElement {
fg: RED_FG,
bg: ORANGE_BG,
character: "▇",
},
SymbolTableElement {
fg: RED_FG,
bg: ORANGE_BG,
character: "█",
},
SymbolTableElement {
fg: RED_FG,
bg: BLACK_BG,
character: "?",
},
];
#[allow(clippy::unusual_byte_groupings)]
const TO_HIDE_LEGEND_ELEMENTS: [u32; 26] = [
0b000_000_000_000_0_000_000_000_000,
0b000_000_000_000_1_000_000_000_000,
0b000_000_001_000_0_000_100_000_000,
0b000_000_100_000_1_000_001_000_000,
0b000_010_000_100_0_001_000_010_000,
0b000_100_010_000_1_000_010_001_000, 0b001_000_100_010_0_010_001_000_100,
0b010_001_000_100_1_001_000_100_010,
0b010_010_001_001_0_100_100_010_010,
0b010_010_010_010_1_010_010_010_010,
0b001_010_100_101_0_101_001_010_100, 0b010_101_010_100_1_001_010_101_010,
0b010_101_010_101_0_101_010_101_010,
0b011_010_101_010_1_010_101_010_110,
0b011_010_101_011_0_110_101_010_110,
0b011_101_011_010_1_010_110_101_110, 0b011_101_101_101_0_101_101_101_110,
0b011_101_110_110_1_011_011_101_110,
0b011_110_111_011_0_110_111_011_110,
0b011_101_111_011_1_110_111_101_110,
0b011_111_011_111_0_111_110_111_110, 0b011_111_110_111_1_111_011_111_110,
0b011_111_111_111_0_111_111_111_110,
0b011_111_111_111_1_111_111_111_110,
0b111_111_111_111_1_111_111_111_110,
0b111_111_111_111_1_111_111_111_111, ];
const LEN_BY_NB_ELEMENT: [u32; 26] = [
139, 133, 128, 122, 117, 111, 105, 100, 94, 88, 83, 78, 72, 66, 60, 55, 50, 44, 38, 32, 27, 21,
16, 10, 4, 0,
];
pub fn print_status_line(target_str: &String, ip: &IpAddr) {
println!("PING {} ({})", target_str, ip);
}
pub fn print_legend_line() {
let nb_cols: u32 = if let Some((w, _)) = term_size::dimensions() {
w as u32
} else {
0
};
let mut index = 0;
while LEN_BY_NB_ELEMENT[index] > nb_cols {
index += 1
}
let nb_elements_to_skip = index;
for (index, element) in CHARS_TABLE.iter().enumerate() {
if (TO_HIDE_LEGEND_ELEMENTS[nb_elements_to_skip]) & (1 << index) != 0 {
continue;
}
print!(
"{} {}{}{}\x1b[0m ",
10 * index,
element.fg,
element.bg,
element.character
);
}
println!("{}", ERASE_LINE_END);
}
pub fn print_ping_line(states: &Vec<State>) {
for state in states {
match state {
State::Received { rtt, .. } => {
let (fg, bg, symbol) = get_symbol_and_colors_for_rrt(*rtt);
print!("{}{}{}{}", fg, bg, symbol, RESET);
}
State::Lost => {
let (fg, bg, symbol) = get_symbol_and_colors_for_rrt(250);
print!("{}{}{}{}", fg, bg, symbol, RESET);
}
State::NotYetReceived { .. } => {
print!("\x1b[35;40m?\x1b[0m");
}
State::SendError => {
print!("!");
}
}
}
println!("{}", ERASE_LINE_END);
}
fn get_symbol_and_colors_for_rrt(rrt: u64) -> (&'static str, &'static str, &'static str) {
let index: usize = if rrt >= 240 { 24 } else { rrt / 10 } as usize;
let SymbolTableElement { fg, bg, character } = CHARS_TABLE[index];
(fg, bg, character)
}
pub fn print_stats(stats: &Stats) {
let total = stats.lost + stats.received;
let percent_lost = if total > 0 {
(stats.lost as f64 / total as f64) * 100.0
} else {
0.0
};
let mad_rtt_rounded = stats.mad_rtt.round() as u64;
let mean_rtt_round = stats.avg_rtt.round() as u32;
println!(
"{}/{} ({:.1}%) | ⌊{}⌋ ⌈{}⌉ [{}] [Δ{}]ms{}",
stats.lost,
total,
percent_lost,
stats.min_rtt,
stats.max_rtt,
mean_rtt_round,
mad_rtt_rounded,
ERASE_LINE_END
);
}