File Coverage

blib/lib/Schedule/Activity/Annotation.pm
Criterion Covered Total %
statement 71 74 95.9
branch 26 30 86.6
condition 10 21 47.6
subroutine 7 7 100.0
pod 0 3 0.0
total 114 135 84.4


line stmt bran cond sub pod time code
1             package Schedule::Activity::Annotation;
2              
3 2     2   6469 use strict;
  2         5  
  2         70  
4 2     2   9 use warnings;
  2         3  
  2         103  
5 2     2   1951 use Ref::Util qw/is_hashref is_regexpref is_ref/;
  2         3016  
  2         203  
6 2     2   13 use Scalar::Util qw/looks_like_number/;
  2         6  
  2         2337  
7              
8             our $VERSION='0.3.0';
9              
10             my %property=map {$_=>undef} qw/message nodes before between p limit attributes note/;
11              
12             sub new {
13 2850     2850 0 23750 my ($ref,%opt)=@_;
14 2850   33     12826 my $class=is_ref($ref)||$ref;
15 2850         10016 return bless(\%opt,$class);
16             }
17              
18             sub validate {
19 20     20 0 302389 my (%node)=@_;
20 20         34 my @errors;
21 20         53 foreach my $k (grep {!exists($property{$_})} keys(%node)) { push @errors,"Invalid key: $k" }
  60         141  
  1         3  
22 20 100       64 if(!defined($node{message})) { push @errors,'Expected: message' }
  2         3  
23 20 100       67 if(!is_regexpref($node{nodes})) { push @errors,'Expected regexp: nodes' }
  4         6  
24 20         37 foreach my $k (grep {defined($node{$_})} qw/between p limit/) {
  60         117  
25 14 100       77 if(!looks_like_number($node{$k})) { push @errors,"Invalid value: $k" }
  3 100       6  
26 3         26 elsif($node{$k}<0) { push @errors,"Negative value: $k" }
27             }
28 20   100     94 $node{before}//={};
29 20 100       47 if(!is_hashref($node{before})) { push @errors,'Before invalid structure' }
  1         3  
30 19         34 else { foreach my $k (grep {defined($node{before}{$_})} qw/min max/) {
  38         83  
31 16 100       64 if(!looks_like_number($node{before}{$k})) { push @errors,"Invalid value: before{$k}" }
  2         8  
32             } }
33 20         124 return @errors;
34             }
35              
36             sub annotate {
37 2850     2850 0 8963 my ($self,@schedule)=@_;
38 2850   50     5575 my %before=%{$$self{before}//{}};
  2850         15967  
39             my %opt=(
40             p =>$$self{p}//1,
41             beforemin=>$before{min}//$before{max}//1,
42             beforemax=>$before{max}//$before{min}//1,
43 2850   100     28957 between =>$$self{between}//1,
      33        
      0        
      33        
      0        
      100        
44             );
45 2850         9163 my @matchidx=grep {rand()<=$opt{p}} grep {$schedule[$_][1]{keyname}=~$$self{nodes}} (0..$#schedule);
  14182         34341  
  34121         146654  
46 2850 100       9144 if(!@matchidx) { return }
  4         57  
47 2846         5241 my @notes;
48 2846         6701 foreach my $i (@matchidx) {
49 14182         45039 my @tmwindow=sort {$a<=>$b} ($schedule[$i][0]-$opt{beforemax},$schedule[$i][0]-$opt{beforemin});
  14182         32370  
50 14182 100       31394 if($i>0) { my $tm=$schedule[$i-1][0]+1; if($tmwindow[0]<=$tm) { $tmwindow[0]=$tm } }
  14182 50       27856  
  14182         29927  
  14163         27382  
51 14182 50       30211 if($i<$#schedule) { my $tm=$schedule[$i+1][0]-1; if($tmwindow[1]>=$tm) { $tmwindow[1]=$tm } }
  14181 100       27264  
  14181         31824  
  0         0  
52 14182 50       29330 if($tmwindow[1]>=$tmwindow[0]) { push @notes,[@tmwindow] }
  14182         39643  
53             }
54 2846 100       7984 if($$self{limit}) { while(1+$#notes>$$self{limit}) {
  4         23  
55 3         14 my $idx=int(rand(1+$#notes)); splice(@notes,$idx,1) } }
  3         15  
56 2846         9452 for(my $i=1;$i<=$#notes;$i++) { ## no critic (CStyleForLoops)
57 11333 100       48803 if($notes[$i][0]-$notes[$i-1][0]<$opt{between}) {
58 2 50       7 if($notes[$i][1]-$notes[$i-1][0]<$opt{between}) { splice(@notes,$i,1); $i-- }
  0         0  
  0         0  
59 2         8 else { $notes[$i][0]=$notes[$i-1][0]+$opt{between} }
60             }
61             }
62 2846         6247 return map {[$$_[0], {map {$_=>$$self{$_}} grep {$$self{$_}} qw/message attributes/}]} @notes;
  14179         25226  
  14180         73078  
  28358         54279  
63             }
64              
65             1;
66              
67             __END__