File Coverage

blib/lib/Lingua/Awkwords/OneOf.pm
Criterion Covered Total %
statement 52 52 100.0
branch 7 8 87.5
condition 3 5 60.0
subroutine 10 10 100.0
pod 4 4 100.0
total 76 79 96.2


line stmt bran cond sub pod time code
1             # -*- Perl -*-
2             #
3             # instances of this object hold a list of choices one of which is
4             # randomly picked upon render
5              
6             package Lingua::Awkwords::OneOf;
7              
8 4     4   85081 use strict;
  4         19  
  4         112  
9 4     4   24 use warnings;
  4         8  
  4         102  
10              
11 4     4   16 use Carp qw(croak confess);
  4         8  
  4         169  
12 4     4   1010 use Math::Random::Discrete;
  4         1481  
  4         144  
13 4     4   329 use Moo;
  4         8217  
  4         19  
14 4     4   2122 use namespace::clean;
  4         8070  
  4         22  
15              
16             our $VERSION = '0.07';
17              
18             my $DEFAULT_WEIGHT = 1;
19              
20             has filters => (
21             is => 'rwp',
22             default => sub { [] },
23             );
24             has filter_with => (
25             is => 'rw',
26             default => sub { '' },
27             );
28             has terms => (
29             is => 'rwp',
30             default => sub { [] },
31             );
32             has picker => ( is => 'rwp', clearer => 1 );
33             has weights => (
34             is => 'rwp',
35             default => sub { [] },
36             );
37              
38             ########################################################################
39             #
40             # METHODS
41              
42             sub add_choice {
43 23 50   23 1 932 croak "add_choice requires a value" if @_ < 2;
44 23         42 my ( $self, $value, $weight ) = @_;
45 23         31 push @{ $self->terms }, $value;
  23         59  
46 23   66     26 push @{ $self->weights }, $weight // $DEFAULT_WEIGHT;
  23         84  
47 23         322 $self->clear_picker;
48 23         103 return $self;
49             }
50              
51 3     3 1 6 sub add_filters { my $self = shift; push @{ $self->filters }, @_; return $self }
  3         4  
  3         11  
  3         7  
52              
53             sub render {
54 340     340 1 980 my $self = shift;
55 340         350 my $str;
56              
57 340         448 my $terms = $self->terms;
58 340 100       646 if ( !@$terms ) {
    100          
59             # in theory this shouldn't happen. could also instead set the
60             # empty string here...
61 1         14 confess "no choices to pick from";
62             } elsif ( @$terms == 1 ) {
63 4         12 $str = $terms->[0]->render;
64             } else {
65 335         428 my $picker = $self->picker;
66 335 100       539 if ( !defined $picker ) {
67 8         34 $picker = Math::Random::Discrete->new( $self->weights, $terms );
68 8         308 $self->_set_picker($picker);
69             }
70 335         520 $str = $picker->rand->render;
71             }
72              
73 339   50     663 my $filter_with = $self->filter_with // '';
74 339         348 for my $filter ( @{ $self->filters } ) {
  339         493  
75 911         4947 $str =~ s/\Q$filter/$filter_with/g;
76             }
77 339         806 return $str;
78             }
79              
80             sub walk {
81 3     3 1 5 my ($self, $callback) = @_;
82 3         8 $callback->($self);
83 3         7 for my $term ( @{ $self->terms } ) {
  3         8  
84 6         12 $term->walk($callback);
85             }
86 3         3 return;
87             }
88              
89             1;
90             __END__