aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakobst1n <jakob.stendahl@outlook.com>2024-06-12 01:09:07 +0200
committerjakobst1n <jakob.stendahl@outlook.com>2024-06-12 01:09:07 +0200
commit68fb5ef079b8c122acde3252b713dd9c89d8aa5f (patch)
tree0bf782aa3578a9ef36ba357b39b2c912f019f082
parent42c249ebe1cbfaac82b8fb349c34e6110d1df89f (diff)
downloadtextgraph-68fb5ef079b8c122acde3252b713dd9c89d8aa5f.tar.gz
textgraph-68fb5ef079b8c122acde3252b713dd9c89d8aa5f.zip
Add attempt at a braille mode
-rw-r--r--src/graph.rs93
-rw-r--r--src/parseopts.rs7
-rw-r--r--tg.17
3 files changed, 92 insertions, 15 deletions
diff --git a/src/graph.rs b/src/graph.rs
index 861478c..1958056 100644
--- a/src/graph.rs
+++ b/src/graph.rs
@@ -41,7 +41,7 @@ impl<T: std::fmt::Display> std::fmt::Display for GraphPixel<T> {
}
/// Available options for how the graph should look
-#[derive(Clone)]
+#[derive(PartialEq, Clone)]
pub enum GraphType {
/// Use only * symbols
Star,
@@ -153,7 +153,11 @@ impl GraphBuilder {
/// If you want to only see the "current state", you should clone first!
pub fn build(&mut self) -> String {
if self.cut_overflow {
- self.keep_tail(self.draw_width);
+ if self.graph_type == GraphType::Braille {
+ self.keep_tail(self.draw_width * 2);
+ } else {
+ self.keep_tail(self.draw_width);
+ }
}
//let min_x = self.x_values.iter().cloned().fold(f64::INFINITY, f64::min);
@@ -184,7 +188,11 @@ impl GraphBuilder {
// Run a second time after axis has been calculated properly
if self.cut_overflow {
- self.keep_tail(self.draw_width);
+ if self.graph_type == GraphType::Braille {
+ self.keep_tail(self.draw_width * 2);
+ } else {
+ self.keep_tail(self.draw_width);
+ }
}
if true {
@@ -199,7 +207,11 @@ impl GraphBuilder {
};
// Scale the data
- let scale_factor = (self.draw_height - 1) as f64 / (max_y - min_y);
+ let mut scale_height = self.draw_height;
+ if self.graph_type == GraphType::Braille {
+ scale_height = self.draw_height * 3;
+ }
+ let scale_factor = (scale_height - 1) as f64 / (max_y - min_y);
for i in 0..self.y_values.len() {
self.y_values[i] = ((self.y_values[i] - min_y) * scale_factor).round();
}
@@ -217,13 +229,23 @@ impl GraphBuilder {
// with the x values.
// Make sure to only use one downsampling-algorithm
fn downsample(&mut self) {
- let factor = self.y_values.len() as f64 / self.draw_width as f64;
- let mut new_values = Vec::with_capacity(self.draw_width);
- for i in 0..self.draw_width {
- let new_value = self.y_values[(i as f64 * factor) as usize];
- new_values.push(new_value);
+ if self.graph_type == GraphType::Braille {
+ let factor = self.y_values.len() as f64 / (self.draw_width as f64 * 2.0);
+ let mut new_values = Vec::with_capacity(self.draw_width * 2);
+ for i in 0..self.draw_width * 2 {
+ let new_value = self.y_values[(i as f64 * factor) as usize];
+ new_values.push(new_value);
+ }
+ self.y_values = new_values;
+ } else {
+ let factor = self.y_values.len() as f64 / self.draw_width as f64;
+ let mut new_values = Vec::with_capacity(self.draw_width);
+ for i in 0..self.draw_width {
+ let new_value = self.y_values[(i as f64 * factor) as usize];
+ new_values.push(new_value);
+ }
+ self.y_values = new_values;
}
- self.y_values = new_values;
}
/// Turn canvas into a string
@@ -370,7 +392,56 @@ impl GraphBuilder {
/// Draw a graph using * for the pixels of the graph
fn draw_braille(&mut self) {
- unimplemented!("The braille mode is not implemented");
+ let mut i = 0;
+ let mut x = 0;
+ while i < self.y_values.len() - 1 {
+ let y1 = (self.draw_height * 3) - (self.y_values[i] as usize) - 1;
+ let y1_abs = y1 / 3;
+ let y2 = (self.draw_height * 3) - (self.y_values[i + 1] as usize) - 1;
+ let y2_abs = y2 / 3;
+
+ if y1_abs == y2_abs {
+ let px = match (y1 % 3, y2 % 3) {
+ (0, 0) => ' ',
+ (0, 1) => '⠠',
+ (0, 2) => '⠐',
+ (0, 3) => '⠈',
+ (1, 0) => '⠄',
+ (1, 1) => '⠤',
+ (1, 2) => '⠔',
+ (1, 3) => '⠌',
+ (2, 0) => '⠂',
+ (2, 1) => '⠢',
+ (2, 2) => '⠒',
+ (2, 3) => '⠊',
+ (3, 0) => '⠁',
+ (3, 1) => '⠡',
+ (3, 2) => '⠑',
+ (3, 3) => '⠉',
+ _ => '?',
+ };
+ self.draw(x, y1_abs, GraphPixel::Normal(px));
+ } else {
+ let px = match y1 % 3 {
+ 0 => ' ',
+ 1 => '⠄',
+ 2 => '⠂',
+ 3 => '⠁',
+ _ => '?',
+ };
+ self.draw(x, y1_abs, GraphPixel::Normal(px));
+ let px = match y2 % 3 {
+ 0 => ' ',
+ 1 => '⠠',
+ 2 => '⠐',
+ 3 => '⠈',
+ _ => '?',
+ };
+ self.draw(x, y2_abs, GraphPixel::Normal(px));
+ }
+ i += 2;
+ x += 1;
+ }
}
}
diff --git a/src/parseopts.rs b/src/parseopts.rs
index 9cb1c7e..7d5d760 100644
--- a/src/parseopts.rs
+++ b/src/parseopts.rs
@@ -65,7 +65,7 @@ impl OptsBuilder {
macro_rules! parseopts_panic {
($progname:expr) => {
println!(
- "Usage: {} [-h|--height <height>] [-w|--width <width>] [-t <star|ascii>]",
+ "Usage: {} [-h|--height <height>] [-w|--width <width>] [-t <star|ascii|braille>]",
$progname
);
std::process::exit(1);
@@ -100,7 +100,7 @@ pub fn parseopt(opts: &mut OptsBuilder, arg: &str, value: Option<String>, progna
}
t => {
println!(
- "Unknown type \"{}\", valid options are \"star\", \"ascii\".",
+ "Unknown type \"{}\", valid options are \"star\", \"ascii\" and \"braille\".",
t
);
parseopts_panic!(progname);
@@ -135,6 +135,9 @@ pub fn parseopt(opts: &mut OptsBuilder, arg: &str, value: Option<String>, progna
"a" | "ascii" => {
opts.graph_type = GraphType::Ascii;
}
+ "b" | "braille" => {
+ opts.graph_type = GraphType::Braille;
+ }
"c" | "cut" => {
opts.cut = true;
}
diff --git a/tg.1 b/tg.1
index 3afffbf..b46afd6 100644
--- a/tg.1
+++ b/tg.1
@@ -20,11 +20,14 @@ Disable distracting elements, such as axis and non-graph text.
Shorthand for -t ascii, if multiple options setting mode is specified,
the last will likely be respected.
+.IP "\fB-b, --braille\fR"
+Shorthand for -t braille, if multiple options setting mode is specified,
+the last will likely be respected.
+
.IP "\fB-n, --last-n\fR \fIcount\fR"
If specified, only the newest \fIcount\fR samples will be plotted.
This can be useful if you want to follow the latest state of a graph that is piped in.
-
.IP "\fB-c, --cut\fR"
This is a special case of \fB--last-n\fR. Where the number of columns
\fB--width\fI will be used for the count.
@@ -32,7 +35,7 @@ This is a special case of \fB--last-n\fR. Where the number of columns
.IP "\fB-t\fR \fItype\fR"
The type of graph to draw,
it defaults to \fBstar\fR, which is the fastest one.
-Options are \fBstar\fR and \fBascii\fR.
+Options are \fBstar\fR, \fBascii\fR and \fBbraille\fR.
Ascii is slightly prettier to look at.
.IP "\fB-w, --width\fR \fIwidth\fR"