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.19';
3             # Last Edit: 2011 2月 27, 21時32分54秒
4             # $Id: $
5              
6 28     28   985765 use warnings;
  28         63  
  28         871  
7 28     28   145 use strict;
  28         49  
  28         710  
8              
9 28     28   19237 use List::MoreUtils qw/any/;
  28         296199  
  28         199  
10              
11 28     28   29798 use Games::Tournament::Swiss::Config;
  28         1155  
  28         1363  
12 28 100       1990 use constant ROLES => @Games::Tournament::Swiss::Config::roles?
13             @Games::Tournament::Swiss::Config::roles:
14 28     28   157 Games::Tournament::Swiss::Config->roles;
  28         1215  
15              
16 28     28   147 use base qw/Games::Tournament::Contestant/;
  28         53  
  28         10493  
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 407783 my $self = shift;
52 1853         6176 my %args = @_;
53             # $args{roles} = [] unless $args{roles};
54 1853         3340 my $object = bless \%args, $self;
55 1853         4970 $object->preference(
56             Games::Tournament::Contestant::Swiss::Preference->new );
57 1853         5334 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 44899     44899 1 63665 my $self = shift;
71 44899   66     113347 my $preference = shift() || $self->{preference};
72 44899         61522 $self->{preference} = $preference;
73 44899         118980 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 48597 my $self = shift;
87 39863 100       78235 $self->{pairingNumber} = shift if @_;
88 39863         118839 $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 3084 my $self = shift;
137 2412         3028 my $round = shift;
138 2412         2907 my $role = shift;
139 2412 100 66     14064 if ( defined $role and defined $round ) {
    50 66        
    100          
140 648         1185 my $oldrole = $self->{roles}->{$round};
141 648 50 33     1584 warn "$oldrole role replaced by $role" if defined $oldrole and
142             $oldrole ne $role;
143 648         1957 $self->{roles}->{$round} = $role;
144             }
145 0         0 elsif ( $self->{roles} and $round ) { return $self->{roles}->{$round}; }
146 1536         3275 elsif ( $self->{roles} ) { return $self->{roles}; }
147 228         546 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 1474 my $self = shift;
159 1116         2164 my $roles = $self->roles;
160 1116         3840 my @rounds = sort { $a <=> $b } keys %$roles;
  3046         5762  
161 1116         1862 my $last = $rounds[-1];
162 1116         1796 my @playrounds = grep { my $role = $roles->{$_};
  3034         4898  
163 3034     4589   11510 any { $role eq $_ } ROLES } @rounds;
  4589         13480  
164 1116         1730 my @playroles = map { $roles->{$_} } @playrounds;
  2938         5899  
165 1116         4802 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 3083 my $self = shift;
180 2295         2966 my $direction = shift;
181 2295 100 100     13917 if ( defined $direction and $direction =~ m/^(?:Up|Down|)$/ ) {
    100          
182 1223         3937 $self->{floater} = $direction;
183             }
184 362         2007 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 3535 my $self = shift;
199 2669         3284 my $round = shift;
200 2669         3382 my $float = shift;
201 2669 100 100     11666 if ( defined $round and defined $float ) {
    100          
    50          
202 648         1667 $self->{floats}->[$round-1] = $float;
203 648         1389 return;
204             }
205             elsif ( defined $round ) {
206 2003 50 66     6340 if ($round == -1 or $round == -2) {
207 2003 100       4730 if (not exists $self->{floats}->[$round-1] ) {return 'Not'}
  634         2016  
208 1369         5271 else { return $self->{floats}->[$round]; }
209             }
210 0         0 else { return $self->{floats}->[$round-1]; }
211             }
212 18         136 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   15578 use Games::Tournament::Contestant::Swiss::Preference;
  28         68  
  28         4910  
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: