File Coverage

blib/lib/App/AsciiChart.pm
Criterion Covered Total %
statement 46 48 95.8
branch 5 8 62.5
condition n/a
subroutine 6 6 100.0
pod 0 2 0.0
total 57 64 89.0


line stmt bran cond sub pod time code
1             package App::AsciiChart;
2 2     2   67849 use 5.008001;
  2         18  
3 2     2   14 use strict;
  2         5  
  2         40  
4 2     2   9 use warnings;
  2         5  
  2         57  
5 2     2   10 use List::Util qw(min max);
  2         4  
  2         1107  
6              
7             our $VERSION = "0.03";
8              
9             sub new {
10 1     1 0 1183 my $class = shift;
11              
12 1         11 my $self = {};
13 1         5 bless $self, $class;
14              
15 1         3 return $self;
16             }
17              
18             sub plot {
19 1     1 0 7 my $self = shift;
20 1         2 my ($series) = @_;
21              
22 1         4 my $min = min @$series;
23 1         3 my $max = max @$series;
24              
25 1         3 my $padding = length $max;
26              
27 1         8 my $range = abs( $min - $max );
28              
29 1         3 my $height = $range;
30 1         4 my $ratio = $height / $range;
31              
32 1         3 my $min2 = int( $min * $ratio );
33 1         2 my $max2 = int( $max * $ratio );
34 1         2 my $rows = abs( $max2 - $min2 );
35              
36 1         3 my $result = [];
37              
38 1         3 for ( 0 .. $rows ) {
39 3         6 push @$result, [ '.', map { '.' } @$series ];
  9         18  
40             }
41              
42 1         3 for my $row ( 0 .. $rows ) {
43 3 100       18 $result->[$row]->[0] =
44             ( sprintf "%${padding}s", $max2 - $ratio * $row )
45             . ( $row == $rows - int( $series->[0] * $ratio ) + $min2
46             ? '┼'
47             : '┤' );
48              
49 3         16 for ( my $x = 0 ; $x < @$series - 1 ; $x++ ) {
50 6         11 my $y0 = int( $series->[$x] * $ratio ) - $min2;
51 6         28 my $y1 = int( $series->[ $x + 1 ] * $ratio ) - $min2;
52              
53 6 50       12 if ( $y0 == $y1 ) {
54 0         0 $result->[ $rows - $y0 ]->[ $x + 1 ] = '─';
55             }
56             else {
57 6 50       14 $result->[ $rows - $y1 ]->[ $x + 1 ] =
58             ( $y0 > $y1 ) ? '╰' : '╭';
59 6 50       12 $result->[ $rows - $y0 ]->[ $x + 1 ] =
60             ( $y0 > $y1 ) ? '╮' : '╯';
61              
62 6         11 my $from = min( $y0, $y1 );
63 6         9 my $to = max( $y0, $y1 );
64              
65 6         20 for ( my $y = $from + 1 ; $y < $to ; $y++ ) {
66 0         0 $result->[ $rows - $y ]->[ $x + 1 ] = '│';
67             }
68             }
69             }
70             }
71              
72 1         3 my $plot = '';
73              
74 1         2 foreach my $line (@$result) {
75 3         6 $plot .= join '', @$line;
76 3         6 $plot .= "\n";
77             }
78              
79 1         4 return $plot;
80             }
81              
82             1;
83             __END__