File Coverage

blib/lib/Games/Tournament/Contestant/Swiss.pm
Criterion Covered Total %
statement 70 105 66.6
branch 22 38 57.8
condition 15 21 71.4
subroutine 15 19 78.9
pod 11 11 100.0
total 133 194 68.5


line stmt bran cond sub pod time code
1             package Games::Tournament::Contestant::Swiss;
2             $Games::Tournament::Contestant::Swiss::VERSION = '0.20';
3             # Last Edit: 2011 2月 27, 21時32分54秒
4             # $Id: $
5              
6 28     28   1030033 use warnings;
  28         64  
  28         868  
7 28     28   134 use strict;
  28         54  
  28         661  
8              
9 28     28   19070 use List::MoreUtils qw/any/;
  28         294900  
  28         198  
10              
11 28     28   30389 use Games::Tournament::Swiss::Config;
  28         1176  
  28         1369  
12 28 100       1982 use constant ROLES => @Games::Tournament::Swiss::Config::roles?
13             @Games::Tournament::Swiss::Config::roles:
14 28     28   165 Games::Tournament::Swiss::Config->roles;
  28         1241  
15              
16 28     28   137 use base qw/Games::Tournament::Contestant/;
  28         51  
  28         10771  
17              
18             # use overload qw/0+/ => 'pairingNumber', qw/""/ => 'name', fallback => 1;
19              
20             =head1 NAME
21              
22             Games::Tournament::Contestant::Swiss A competitor in a FIDE-Swiss-Rules event
23              
24             =cut
25              
26             =head1 SYNOPSIS
27              
28             my $foo = Games::Tournament::Contestant::Swiss->new( rating => '15', name => 'Deep Blue', pairingNumber => 2 );
29             ...
30              
31             =head1 DESCRIPTION
32              
33             Subclasses Games::Tournament::Contestant with Games::Tournament::Swiss-specific data and methods, like pairingNumber, floats.
34              
35             Games::Tournament::Swiss will use this class when constructing a 'Bye' contestant.
36              
37             =head1 METHODS
38              
39             =head2 new
40              
41             Games::Tournament::Contestant::Swiss->new( rating => '15',
42             name => 'Red Chessman', pairingNumber => 2,
43             floats => [qw/Not Down Not Not],
44             roles => [qw/Black White Black White/] );
45              
46             Actually, you don't want to assign pairing numbers this way. Let the assignPairingNumbers method in Games::Tournament::Swiss do it. The player gets a default mild preference for neither role.
47              
48             =cut
49              
50             sub new() {
51 1853     1853 1 407557 my $self = shift;
52 1853         5774 my %args = @_;
53             # $args{roles} = [] unless $args{roles};
54 1853         3283 my $object = bless \%args, $self;
55 1853         5185 $object->preference(
56             Games::Tournament::Contestant::Swiss::Preference->new );
57 1853         5321 return $object;
58             }
59              
60              
61             =head2 preference
62              
63             $member->preference
64              
65             Gets (sets) $member's preference, or right (duty) to take a role, eg White or Black, in the next round, calculated as a function of the difference between the number of games previously played in the different roles, and accommodated according to its value, Mild, Strong, or Absolute. An Absolute preference of +2 for White is given when the contestant has played 2 (or a larger number) more of the previous rounds as Black than as White, or when the last 2 rounds were played as Black. A Strong preference of +1 for White represents having played one more round as Black than as White. A Mild preference of +0 occurs when the number of games played with both colors is the same, but the last game was played as Black. A Mild preference of -0 is the same, but with the last game being as White, the preference is for Black. Preferences of -1 and -2 represent the same situations as for +1 and +2, but with the roles reversed. Before the first round, the preference of the highest ranked player (+-0) is determined by lot. A7
66              
67             =cut
68              
69             sub preference {
70 46067     46067 1 64203 my $self = shift;
71 46067   66     113627 my $preference = shift() || $self->{preference};
72 46067         62688 $self->{preference} = $preference;
73 46067         123650 return $preference;
74             }
75              
76              
77             =head2 pairingNumber
78              
79             $member->pairingNumber(1)
80              
81             Sets/gets the pairing number of the contestant, used to identify participants when pairing them with others. This index is assigned in order of a sorting of the participants by ranking, title and name. You know what you're doing with this number, don't you?
82              
83             =cut
84              
85             sub pairingNumber {
86 39863     39863 1 52843 my $self = shift;
87 39863 100       77923 $self->{pairingNumber} = shift if @_;
88 39863         126517 $self->{pairingNumber};
89             }
90              
91              
92             =head2 oldId
93              
94             $member->oldId
95              
96             Sets/gets an original, possibly unreliable id of the contestant, supplied by the user.
97              
98             =cut
99              
100             sub oldId {
101 0     0 1 0 my $self = shift;
102 0         0 my $oldId = shift;
103 0 0       0 if ( defined $oldId ) { $self->{oldId} = $oldId; }
  0 0       0  
104 0         0 elsif ( $self->{oldId} ) { return $self->{oldId}; }
105             }
106              
107             =head2 opponents
108              
109             $member->opponents( 0, 5, 11 )
110             $rolehistory = $member->opponents
111              
112             If ids are passed, adds them to the end of the list representing the latest opponents that $member has had in this tournament. (Normally one and only one parameter, the id of the opponent in the latest round, will be passed.) If no parameter is passed, returns a reference to the list. If the member had no game or played no game, because of a bye, or no result, or was unpaired, pass 'Bye' or 'Forfeit' or 'Unpaired'.
113              
114             =cut
115              
116             sub opponents {
117 0     0 1 0 my $self = shift;
118 0         0 my @opponents = @_;
119 0 0       0 if ( @opponents ) { push @{ $self->{opponents} }, @opponents; return }
  0 0       0  
  0         0  
  0         0  
120 0         0 elsif ( $self->{opponents} ) { return $self->{opponents}; }
121 0         0 else { return []; }
122             }
123              
124              
125             =head2 roles
126              
127             $member->roles( 1, 'Black' )
128             $member->roles( 1 ) # 'Black'
129             $rolehistory = $member->roles # { 1 => 'Black' }
130              
131             If a round and role are passed, adds them to the roles that $member has had in this tournament. If the member had no game (or had a game but didn't play it), that is, if they had a bye, or no result, or were unpaired, pass 'Bye', or 'Forfeit', or 'Unpaired.' F2,3
132              
133             =cut
134              
135             sub roles {
136 2412     2412 1 3079 my $self = shift;
137 2412         2984 my $round = shift;
138 2412         2938 my $role = shift;
139 2412 100 66     14195 if ( defined $role and defined $round ) {
    50 66        
    100          
140 648         1181 my $oldrole = $self->{roles}->{$round};
141 648 50 33     1605 warn "$oldrole role replaced by $role" if defined $oldrole and
142             $oldrole ne $role;
143 648         1956 $self->{roles}->{$round} = $role;
144             }
145 0         0 elsif ( $self->{roles} and $round ) { return $self->{roles}->{$round}; }
146 1536         3304 elsif ( $self->{roles} ) { return $self->{roles}; }
147 228         529 else { return {}; }
148             }
149              
150              
151             =head2 rolesPlayedList
152              
153             A list, in round order, of the roles played against other players. Byes and other non-partnership roles are not included.
154              
155             =cut
156              
157             sub rolesPlayedList {
158 1116     1116 1 1470 my $self = shift;
159 1116         2290 my $roles = $self->roles;
160 1116         3841 my @rounds = sort { $a <=> $b } keys %$roles;
  3009         5735  
161 1116         1908 my $last = $rounds[-1];
162 1116         1822 my @playrounds = grep { my $role = $roles->{$_};
  3034         4837  
163 3034     4589   11787 any { $role eq $_ } ROLES } @rounds;
  4589         13653  
164 1116         1743 my @playroles = map { $roles->{$_} } @playrounds;
  2938         5879  
165 1116         4823 return \@playroles;
166             }
167              
168              
169             =head2 floating
170              
171             $member->floating
172             $member->floating( 'Up'|'Down'|'' )
173              
174             Sets/gets the direction in which the contestant is floating in the next round, "Up", "Down". If nothing is returned, the contestant is not floating. A4
175              
176             =cut
177              
178             sub floating {
179 2295     2295 1 3038 my $self = shift;
180 2295         2933 my $direction = shift;
181 2295 100 100     14054 if ( defined $direction and $direction =~ m/^(?:Up|Down|)$/ ) {
    100          
182 1223         4093 $self->{floater} = $direction;
183             }
184 362         1961 elsif ( $self->{floater} ) { return $self->{floater}; }
185             }
186              
187             =head2 floats
188              
189             $member->floats( $round, 'Down' )
190             $rolehistory = $member->floats
191              
192             If a round number and float is passed, inserts this in an anonymous array representing the old floats that $member has had in this tournament. If only a round is passed, returns the float for that round. If no parameter is passed, returns a anonymous array of all the floats ordered by the round. If the player was not floated, pass 'Not'. For convenience, if -1 or -2 are passed for the last round before, or the round 2 rounds ago, and those rounds do not exist (perhaps the tournament only started one round before), 'Not' is returned.
193              
194             =cut
195              
196              
197             sub floats {
198 2669     2669 1 3494 my $self = shift;
199 2669         3305 my $round = shift;
200 2669         3153 my $float = shift;
201 2669 100 100     11491 if ( defined $round and defined $float ) {
    100          
    50          
202 648         1705 $self->{floats}->[$round-1] = $float;
203 648         1332 return;
204             }
205             elsif ( defined $round ) {
206 2003 50 66     6244 if ($round == -1 or $round == -2) {
207 2003 100       4598 if (not exists $self->{floats}->[$round-1] ) {return 'Not'}
  634         2069  
208 1369         5314 else { return $self->{floats}->[$round]; }
209             }
210 0         0 else { return $self->{floats}->[$round-1]; }
211             }
212 18         68 elsif ( $self->{floats} ) { return $self->{floats}; }
213 0           else { return; }
214             }
215              
216             =head2 importPairtableRecord
217              
218             $member->importPairtableRecord(
219             { opponents => [ 6,4 ]
220             roles => [ 'Win', 'Loss' ],
221             floats => [ undef, 'Not', 'Down' ],
222             score => 1.5 } )
223              
224             Populate $member with data about opponents met, roles played, and floats received in previous rounds, which together with the total score will allow it to be paired with an appropriate opponent in the next round. Set $member's preference. Delete any pre-existing opponents, roles, floats, scores, score, or preference data.
225              
226             =cut
227              
228              
229             sub importPairtableRecord {
230 0     0 1   my $self = shift;
231 0           my $record = shift;
232             #die $self->name . ", " . $self->id . " pairtable record field lengths"
233             # unless @{$record->{opponents}} == @{$record->{roles}} and
234             # @{$record->{roles}} == @{$record->{floats}} - 1;
235 0           my ($opponents, $roles, $floats) = @$record{qw/opponents roles floats/};
236 0           delete @$self{qw/opponents roles floats scores score preference/};
237 0           $self->opponents(@$opponents);
238 0           $self->roles(@$roles);
239 0           for my $i ( 0 .. $#$floats ) { $self->floats( $i, $floats->[$i] ); }
  0            
240 28     28   15567 use Games::Tournament::Contestant::Swiss::Preference;
  28         69  
  28         4762  
241 0           $self->preference(Games::Tournament::Contestant::Swiss::Preference->new);
242 0           $self->preference->update( [ @$roles[0..$_] ] ) for 0.. $#$roles;
243 0           $self->{score} = $record->{score};
244 0           return;
245             }
246              
247             =head2 unbyable
248              
249             $member->unbyable(1)
250             return BYE unless $member->unbyable
251              
252             A flag of convenience telling you whether to let this player have the bye. Am I doing the right thing here? This will be gettable and settable, but will it be reliable?
253              
254             =cut
255              
256             sub unbyable {
257 0     0 1   my $self = shift;
258 0           my $unbyable = shift;
259 0 0         if ( $unbyable ) { $self->{unbyable} = 1; return }
  0 0          
  0            
260 0           elsif ( defined $self->{unbyable} ) { return $self->{unbyable}; }
261 0           else { return; }
262             }
263              
264              
265             =head1 AUTHOR
266              
267             Dr Bean, C<< >>
268              
269             =head1 BUGS
270              
271             Please report any bugs or feature requests to
272             C, or through the web interface at
273             L.
274             I will be notified, and then you'll automatically be notified of progress on
275             your bug as I make changes.
276              
277             =head1 SUPPORT
278              
279             You can find documentation for this module with the perldoc command.
280              
281             perldoc Games::Tournament::Contestant::Swiss
282              
283             You can also look for information at:
284              
285             =over 4
286              
287             =item * AnnoCPAN: Annotated CPAN documentation
288              
289             L
290              
291             =item * CPAN Ratings
292              
293             L
294              
295             =item * RT: CPAN's request tracker
296              
297             L
298              
299             =item * Search CPAN
300              
301             L
302              
303             =back
304              
305             =head1 ACKNOWLEDGEMENTS
306              
307             =head1 COPYRIGHT & LICENSE
308              
309             Copyright 2006 Dr Bean, all rights reserved.
310              
311             This program is free software; you can redistribute it and/or modify it
312             under the same terms as Perl itself.
313              
314             =cut
315              
316             1; # End of Games::Tournament::Contestant::Swiss
317              
318             # vim: set ts=8 sts=4 sw=4 noet: