File Coverage

blib/lib/Sub/Rate.pm
Criterion Covered Total %
statement 45 47 95.7
branch 8 10 80.0
condition n/a
subroutine 9 9 100.0
pod 3 3 100.0
total 65 69 94.2


line stmt bran cond sub pod time code
1             package Sub::Rate;
2 4     4   3206 use strict;
  4         7  
  4         162  
3 4     4   23 use warnings;
  4         7  
  4         126  
4 4     4   2683 use Any::Moose;
  4         124359  
  4         32  
5 4     4   2488 use Carp;
  4         9  
  4         859  
6              
7             our $VERSION = '0.05';
8              
9             has max_rate => (
10             is => 'rw',
11             default => 100,
12             );
13              
14             has rand_func => (
15             is => 'rw',
16             default => sub {
17             return sub { rand($_[0]) };
18             },
19             );
20              
21             has sort => (
22             is => 'rw',
23             default => 0,
24             );
25              
26             has _func => (
27             is => 'rw',
28             default => sub { [] },
29             );
30              
31             has _default_func => (
32             is => 'rw',
33             );
34              
35 4     4   26 no Any::Moose;
  4         10  
  4         73  
36              
37             sub add {
38 11     11 1 983 my ($self, $rate, $func) = @_;
39              
40 11 100       39 if ($rate eq 'default') {
41 1         7 $self->_default_func($func);
42             }
43             else {
44 10         14 my $total_rate = 0;
45 10         15 $total_rate += $_->[0] for @{ $self->_func };
  10         51  
46              
47 10 100       47 if ($total_rate + $rate > $self->max_rate) {
48 1         223 croak sprintf 'Exceed max_rate, current:%s max:%s',
49             $total_rate + $rate, $self->max_rate;
50             }
51              
52 9         14 push @{ $self->_func }, [ $rate, $func ];
  9         45  
53             }
54             }
55              
56             sub generate {
57 3     3 1 17 my ($self) = @_;
58              
59 3         7 my @sorted_funcs = @{ $self->_func };
  3         12  
60 3 50       17 @sorted_funcs = sort { $a->[0] <=> $b->[0] } @sorted_funcs if $self->sort;
  0         0  
61              
62 3         15 my $rand = $self->rand_func;
63 3         12 my $max_rate = $self->max_rate;
64 3         22 my $default_func = $self->_default_func;
65              
66             sub {
67 200100     200100   771342 my @args = @_;
68              
69 200100         272967 my $index = $rand->( $max_rate );
70 200100         206220 my $cursor = 0;
71              
72 200100         223008 for my $f (@sorted_funcs) {
73 357023         355079 $cursor += $f->[0];
74              
75 357023 100       682933 if ($index <= $cursor) {
76 129851         246108 return $f->[1]->(@args);
77             }
78             }
79              
80 70249 50       117095 if ($default_func) {
81 70249         129061 return $default_func->(@args);
82             }
83             else {
84 0         0 return;
85             }
86 3         42 };
87             }
88              
89             sub clear {
90 2     2 1 2685 my ($self) = @_;
91 2         18 $self->_func([]);
92 2         18 $self->_default_func(undef);
93             }
94              
95             __PACKAGE__->meta->make_immutable;
96              
97             __END__