File Coverage

blib/lib/Games/Go/AGA/DataObjects/Directives.pm
Criterion Covered Total %
statement 61 108 56.4
branch 10 32 31.2
condition 2 12 16.6
subroutine 13 21 61.9
pod 8 13 61.5
total 94 186 50.5


line stmt bran cond sub pod time code
1             #===============================================================================
2             #
3             # FILE: Games::Go::AGA::DataObjects::Directives.pm
4             #
5             # USAGE: use Games::Go::AGA::DataObjects::Directives;
6             #
7             # PODNAME: Games::Go::AGA::DataObjects::Directives
8             # ABSTRACT: model directives information from an AGA register.tde file
9             #
10             # AUTHOR: Reid Augustin (REID),
11             # CREATED: 11/19/2010 03:13:05 PM PST
12             #===============================================================================
13              
14 3     3   26844 use strict;
  3         7  
  3         102  
15 3     3   14 use warnings;
  3         4  
  3         118  
16              
17             package Games::Go::AGA::DataObjects::Directives;
18 3     3   942 use Moo;
  3         18533  
  3         59  
19 3     3   3426 use namespace::clean;
  3         16819  
  3         17  
20              
21 3     3   1374 use Games::Go::AGA::DataObjects::Types qw( is_Rank is_Rating );
  3         6  
  3         323  
22 3     3   832 use Games::Go::AGA::Parse::Util qw( Rank_to_Rating );
  3         919  
  3         179  
23 3     3   15 use Games::Go::AGA::DataObjects::Types qw( isa_CodeRef isa_HashRef );
  3         6  
  3         3697  
24              
25             our $VERSION = '0.152'; # VERSION
26              
27             has booleans => (
28             isa => \&isa_HashRef,
29             is => 'lazy',
30             default => sub {
31             {
32             FORCE_ROUND_ROBIN => 1,
33             NO_ROUND_ROBIN => 1,
34             MCMAHON => 1,
35             AGA_RATED => 1,
36             TEST => 1,
37             }
38             },
39             );
40             has change_callback => (
41             isa => \&isa_CodeRef,
42             is => 'rw',
43             lazy => 1,
44             default => sub { sub { } }
45             );
46              
47             sub BUILD {
48 3     3 0 8575 my ($self) = @_;
49 3         28 $self->{keys} = []; # empty arrays
50 3         81 $self->{values} = [];
51             }
52              
53             sub changed {
54 0     0 0 0 my ($self) = @_;
55              
56 0         0 &{$self->change_callback}(@_);
  0         0  
57             }
58              
59             sub directives {
60 0     0 1 0 my ($self) = @_;
61              
62             return wantarray
63 0         0 ? @{$self->{keys}}
64 0 0       0 : scalar @{$self->{keys}};
  0         0  
65             }
66              
67             sub is_boolean {
68 19     19 0 25 my ($self, $key) = @_;
69              
70 19         445 return $self->booleans->{uc $key};
71             }
72              
73             sub get_directive_at_idx {
74 0     0 1 0 my ($self, $idx) = @_;
75              
76             croak("$idx out of range") if (($idx < 0) or
77 0 0 0     0 ($idx >= @{$self->{keys}}));
  0         0  
78 0         0 return ($self->{keys}[$idx], $self->{values}[$idx]);
79             }
80              
81             sub set_directive_at_idx {
82 0     0 1 0 my ($self, $idx, $key, $value) = @_;
83              
84             croak("$idx out of range") if (($idx < 0) or
85 0 0 0     0 ($idx >= @{$self->{keys}}));
  0         0  
86 0 0       0 $value = $self->_munge_BAND_BREAKS($value) if (uc $key eq 'BAND_BREAKS');
87 0         0 $self->{keys}[$idx] = $key;
88 0         0 $self->{values}[$idx] = $value;
89 0         0 $self->changed;
90 0         0 return $self;
91             }
92              
93             sub delete_directive_at_idx {
94 0     0 1 0 my ($self, $idx) = @_;
95              
96 0 0       0 $idx = 0 if ($idx < 0);
97 0 0       0 $idx = $#{$self->{keys}} if ($idx > $#{$self->{keys}});
  0         0  
  0         0  
98              
99 0         0 splice(@{$self->{keys}} , $idx, 1);
  0         0  
100 0         0 splice(@{$self->{values}}, $idx, 1);
  0         0  
101 0         0 $self->changed;
102 0         0 return $self;
103             }
104              
105             sub _munge_BAND_BREAKS {
106 1     1   3 my ($self, $value) = @_;
107              
108 1 50       6 return '' if ($value eq ''); #special case to mark empty breaks
109             return join ' ', # read from the bottom up:
110 1         7 sort { $b <=> $a } # sort stronger bands higher
111 2         9 grep { $_ } # defined and truthy
112 2 50       9 map { is_Rank($_) # is it a valid Rank?
    50          
113             ? int Rank_to_Rating($_) # if so, convert to a Rating and integerize
114             : is_Rating($_) # is it a Rating?
115             ? $_ # pass through untouched
116             : undef } # filter out everything else
117 1         11 grep { $_ } # defined and truthy
  2         7  
118             split(/[^\ddDkK\.\-]+/, $value); # split into ranks/ratings
119             }
120              
121             sub insert_directive_above {
122 5     5 1 9 my ($self, $idx, $key, $value) = @_;
123              
124 5 50 33     36 if (not defined $idx or
      33        
125             $idx < 0 or
126 0         0 $idx >= @{$self->{keys}}) {
127 5         6 $idx = @{$self->{keys}}; # add to end
  5         10  
128             }
129              
130 5 100       23 $value = $self->_munge_BAND_BREAKS($value) if (uc $key eq 'BAND_BREAKS');
131 5         14 splice(@{$self->{keys}} , $idx, 0, $key);
  5         14  
132 5         6 splice(@{$self->{values}}, $idx, 0, $value);
  5         11  
133 5         18 $self->changed;
134 5         21 return $self;
135             }
136              
137             sub delete_directive {
138 0     0 1 0 my ($self, $key) = @_;
139              
140 0         0 my $keys = $self->{keys};
141              
142 0         0 for (my $ii = $#{$keys}; $ii >= 0; $ii--) {
  0         0  
143 0 0       0 if (uc $key eq uc $keys->[$ii]) {
144 0         0 $self->delete_directive_at_idx($ii);
145 0         0 $self->changed;
146 0         0 last;
147             }
148             }
149 0         0 return $self;
150             }
151              
152             sub get_directive_values { # for backwards compatibility
153 0     0 0 0 shift->get_directive_value(@_);
154             }
155              
156             sub get_directive_value {
157 20     20 1 25 my ($self, $key) = @_;
158              
159 20         35 my $keys = $self->{keys};
160 20         28 $key = uc ($key);
161 20         18 foreach my $ii (0 .. $#{$keys}) {
  20         67  
162 98 100       207 if (uc($keys->[$ii]) eq $key) {
163 19         28 my $val = $self->{values}[$ii];
164 19 50       46 $val = 1 if ($self->is_boolean($key)); # booleans (key but no defined value)
165 19         237 return $val;
166             }
167             }
168 1         3 return; # undef
169             }
170              
171             sub set_directive_value {
172 5     5 1 9 my ($self, $key, $val) = @_;
173              
174 5         8 my $keys = $self->{keys};
175 5         8 my $uc_key = uc ($key);
176 5         5 foreach my $ii (0 .. $#{$keys}) {
  5         17  
177 10 50       28 if (uc($keys->[$ii]) eq $uc_key) {
178 0 0       0 $val = '' if ($self->directive_is_boolean($key)); # presence is sufficient
179 0         0 return $self->set_directive_at_idx ($ii, $key, $val);
180             }
181             }
182             # not found? add to the end
183 5         23 return $self->insert_directive_above (-1, $key, $val);
184             }
185              
186             sub fprint {
187 0     0 0   my ($self, $fh) = @_;
188              
189 0           for my $ii (0 .. $#{$self->{keys}}) {
  0            
190 0           $fh->print("## $self->{keys}[$ii] $self->{values}[$ii]\n");
191             }
192             }
193              
194             1;
195              
196             __END__