File Coverage

blib/lib/Text/Spintax/RenderNode.pm
Criterion Covered Total %
statement 35 53 66.0
branch 13 26 50.0
condition n/a
subroutine 9 11 81.8
pod 2 9 22.2
total 59 99 59.6


line stmt bran cond sub pod time code
1             package Text::Spintax::RenderNode;
2              
3 2     2   11 use strict;
  2         2  
  2         79  
4 2     2   12 use warnings FATAL => 'all';
  2         4  
  2         1557  
5              
6 1 50   1 0 3 sub parent { scalar @_ == 2 and $_[0]->{parent} = $_[1]; return $_[0]->{parent} }
  1         4  
7 305 100   305 0 485 sub children { scalar @_ == 2 and $_[0]->{children} = $_[1]; return $_[0]->{children} }
  305         495  
8 353 50   353 0 508 sub weight { scalar @_ == 2 and $_[0]->{weight} = $_[1]; return $_[0]->{weight} }
  353         542  
9 303 50   303 0 442 sub text { scalar @_ == 2 and $_[0]->{text} = $_[1]; return $_[0]->{text} }
  303         974  
10 811 50   811 0 1176 sub type { scalar @_ == 2 and $_[0]->{type} = $_[1]; return $_[0]->{type} }
  811         1553  
11              
12             =head1 SUBROUTINES/METHODS
13              
14             =cut
15              
16             sub new {
17 7     7 0 9 my $class = shift;
18 7         27 my %init = @_;
19 7         14 my $self = bless \%init, $class;
20 7         18 return $self;
21             }
22              
23             =head2 render
24              
25             Generates a text string from all the possible variations. Uses weights to determine how likely each possible string is to be rendered.
26              
27             =cut
28              
29             sub render {
30 505     505 1 1205 my $self = shift;
31 505 100       569 if ($self->type eq "text") {
    100          
    50          
32 303         358 return $self->text;
33             }
34             elsif ($self->type eq "spin") {
35 101         85 my $total = 0;
36 101         71 foreach my $child (@{$self->children}) {
  101         119  
37 202         238 $total += $child->weight;
38             }
39 101         158 my $rand = rand $total;
40 101         81 foreach my $child (@{$self->children}) {
  101         128  
41 151         186 $rand -= $child->weight;
42 151 100       340 $rand <= 0 and return $child->render;
43             }
44             }
45             elsif ($self->type eq "sequence") {
46 101         116 return join "", map { $_->render } @{$self->children};
  303         382  
  101         118  
47             }
48             else {
49 0           die "invalid type";
50             }
51             }
52              
53             sub equal_path_weight {
54 0     0 0   my $self = shift;
55 0           $self->weight($self->num_paths);
56 0 0         foreach my $child ($self->children ? @{$self->children} : ()) {
  0            
57 0           $child->equal_path_weight;
58             }
59             }
60              
61             =head2 num_paths
62              
63             Returns the number of possible strings that could be generated from this node. Combinatorially speaking, children of a sequence node multiply and children of a spin node add.
64              
65             "{a|b|c}" has 1+1+1=3 possibilities: a, b, c
66              
67             "{a|b} {c|d}" has 2*2=4 possibilities: a c, a d, b c, b d
68              
69             =cut
70              
71             sub num_paths {
72 0     0 1   my $self = shift;
73 0 0         if ($self->type eq "spin") {
74 0           my $num_paths = 0;
75 0 0         foreach my $child ($self->children ? @{$self->children} : ()) {
  0            
76 0           $num_paths += $child->num_paths;
77             }
78 0           return $num_paths;
79             }
80             else {
81 0           my $num_paths = 1;
82 0 0         foreach my $child ($self->children ? @{$self->children} : ()) {
  0            
83 0           $num_paths *= $child->num_paths;
84             }
85 0           return $num_paths;
86             }
87             }
88              
89             1;