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   100327 use strict;
  4         13  
  4         107  
9 4     4   16 use warnings;
  4         7  
  4         98  
10              
11 4     4   17 use Carp qw(croak confess);
  4         7  
  4         204  
12 4     4   1673 use Math::Random::Discrete;
  4         2299  
  4         98  
13 4     4   456 use Moo;
  4         9286  
  4         21  
14 4     4   2511 use namespace::clean;
  4         9958  
  4         26  
15              
16             our $VERSION = '0.10';
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 17 50   17 1 1627 croak "add_choice requires a value" if @_ < 2;
44 17         36 my ($self, $value, $weight) = @_;
45 17         23 push @{ $self->terms }, $value;
  17         45  
46 17   66     26 push @{ $self->weights }, $weight // $DEFAULT_WEIGHT;
  17         67  
47 17         249 $self->clear_picker;
48 17         82 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 327     327 1 800 my $self = shift;
55 327         358 my $str;
56              
57 327         557 my $terms = $self->terms;
58 327 100       604 if (!@$terms) {
    100          
59             # in theory this shouldn't happen. could also instead set the
60             # empty string here...
61 1         161 confess "no choices to pick from";
62             } elsif (@$terms == 1) {
63 4         11 $str = $terms->[0]->render;
64             } else {
65 322         387 my $picker = $self->picker;
66 322 100       588 if (!defined $picker) {
67 4         32 $picker = Math::Random::Discrete->new($self->weights, $terms);
68 4         181 $self->_set_picker($picker);
69             }
70 322         548 $str = $picker->rand->render;
71             }
72              
73 326   50     779 my $filter_with = $self->filter_with // '';
74 326         336 for my $filter (@{ $self->filters }) {
  326         591  
75 911         4895 $str =~ s/\Q$filter/$filter_with/g;
76             }
77 326         1201 return $str;
78             }
79              
80             sub walk {
81 3     3 1 6 my ($self, $callback) = @_;
82 3         9 $callback->($self);
83 3         9 for my $term (@{ $self->terms }) {
  3         8  
84 6         14 $term->walk($callback);
85             }
86 3         5 return;
87             }
88              
89             1;
90             __END__