Browse Source

Reuse code for printing scale info

log-scale
JuanLeon Lahoz 4 years ago
parent
commit
624577411e
  1. 77
      src/format/mod.rs
  2. 22
      src/plot/histogram.rs
  3. 17
      src/plot/matchbar.rs
  4. 14
      src/plot/splittimehist.rs
  5. 17
      src/plot/terms.rs
  6. 16
      src/plot/timehist.rs

77
src/format/mod.rs

@ -1,7 +1,12 @@
use std::fmt;
use std::ops::Range;
use yansi::Color::{Blue, Green, Red};
use yansi::Paint;
// Units-based suffixes for human formatting.
const UNITS: &[&str] = &["", " K", " M", " G", " T", " P", " E", " Z", " Y"];
pub static BAR_CHAR: &str = "∎";
#[derive(Debug)]
pub struct F64Formatter {
@ -63,9 +68,46 @@ impl F64Formatter {
}
}
pub struct HorizontalScale {
/// How many units are represented by a char
scale: usize,
}
impl HorizontalScale {
pub fn new(scale: usize) -> HorizontalScale {
HorizontalScale {
scale: 1.max(scale),
}
}
pub fn get_bar(&self, units: usize) -> Paint<String> {
Red.paint(format!("{:∎<width$}", "", width = units / self.scale))
}
pub fn get_count(&self, units: usize, width: usize) -> Paint<String> {
Green.paint(format!("{:width$}", units, width = width))
}
pub fn get_scale(&self) -> usize {
self.scale
}
}
impl fmt::Display for HorizontalScale {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
writeln!(
formatter,
"Each {} represents a count of {}",
Red.paint(BAR_CHAR),
Blue.paint(self.scale.to_string()),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use yansi::Paint;
#[test]
fn test_basic_format() {
@ -155,4 +197,39 @@ mod tests {
"-0.0 M"
);
}
#[test]
fn test_horizontal_scale() {
Paint::disable();
assert_eq!(
format!("{}", HorizontalScale::new(123)),
format!("Each {BAR_CHAR} represents a count of 123\n")
);
}
#[test]
fn test_horizontal_scale_with_zero_scale() {
Paint::disable();
let scale = HorizontalScale::new(0);
assert_eq!(scale.get_scale(), 1);
assert_eq!(
format!("{}", scale),
format!("Each {BAR_CHAR} represents a count of 1\n")
);
}
#[test]
fn test_horizontal_scale_bar() {
let scale = HorizontalScale::new(10);
assert_eq!(
scale.get_bar(80),
Red.paint(format!("{:∎<width$}", "", width = 8))
);
}
#[test]
fn test_horizontal_scale_count() {
let scale = HorizontalScale::new(10);
assert_eq!(scale.get_count(80, 5), Green.paint(format!(" 80")));
}
}

22
src/plot/histogram.rs

@ -1,9 +1,9 @@
use std::fmt;
use std::ops::Range;
use yansi::Color::{Blue, Green, Red};
use yansi::Color::Blue;
use crate::format::F64Formatter;
use crate::format::{F64Formatter, HorizontalScale};
use crate::stats::Stats;
#[derive(Debug)]
@ -130,15 +130,11 @@ impl HistWriter {
pub fn write(&self, f: &mut fmt::Formatter, hist: &Histogram) -> fmt::Result {
let width_range = self.get_width(hist);
let width_count = ((hist.top as f64).log10().ceil() as usize).max(1);
let divisor = 1.max(hist.top / self.get_max_bar_len(width_range + width_count));
writeln!(
f,
"each {} represents a count of {}",
Red.paint("∎"),
Blue.paint(divisor.to_string()),
)?;
let horizontal_scale =
HorizontalScale::new(hist.top / self.get_max_bar_len(width_range + width_count));
writeln!(f, "{}", horizontal_scale)?;
for x in hist.vec.iter() {
self.write_bucket(f, x, divisor, width_range, width_count)?;
self.write_bucket(f, x, &horizontal_scale, width_range, width_count)?;
}
Ok(())
}
@ -147,7 +143,7 @@ impl HistWriter {
&self,
f: &mut fmt::Formatter,
bucket: &Bucket,
divisor: usize,
horizontal_scale: &HorizontalScale,
width: usize,
width_count: usize,
) -> fmt::Result {
@ -160,8 +156,8 @@ impl HistWriter {
self.formatter.format(bucket.range.end),
width = width,
)),
count = Green.paint(format!("{:width$}", bucket.count, width = width_count)),
bar = Red.paint(format!("{:∎<width$}", "", width = bucket.count / divisor)),
count = horizontal_scale.get_count(bucket.count, width_count),
bar = horizontal_scale.get_bar(bucket.count)
)
}

17
src/plot/matchbar.rs

@ -1,6 +1,8 @@
use std::fmt;
use yansi::Color::{Blue, Green, Red};
use yansi::Color::Blue;
use crate::format::HorizontalScale;
#[derive(Debug)]
/// A struct that represents a single match bar of a match bar histogram (a
@ -54,7 +56,7 @@ impl MatchBar {
impl fmt::Display for MatchBar {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let width = f.width().unwrap_or(100);
let divisor = 1.max(self.top_values / width);
let horizontal_scale = HorizontalScale::new(self.top_values / width);
let width_count = format!("{}", self.top_values).len();
writeln!(
f,
@ -64,19 +66,14 @@ impl fmt::Display for MatchBar {
self.vec.iter().map(|r| r.count).sum::<usize>()
)),
)?;
writeln!(
f,
"Each {} represents a count of {}",
Red.paint("∎"),
Blue.paint(divisor.to_string()),
)?;
writeln!(f, "{}", horizontal_scale)?;
for row in self.vec.iter() {
writeln!(
f,
"[{label}] [{count}] {bar}",
label = Blue.paint(format!("{:width$}", row.label, width = self.top_lenght)),
count = Green.paint(format!("{:width$}", row.count, width = width_count)),
bar = Red.paint(format!("{:∎<width$}", "", width = row.count / divisor))
count = horizontal_scale.get_count(row.count, width_count),
bar = horizontal_scale.get_bar(row.count)
)?;
}
Ok(())

14
src/plot/splittimehist.rs

@ -3,6 +3,7 @@ use std::fmt;
use chrono::{DateTime, Duration, FixedOffset};
use yansi::Color::{Blue, Cyan, Green, Magenta, Red};
use crate::format::{HorizontalScale, BAR_CHAR};
use crate::plot::date_fmt_string;
const COLORS: &[yansi::Color] = &[Red, Blue, Magenta, Green, Cyan];
@ -134,7 +135,7 @@ impl SplitTimeHistogram {
write!(
f,
"{}",
COLORS[i].paint("∎".repeat(row.count[i] / divisor).to_string())
COLORS[i].paint(BAR_CHAR.repeat(row.count[i] / divisor).to_string())
)?;
}
writeln!(f)
@ -146,7 +147,7 @@ impl fmt::Display for SplitTimeHistogram {
let width = f.width().unwrap_or(100);
let total = self.vec.iter().map(|r| r.total()).sum::<usize>();
let top = self.vec.iter().map(|r| r.total()).max().unwrap_or(1);
let divisor = 1.max(top / width);
let horizontal_scale = HorizontalScale::new(top / width);
// These are the widths of every count column
let widths: Vec<usize> = (0..self.strings.len())
.map(|i| {
@ -163,15 +164,10 @@ impl fmt::Display for SplitTimeHistogram {
let total = self.vec.iter().map(|r| r.count[i]).sum::<usize>();
writeln!(f, "{}: {}.", COLORS[i].paint(s), total)?;
}
writeln!(
f,
"Each {} represents a count of {}",
Red.paint("∎"),
divisor
)?;
writeln!(f, "{}", horizontal_scale)?;
let ts_fmt = date_fmt_string(self.step.num_seconds());
for row in self.vec.iter() {
self.fmt_row(f, row, divisor, &widths, ts_fmt)?;
self.fmt_row(f, row, horizontal_scale.get_scale(), &widths, ts_fmt)?;
}
Ok(())
}

17
src/plot/terms.rs

@ -1,7 +1,9 @@
use std::collections::HashMap;
use std::fmt;
use yansi::Color::{Blue, Green, Red};
use yansi::Color::Blue;
use crate::format::HorizontalScale;
#[derive(Debug)]
/// A struct holding data to plot a Histogram of the most frequent terms in an
@ -42,21 +44,16 @@ impl fmt::Display for CommonTerms {
counts.sort_by(|a, b| b.1.cmp(a.1));
let values = &counts[..self.lines.min(counts.len())];
let label_width = values.iter().fold(1, |acc, x| acc.max(x.0.len()));
let divisor = 1.max(counts[0].1 / width);
let horizontal_scale = HorizontalScale::new(counts[0].1 / width);
let width_count = format!("{}", counts[0].1).len();
writeln!(
f,
"Each {} represents a count of {}",
Red.paint("∎"),
Blue.paint(divisor.to_string()),
)?;
writeln!(f, "{}", horizontal_scale)?;
for (term, count) in values.iter() {
writeln!(
f,
"[{label}] [{count}] {bar}",
label = Blue.paint(format!("{:>width$}", term, width = label_width)),
count = Green.paint(format!("{:width$}", count, width = width_count)),
bar = Red.paint(format!("{:∎<width$}", "", width = *count / divisor))
count = horizontal_scale.get_count(**count, width_count),
bar = horizontal_scale.get_bar(**count)
)?;
}
Ok(())

16
src/plot/timehist.rs

@ -1,8 +1,9 @@
use std::fmt;
use chrono::{DateTime, Duration, FixedOffset};
use yansi::Color::{Blue, Green, Red};
use yansi::Color::Blue;
use crate::format::HorizontalScale;
use crate::plot::date_fmt_string;
#[derive(Debug)]
@ -97,7 +98,7 @@ impl TimeHistogram {
impl fmt::Display for TimeHistogram {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let width = f.width().unwrap_or(100);
let divisor = 1.max(self.top / width);
let horizontal_scale = HorizontalScale::new(self.top / width);
let width_count = format!("{}", self.top).len();
writeln!(
f,
@ -107,20 +108,15 @@ impl fmt::Display for TimeHistogram {
self.vec.iter().map(|r| r.count).sum::<usize>()
)),
)?;
writeln!(
f,
"Each {} represents a count of {}",
Red.paint("∎"),
Blue.paint(divisor.to_string()),
)?;
writeln!(f, "{}", horizontal_scale)?;
let ts_fmt = date_fmt_string(self.step.num_seconds());
for row in self.vec.iter() {
writeln!(
f,
"[{label}] [{count}] {bar}",
label = Blue.paint(format!("{}", row.start.format(ts_fmt))),
count = Green.paint(format!("{:width$}", row.count, width = width_count)),
bar = Red.paint(format!("{:∎<width$}", "", width = row.count / divisor))
count = horizontal_scale.get_count(row.count, width_count),
bar = horizontal_scale.get_bar(row.count)
)?;
}
Ok(())

Loading…
Cancel
Save