Skip to content

Commit

Permalink
Added Horizontal graph
Browse files Browse the repository at this point in the history
- refactored comment stuff out into core
- renamed test & tester to be vertical specific
- added horizontal_tester.raku
- added Horizontal.rakumod
- added 02-horizontal.rakutest
  • Loading branch information
masukomi committed Feb 4, 2023
1 parent 6b35f85 commit b71bed8
Show file tree
Hide file tree
Showing 8 changed files with 314 additions and 82 deletions.
2 changes: 2 additions & 0 deletions META6.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
"name": "CLI::Graphing::BarChart",
"perl": "6.d",
"provides": {
"CLI::Graphing::BarChart::Core": "lib/CLI/Graphing/BarChart/Core.rakumod",
"CLI::Graphing::BarChart::Horizontal": "lib/CLI/Graphing/BarChart/Horizontal.rakumod",
"CLI::Graphing::BarChart::Vertical": "lib/CLI/Graphing/BarChart/Vertical.rakumod"
},
"resources": [
Expand Down
43 changes: 43 additions & 0 deletions horizontal-graph-tester.raku
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env raku

use lib 'lib';
use CLI::Graphing::BarChart::Horizontal;


say "X and Y axis\n";
my $x_and_y_axis_graph = CLI::Graphing::BarChart::Horizontal.new(
data => [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
graph_height => 10,
x_axis_labels => <a b c d e f g h i j>,
y_axis_labels => <0 1 2 3 4 5 6 7 8 9 10>
);

$x_and_y_axis_graph.print();


say "\n\nJust Y axis\n";
my $y_axis_graph = CLI::Graphing::BarChart::Horizontal.new(
data => [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
graph_height => 10,
y_axis_labels => <0 1 2 3 4 5 6 7 8 9 10 11>,
);
$y_axis_graph.print();


say "\n\nWide Y axis labels\n";
$x_and_y_axis_graph = CLI::Graphing::BarChart::Horizontal.new(
data => [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
graph_height => 10,
x_axis_labels => <a b c d e f g h i j >,
y_axis_labels => <alpha bravo charlie delta echo foxtrot golf hotel india juliet kilo>,
);
$x_and_y_axis_graph.print();

say "\n\nInsufficent Wide Y axis labels\n";
$x_and_y_axis_graph = CLI::Graphing::BarChart::Horizontal.new(
data => [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
graph_height => 10,
x_axis_labels => <a b c d e f g h i j>,
y_axis_labels => <alpha bravo charlie delta echo foxtrot golf hotel >,
);
$x_and_y_axis_graph.print();
65 changes: 65 additions & 0 deletions lib/CLI/Graphing/BarChart/Core.rakumod
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
class CLI::Graphing::BarChart::Core {
use Listicles;
has $.data;
has $.bar_length is rw = 10;
has $.y_axis_labels is rw = [];
has $.x_axis_labels is rw = [];
# has $.bar_drawing_character = '█';

# Implement these in subclasses
method generate(){...}

#| Prints the graph to standard out.
method print() {
say self.generate();
}

method validate-bar-length() {
unless $!bar_length {
die("You must specify a bar_length (number of lines for the core graph).");
}
}

# each row is an array of the characters that make up that row
method generate-core-graph(Array $data,
Int $bar_length,
Str $bar_element_character
) returns Array {

my @rows = [];
for $data.pairs -> $pair {
my $num_chars = $pair.value * ($bar_length / 100);

my $bar_chars = ($bar_element_character x $num_chars);
my @new_row = $bar_length == 1
?? $bar_chars.split('', skip-empty => True).Array
!! self.pad-with-x-array($bar_chars, $bar_length);

# remember, the graph is sideways, so the x axis is currently on the left
# if it's not there we don't do anything
# if it is there we prepend to the left side of the row
@rows.push: @new_row;
}
return @rows;
}
# pads the string you passed in with spaces up to $width
method pad-with-space(Str $string, Int $width, Bool $pad_right=True) returns Str {
return $string if $string.chars >= $width;

return sprintf('%-' ~ $width ~ 's', $string) if $pad_right;
return sprintf('%' ~ $width ~ 's', $string);
}
# method !pad-with-x-array(Str $string, Int $width, Str $padding_char=' ') returns Array {
method pad-with-x-array(Str $string,
Int $width,
Str $padding_char=' ',
Bool $pad_right = True) returns Array {
my @response = $string.split('', skip-empty => True).Array;
return @response if @response.elems >= $width;
if $pad_right {
return @response.append($padding_char xx $width - @response.elems);
}
return ($padding_char xx $width - @response.elems).Array.append: @response;
}

}
90 changes: 90 additions & 0 deletions lib/CLI/Graphing/BarChart/Horizontal.rakumod
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use CLI::Graphing::BarChart::Core;

class CLI::Graphing::BarChart::Horizontal is CLI::Graphing::BarChart::Core {
use Listicles;
# From Core...
# has $.data;
# has $.bar_length;
# has $.y_axis_labels = [];
# has $.x_axis_labels = [];

has $.bar_drawing_character = '';

method generate() returns Str {
self.validate-or-die();


my $rows = self.generate-core-graph($.data, $.bar_length, $.bar_drawing_character);
# X axis labels are just another row
# Y axis labels just get prepended
# 0x0 is top left
# the last row is the x axis labels (if present)
#
# 1. find the length of the longest y_axis_labels
my $max_y_label = $.y_axis_labels.map({.chars}).max;
my $border =[' ', '', ' '];
if $.y_axis_labels {
for (0..^$.data.elems) -> $index {
if $index < $.y_axis_labels.elems {
my $prepension = self.pad-with-x-array($.y_axis_labels[$index],
$max_y_label,
' ',
False);
$rows[$index] = $prepension
.append($border.Array)
.append($rows[$index].Array);
} else {
# they have fewer Y axis items than data points
$rows[$index] = self.pad-with-x-array("",
$max_y_label + 3,
' ',
False
).append($rows[$index].Array);
}
}
if ! $.x_axis_labels.is-empty {
$rows.push(self.pad-with-x-array("",
$max_y_label + 3,
' ',
False
)
.append($.x_axis_labels.Array))
}
} elsif ! $.x_axis_labels.is-empty {
$rows.push($.x_axis_labels)
}

self!join-rows($rows);
}
method !join-rows($rows){
$rows.map({.join('')}).join("\n");
}

method validate-or-die(){
self.validate-bar-length();
if $.x_axis_labels {
self.validate-x-labels($.x_axis_labels);
self.x_axis_labels = $.x_axis_labels.map({.Str}).Array;
}
if $.y_axis_labels {
self.validate-y-labels($.y_axis_labels, $.data);
self.y_axis_labels = $.y_axis_labels.map({.Str}).Array;
}

}
#| either works or dies
method validate-x-labels($x_labels) {
return True unless $x_labels;
my $all_good = $x_labels.all-are(-> $x {$x.chars <= 1 });
die("x labels on horizontal graphs must be 1 or zero characters long") unless $all_good;
if $x_labels.elems > $.bar_length {
die ("You can't have more x labels than characters in the bar_length");
}
}
method validate-y-labels($y_labels, $data){
return True unless $y_labels;
if $y_labels.elems > 0 & $y_labels.elems > $data.elems {
die("You can't have more y labels than data elements.")
}
}
}
Loading

0 comments on commit b71bed8

Please sign in to comment.