line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Games::Tournament::Contestant::Swiss::Preference; |
2
|
|
|
|
|
|
|
$Games::Tournament::Contestant::Swiss::Preference::VERSION = '0.20'; |
3
|
|
|
|
|
|
|
# Last Edit: 2016 Jan 01, 13:45:02 |
4
|
|
|
|
|
|
|
# $Id: $ |
5
|
|
|
|
|
|
|
|
6
|
30
|
|
|
30
|
|
130080
|
use warnings; |
|
30
|
|
|
|
|
52
|
|
|
30
|
|
|
|
|
1578
|
|
7
|
30
|
|
|
30
|
|
152
|
use strict; |
|
30
|
|
|
|
|
49
|
|
|
30
|
|
|
|
|
619
|
|
8
|
30
|
|
|
30
|
|
467
|
use Carp; |
|
30
|
|
|
|
|
60
|
|
|
30
|
|
|
|
|
2053
|
|
9
|
|
|
|
|
|
|
|
10
|
30
|
|
|
30
|
|
164
|
use List::Util qw/first/; |
|
30
|
|
|
|
|
52
|
|
|
30
|
|
|
|
|
1882
|
|
11
|
30
|
|
|
30
|
|
923
|
use List::MoreUtils qw/any/; |
|
30
|
|
|
|
|
11846
|
|
|
30
|
|
|
|
|
183
|
|
12
|
|
|
|
|
|
|
|
13
|
30
|
|
|
30
|
|
13373
|
use Games::Tournament::Swiss::Config; |
|
30
|
|
|
|
|
54
|
|
|
30
|
|
|
|
|
1424
|
|
14
|
|
|
|
|
|
|
|
15
|
30
|
100
|
|
|
|
1630
|
use constant ROLES => @Games::Tournament::Swiss::Config::roles? |
16
|
|
|
|
|
|
|
@Games::Tournament::Swiss::Config::roles: |
17
|
30
|
|
|
30
|
|
176
|
Games::Tournament::Swiss::Config->roles; |
|
30
|
|
|
|
|
65
|
|
18
|
|
|
|
|
|
|
|
19
|
30
|
|
|
30
|
|
144
|
use base qw/Games::Tournament/; |
|
30
|
|
|
|
|
46
|
|
|
30
|
|
|
|
|
22799
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
# use overload qw/0+/ => 'next', qw/""/ => 'value', fallback => 1; |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=head1 NAME |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
Games::Tournament::Contestant::Swiss::Preference A competitor's right to a role. |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=cut |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=head1 SYNOPSIS |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
pray if $preference->role eq 'Black' and $preference->strength eq 'Strong'; |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=head1 DESCRIPTION |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
The preference, or expectation/right/duty one has with reference to a role, eg White, in the next round depends on the difference between the number of games previously played in it and in the alternative roles, and is either Mild, Strong, or Absolute. The more games played in other roles than in this role, the greater the right/duty to play the next game in this role. The FIDE Swiss Rules (C04.1) represent the difference as the number of Games as White minus the number as Black, so a greater number of games as Black is a negative number and of White a positive number. For equal number of games, +0 indicates the last game was as White, and -0 indicates the last game was as Black. So +0 represents a Mild preference for Black and -0 for White. This implementation uses a 'sign' field to perform the same function as the +/- sign. |
36
|
|
|
|
|
|
|
As an API, the strength method returns 'Mild', 'Strong', or 'Absolute' and the role method returns 'Black', 'White', or whatever the preferred role is, respecting the 2 consecutive games in the same role rule. A7 |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=head1 METHODS |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=head2 new |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
$pref = Games::Tournament::Contestant::Swiss::Preference->new( |
43
|
|
|
|
|
|
|
difference => 0, sign => 'Black', round => 0 ); |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
The default difference is 0. The default sign is ''. |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=cut |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub new { |
50
|
1931
|
|
|
1931
|
1
|
131903
|
my $self = shift; |
51
|
1931
|
|
|
|
|
2922
|
my %args = @_; |
52
|
1931
|
100
|
|
|
|
5604
|
$args{sign} = '' unless $args{sign}; |
53
|
1931
|
100
|
|
|
|
4422
|
$args{difference} = 0 unless $args{difference}; |
54
|
1931
|
|
|
|
|
3611
|
my $pref = bless \%args, $self; |
55
|
1931
|
|
|
|
|
5673
|
return $pref; |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=head2 update |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
$pref->update( \@oldRoles ) |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
Updates the difference (ie, the internal representation of preference) on the basis of the last role (and second-last role) in \@oldRoles. A minimal sanity check is performed. \@oldRoles is a history of roles in previous rounds, and it is expected only the last role of this history has not yet been used to update the preference. That is, this method must be used round-by-round to keep a players preference up to date. However, the second-last role (in addition to the last role) is also needed to determine the preference in cases when the same role was taken in the last 2 games. So for updates after the second round, make sure the history is at least 2 elements long. Byes and unplayed games have no effect on the preference, so make sure that roles in unplayed games don't make it into oldRoles A5, F2 . |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=cut |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
sub update { |
68
|
749
|
|
|
749
|
1
|
1887
|
my $self = shift; |
69
|
749
|
|
|
|
|
955
|
my $roles = shift; |
70
|
749
|
|
|
|
|
955
|
my $message = "Preference update: "; |
71
|
749
|
100
|
66
|
1142
|
|
4268
|
return unless $roles->[-1] and any { $roles->[-1] eq $_ } ROLES; |
|
1142
|
|
|
|
|
3613
|
|
72
|
727
|
|
|
|
|
2679
|
my @reverseRoles = reverse @$roles; |
73
|
727
|
|
|
|
|
973
|
my $lastRole = $reverseRoles[0]; |
74
|
727
|
|
|
|
|
930
|
my $before = $reverseRoles[1]; |
75
|
727
|
|
|
|
|
874
|
my $oneBeforeThat = $reverseRoles[2]; |
76
|
727
|
100
|
100
|
|
|
3672
|
$message .= "3-game run as $lastRole\n" if $before and $oneBeforeThat and |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
77
|
|
|
|
|
|
|
$oneBeforeThat eq $before and $before eq $lastRole; |
78
|
727
|
|
|
|
|
1518
|
my $difference = $self->difference; |
79
|
727
|
|
|
|
|
1532
|
my $sign = $self->sign; |
80
|
727
|
|
|
1004
|
|
3174
|
my $otherDirection = first { $_ ne $sign } ROLES; |
|
1004
|
|
|
|
|
1728
|
|
81
|
727
|
100
|
66
|
|
|
4386
|
if ( not $sign or not defined $difference ) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
82
|
109
|
|
|
|
|
160
|
$sign = $lastRole; |
83
|
109
|
|
|
|
|
163
|
$difference = 1; |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
elsif ( $lastRole eq $otherDirection ) { |
86
|
492
|
100
|
|
|
|
1077
|
if ( $difference > 0 ) { |
|
|
50
|
|
|
|
|
|
87
|
288
|
|
|
|
|
350
|
$difference--; |
88
|
288
|
100
|
|
|
|
697
|
if ( $difference == 0 ) { |
89
|
243
|
|
|
|
|
416
|
$sign = $otherDirection; |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
elsif ( $difference == 0 ) { |
93
|
204
|
|
|
|
|
288
|
$sign = $lastRole; |
94
|
204
|
|
|
|
|
325
|
$difference = 1; |
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
else { |
97
|
0
|
|
|
|
|
0
|
die "$difference games more as $sign after $lastRole role?"; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
elsif ( $lastRole eq $sign ) { |
101
|
126
|
|
|
|
|
174
|
$difference++; |
102
|
126
|
100
|
|
|
|
314
|
if ( $difference > 2 ) { |
103
|
32
|
|
|
|
|
73
|
$message .= "$difference games more as $lastRole\n"; |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
else { |
107
|
0
|
|
|
|
|
0
|
die |
108
|
|
|
|
|
|
|
"$lastRole role update on ${difference}-game difference in $sign role?"; |
109
|
|
|
|
|
|
|
} |
110
|
727
|
|
|
|
|
1520
|
$self->sign($sign); |
111
|
727
|
|
|
|
|
1431
|
$self->difference($difference); |
112
|
727
|
100
|
|
|
|
1287
|
if ($before) { $self->lastTwo( [ $before, $lastRole ] ); } |
|
529
|
|
|
|
|
1577
|
|
113
|
198
|
|
|
|
|
575
|
else { $self->lastTwo( [$lastRole] ); } |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=head2 asString |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
$pref->asString |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
The difference as a string, ^[+-][012]$. '0' represents a mild preference, '1' a strong one and '2' an absolute one. '-' represents a preference for White, or the first element of @Games::Tournament::Swiss::Config::roles, and '+' represents a preference for Black or the second element. A player may have an absolute preference even if the difference is 0, because it played the previous 2 rounds in the other color. |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=cut |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub asString { |
127
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
128
|
0
|
0
|
|
|
|
0
|
my $string = $self->sign eq (ROLES)[0] ? '+' : |
|
|
0
|
|
|
|
|
|
129
|
|
|
|
|
|
|
$self->sign eq (ROLES)[1] ? '-' : ''; |
130
|
0
|
|
|
|
|
0
|
$string .= $self->difference; |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=head2 difference |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
$pref->difference(2) |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
Sets/gets the value of the difference in games played in one role over those played in other alternative roles. Equals either 0,1,2. |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=cut |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub difference { |
144
|
6916
|
|
|
6916
|
1
|
8605
|
my $self = shift; |
145
|
6916
|
|
|
|
|
8223
|
my $difference = shift(); |
146
|
6916
|
100
|
|
|
|
13926
|
$self->{difference} = $difference if defined $difference; |
147
|
6916
|
|
|
|
|
14685
|
return $self->{difference}; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=head2 sign |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
$pref->sign('Black') |
154
|
|
|
|
|
|
|
$pref->sign('-') |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
Sets/gets the role which the player has taken more often, or more recently, than other alternative roles. The preference is thus for the other role. |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=cut |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
sub sign { |
161
|
76757
|
|
|
76757
|
1
|
92175
|
my $self = shift; |
162
|
76757
|
|
66
|
|
|
192945
|
my $sign = shift() || $self->{sign}; |
163
|
76757
|
|
|
|
|
176374
|
my %abbrev = ( White => '+', Black => '-' ); |
164
|
76757
|
|
|
|
|
178297
|
my %expando = reverse %abbrev; |
165
|
76757
|
50
|
|
|
|
173341
|
$sign = $expando{$sign} if $expando{$sign}; |
166
|
76757
|
|
|
|
|
109173
|
$self->{sign} = $sign; |
167
|
76757
|
|
|
|
|
310309
|
return $sign; |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=head2 strength |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
$pref->strength |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
Gets the strength of the preference, 'Mild,' 'Strong,' or 'Absolute.' |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=cut |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
sub strength { |
180
|
3954
|
|
|
3954
|
1
|
5278
|
my $self = shift; |
181
|
3954
|
|
|
|
|
7410
|
my @degree = qw/Mild Strong Absolute/; |
182
|
3954
|
|
|
|
|
7356
|
my $diff = $self->difference; |
183
|
3954
|
|
|
|
|
5766
|
my $strength = $degree[$diff]; |
184
|
3954
|
100
|
|
|
|
7701
|
$strength = 'Absolute' if $diff > 2 ; |
185
|
3954
|
|
|
|
|
4386
|
my @lastRoles = @{ $self->lastTwo }; |
|
3954
|
|
|
|
|
7158
|
|
186
|
3954
|
100
|
|
|
|
9411
|
if ( @lastRoles == 2 ) { |
187
|
3322
|
100
|
|
|
|
7654
|
$strength = 'Absolute' if $lastRoles[0] eq $lastRoles[1]; |
188
|
|
|
|
|
|
|
} |
189
|
3954
|
|
|
|
|
21750
|
return $strength; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=head2 role |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
$pref->role |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
Gets the role which the preference entitles/requires the player to take in the next round. Not defined if sign is ''. |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=cut |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub role { |
202
|
30603
|
|
|
30603
|
1
|
41587
|
my $self = shift; |
203
|
30603
|
|
|
|
|
34398
|
my $role; |
204
|
30603
|
100
|
|
43112
|
|
56099
|
$role = first { $_ ne $self->sign } ROLES if $self->sign; |
|
43112
|
|
|
|
|
88436
|
|
205
|
30603
|
|
|
|
|
76389
|
my @lastRoles = @{ $self->lastTwo }; |
|
30603
|
|
|
|
|
58904
|
|
206
|
30603
|
100
|
100
|
|
|
129271
|
if ( @lastRoles == 2 and $lastRoles[0] eq $lastRoles[1] ) |
207
|
|
|
|
|
|
|
{ |
208
|
3909
|
|
|
5903
|
|
15616
|
$role = first { $_ ne $lastRoles[0] } ROLES; |
|
5903
|
|
|
|
|
9828
|
|
209
|
|
|
|
|
|
|
} |
210
|
30603
|
|
|
|
|
157128
|
return $role; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=head2 round |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
$pref->round |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
Sets/gets the round in this game up to which play is used to calculate the preference . The default is 0. |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
=cut |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
sub round { |
223
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
224
|
0
|
|
0
|
|
|
0
|
my $round = shift() || $self->{round}; |
225
|
0
|
|
|
|
|
0
|
$self->{round} = $round; |
226
|
0
|
|
|
|
|
0
|
return $round; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=head2 lastTwo |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
$pref->lastTwo |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
Sets/gets a list of the roles in the last 2 games. If the 2 roles are the same, there is an absolute preference for the other role. |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
=cut |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
sub lastTwo { |
239
|
35329
|
|
|
35329
|
1
|
45123
|
my $self = shift; |
240
|
35329
|
|
|
|
|
42629
|
my $lastTwo = shift; |
241
|
35329
|
100
|
|
|
|
88684
|
if ( defined $lastTwo ) { $self->{lastTwo} = $lastTwo; } |
|
727
|
100
|
|
|
|
4125
|
|
242
|
31130
|
|
|
|
|
82003
|
elsif ( $self->{lastTwo} ) { return $self->{lastTwo}; } |
243
|
3472
|
|
|
|
|
7228
|
else { return []; } |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
=head1 AUTHOR |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
Dr Bean, C<< >> |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=head1 BUGS |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
Please report any bugs or feature requests to |
253
|
|
|
|
|
|
|
C, or through the web interface at |
254
|
|
|
|
|
|
|
L. |
255
|
|
|
|
|
|
|
I will be notified, and then you'll automatically be notified of progress on |
256
|
|
|
|
|
|
|
your bug as I make changes. |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
=head1 SUPPORT |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
perldoc Games::Tournament::Contestant::Swiss::Preference |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
You can also look for information at: |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=over 4 |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
L |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
=item * CPAN Ratings |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
L |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
L |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
=item * Search CPAN |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
L |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=back |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
Copyright 2006 Dr Bean, all rights reserved. |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
293
|
|
|
|
|
|
|
under the same terms as Perl itself. |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=cut |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
1; # End of Games::Tournament::Contestant::Preference |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
# vim: set ts=8 sts=4 sw=4 noet: |