File Coverage

blib/lib/App/AsciiChart.pm
Criterion Covered Total %
statement 48 50 96.0
branch 5 8 62.5
condition 2 2 100.0
subroutine 6 6 100.0
pod 0 2 0.0
total 61 68 89.7


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