File Coverage

blib/lib/Schedule/Activity/Attribute/Report.pm
Criterion Covered Total %
statement 110 111 99.1
branch 32 36 88.8
condition 7 12 58.3
subroutine 10 10 100.0
pod 0 6 0.0
total 159 175 90.8


line stmt bran cond sub pod time code
1             package Schedule::Activity::Attribute::Report;
2              
3 1     1   704 use strict;
  1         3  
  1         41  
4 1     1   5 use warnings;
  1         3  
  1         58  
5 1     1   5 use Scalar::Util qw/looks_like_number/;
  1         2  
  1         149  
6 1     1   8 use Ref::Util qw/is_ref/;
  1         2  
  1         1719  
7              
8             our $VERSION='0.3.0';
9              
10             sub new {
11 2     2 0 7 my ($ref,%schedule)=@_;
12 2   33     10 my $class=is_ref($ref)||$ref;
13 2         6 my %self=%schedule; # shallow
14 2         7 return bless(\%self,$class);
15             }
16              
17             sub gridreport {
18 10     10 0 45 my ($self,%opt)=@_;
19 10   50     27 $opt{steps}//=10;
20 10 100       17 my $yidx=1; if($opt{values} eq 'avg') { $yidx=2 };
  10         23  
  7         12  
21 10         18 my $tmmin=( sort {$a<=>$b} map {$$_{xy}[0][0]} values %{$$self{attributes}})[0];
  10         27  
  20         74  
  10         34  
22 10         22 my $tmmax=(reverse sort {$a<=>$b} map {$$_{xy}[-1][0]} values %{$$self{attributes}})[0];
  10         20  
  20         42  
  10         19  
23 10         31 my $tmstep=($tmmax-$tmmin)/$opt{steps};
24 10         58 my @times=map {$tmmin+$tmstep*$_} (0..$opt{steps});
  111         188  
25 10         20 my @res;
26 10 50       26 if($opt{header}) { push @res,[map {sprintf($opt{fmt},$_)} @times]; if($opt{names}) { push @{$res[-1]},'Attribute' } }
  5 100       11  
  55         204  
  5         21  
  5         11  
  5         18  
27 10         17 foreach my $name (sort keys %{$$self{attributes}}) {
  10         43  
28 20         69 my @row;
29 20         62 my $attr=$$self{attributes}{$name}{xy};
30 20         41 my ($i,$y)=(-1);
31 20         34 foreach my $tm (@times) {
32 222   100     776 while(($i<$#$attr)&&($tm>=$$attr[$i+1][0])) { $i++ }
  1120         3336  
33 222 50       591 if($i<0) { $y=0 }
  0 100       0  
    100          
34 20         33 elsif($i>=$#$attr) { $y=$$attr[$i][$yidx] }
35 21         38 elsif($i==0) { $y=$$attr[0][$yidx] }
36             else {
37 181         389 my $p=($tm-$$attr[$i][0])/($$attr[$i+1][0]-$$attr[$i][0]);
38 181         351 $y=(1-$p)*$$attr[$i][$yidx]+$p*$$attr[$i+1][$yidx];
39             }
40 222         923 push @row,sprintf($opt{fmt},$y);
41             }
42 20 100       51 if($opt{names}) { push @row,$name }
  16         28  
43 20         61 push @res,\@row;
44             }
45 10         75 return @res;
46             }
47              
48             sub summaryreport {
49 6     6 0 22 my ($self,%opt)=@_;
50 6 100       11 my $yidx=1; if($opt{values} eq 'avg') { $yidx=2 };
  6         14  
  3         5  
51 6         8 my @res;
52 6 100       15 if($opt{header}) { push @res,[$opt{values} eq 'avg'?'Average':'Value']; if($opt{names}) { push @{$res[-1]},'Attribute' } }
  2 50       5  
  2 100       4  
  2         3  
  2         6  
53 6         10 foreach my $name (sort keys %{$$self{attributes}}) {
  6         26  
54 12         74 push @res,[sprintf($opt{fmt},$$self{attributes}{$name}{xy}[-1][$yidx])];
55 12 100       23 if($opt{names}) { push @{$res[-1]},$name }
  8         9  
  8         18  
56             }
57 6         1148 return @res;
58             }
59              
60             sub rawhash {
61 1     1 0 4 my ($value,@rows)=@_;
62 1         2 my %res;
63 1         3 my @times=@{shift @rows}; pop(@times);
  1         7  
  1         2  
64 1         3 foreach my $row (@rows) {
65 2         5 my $name=pop(@$row);
66 2         6 foreach my $i (0..$#times) {
67 22         37 my $tm=$times[$i];
68 22         30 my $v=$$row[$i];
69 22         74 $res{$name}{$value}{$tm}=$v;
70             }
71             }
72 1         31 return %res;
73             }
74              
75             sub rawplot {
76 1     1 0 5 my ($sep,@rows)=@_;
77 1         2 my @times=@{shift @rows}; pop(@times);
  1         8  
  1         3  
78 1   50     4 my $res=join($sep,'Time',map {$$_[1+$#times]//''} @rows)."\n";
  2         13  
79 1   50     6 foreach my $i (0..$#times) { $res.=join($sep,$times[$i],map {$$_[$i]//''} @rows)."\n" }
  11         19  
  22         67  
80 1         14 return $res;
81             }
82              
83             sub report {
84 16     16 0 147 my ($self,%opt)=@_;
85 16         134 %opt=(
86             type =>'',
87             values=>'avg',
88             header=>1,
89             names =>1,
90             fmt =>'%0.4g',
91             sep =>"\t",
92             format=>'text',
93             %opt
94             );
95 16 100       86 if($opt{format}=~/^hash/) { $opt{header}=$opt{names}=1 }
  1         3  
96             #
97 16         53 my @rows; # will use dispatch later
98 16 100       57 if ($opt{type} eq 'grid') { @rows=$self->gridreport(%opt) }
  10 50       42  
99 6         20 elsif($opt{type} eq 'summary') { @rows=$self->summaryreport(%opt) }
100             #
101 16 100       71 if ($opt{format} eq 'hash') { return +{rawhash($opt{values},@rows)} }
  1 100       6  
    100          
102 1         16 elsif($opt{format} eq 'table') { return \@rows }
103 1         5 elsif($opt{format} eq 'plot') { return rawplot($opt{sep},@rows) }
104 13         28 else { return join("\n",map {join($opt{sep},@$_)} @rows) }
  30         233  
105             }
106              
107             1;
108              
109             __END__