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   99712 use strict;
  4         18  
  4         106  
9 4     4   18 use warnings;
  4         7  
  4         98  
10              
11 4     4   19 use Carp qw(croak confess);
  4         7  
  4         180  
12 4     4   1619 use Math::Random::Discrete;
  4         1706  
  4         103  
13 4     4   449 use Moo;
  4         9396  
  4         17  
14 4     4   2759 use namespace::clean;
  4         9408  
  4         25  
15              
16             our $VERSION = '0.08';
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 1307 croak "add_choice requires a value" if @_ < 2;
44 23         38 my ( $self, $value, $weight ) = @_;
45 23         34 push @{ $self->terms }, $value;
  23         62  
46 23   66     29 push @{ $self->weights }, $weight // $DEFAULT_WEIGHT;
  23         83  
47 23         349 $self->clear_picker;
48 23         104 return $self;
49             }
50              
51 3     3 1 6 sub add_filters { my $self = shift; push @{ $self->filters }, @_; return $self }
  3         5  
  3         12  
  3         5  
52              
53             sub render {
54 340     340 1 885 my $self = shift;
55 340         352 my $str;
56              
57 340         411 my $terms = $self->terms;
58 340 100       586 if ( !@$terms ) {
    100          
59             # in theory this shouldn't happen. could also instead set the
60             # empty string here...
61 1         17 confess "no choices to pick from";
62             } elsif ( @$terms == 1 ) {
63 4         13 $str = $terms->[0]->render;
64             } else {
65 335         434 my $picker = $self->picker;
66 335 100       523 if ( !defined $picker ) {
67 8         41 $picker = Math::Random::Discrete->new( $self->weights, $terms );
68 8         327 $self->_set_picker($picker);
69             }
70 335         488 $str = $picker->rand->render;
71             }
72              
73 339   50     613 my $filter_with = $self->filter_with // '';
74 339         348 for my $filter ( @{ $self->filters } ) {
  339         507  
75 911         4790 $str =~ s/\Q$filter/$filter_with/g;
76             }
77 339         754 return $str;
78             }
79              
80             sub walk {
81 3     3 1 7 my ($self, $callback) = @_;
82 3         9 $callback->($self);
83 3         6 for my $term ( @{ $self->terms } ) {
  3         9  
84 6         13 $term->walk($callback);
85             }
86 3         4 return;
87             }
88              
89             1;
90             __END__