line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Games::Tournament::Swiss::Bracket; |
2
|
|
|
|
|
|
|
$Games::Tournament::Swiss::Bracket::VERSION = '0.21'; |
3
|
|
|
|
|
|
|
# Last Edit: 2016 Jan 01, 13:44:55 |
4
|
|
|
|
|
|
|
# $Id: $ |
5
|
|
|
|
|
|
|
|
6
|
26
|
|
|
26
|
|
58570
|
use warnings; |
|
26
|
|
|
|
|
43
|
|
|
26
|
|
|
|
|
986
|
|
7
|
26
|
|
|
26
|
|
130
|
use strict; |
|
26
|
|
|
|
|
50
|
|
|
26
|
|
|
|
|
567
|
|
8
|
26
|
|
|
26
|
|
124
|
use Carp; |
|
26
|
|
|
|
|
51
|
|
|
26
|
|
|
|
|
1819
|
|
9
|
|
|
|
|
|
|
|
10
|
26
|
|
|
26
|
|
166
|
use constant ROLES => @Games::Tournament::Swiss::Config::roles; |
|
26
|
|
|
|
|
41
|
|
|
26
|
|
|
|
|
1782
|
|
11
|
|
|
|
|
|
|
|
12
|
26
|
|
|
26
|
|
130
|
use base qw/Games::Tournament::Swiss/; |
|
26
|
|
|
|
|
47
|
|
|
26
|
|
|
|
|
2592
|
|
13
|
26
|
|
|
26
|
|
548
|
use Games::Tournament::Contestant::Swiss; |
|
26
|
|
|
|
|
49
|
|
|
26
|
|
|
|
|
589
|
|
14
|
26
|
|
|
26
|
|
11085
|
use Games::Tournament::Card; |
|
26
|
|
|
|
|
69
|
|
|
26
|
|
|
|
|
808
|
|
15
|
26
|
|
|
26
|
|
154
|
use List::Util qw/max min reduce sum/; |
|
26
|
|
|
|
|
52
|
|
|
26
|
|
|
|
|
1943
|
|
16
|
26
|
|
|
26
|
|
133
|
use List::MoreUtils qw/any notall/; |
|
26
|
|
|
|
|
49
|
|
|
26
|
|
|
|
|
119
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 NAME |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
Games::Tournament::Swiss::Bracket - Players with same/similar scores pairable with each other |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=cut |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head1 SYNOPSIS |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
$tourney = Games::Tournament::Swiss>new($rounds, \@entrants); |
27
|
|
|
|
|
|
|
@rankedPlayers = $tourney->assignPairingNumbers; |
28
|
|
|
|
|
|
|
@firstbrackets = $t->formBrackets; |
29
|
|
|
|
|
|
|
... |
30
|
|
|
|
|
|
|
$tourney->collectCards(@games); |
31
|
|
|
|
|
|
|
@scores = $tourney->updateScores($round); |
32
|
|
|
|
|
|
|
@groups = $tourney->formBrackets; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=head1 DESCRIPTION |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
In a Swiss tournament, in each round contestants are paired with other players with the same, or similar, scores. These contestants are grouped into a score group (bracket) in the process of deciding who plays who. |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
The concept of immigration control is applied to impose order on the players floating in and out of these score brackets. That is, floating is like flying. |
39
|
|
|
|
|
|
|
I pulled back on this metaphor. It was probably overengineering. |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
=head1 METHODS |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
=head2 new |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
$group = Games::Tournament::Swiss::Bracket->new( score => 7.5, members => [ $a, $b, $c ], remainderof => $largergroup ) |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
members is a reference to a list of Games::Tournament::Contestant::Swiss objects. The order is important. If the score group includes floaters, these members' scores will not be the same as $group->score. Such a heterogenous group is paired in two parts--first the downfloaters, and then the homogeneous remainder group. Remainder groups can be recognized by the existence of a 'remainderof' key that links them to the group they came from. Some members may also float down from a remainder group. Each bracket needs a score to determine the right order they will be paired in. The number, from 1 to the total number of brackets, reflects that order. A3 |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=cut |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
sub new { |
52
|
287
|
|
|
287
|
1
|
776
|
my $self = shift; |
53
|
287
|
|
|
|
|
1035
|
my %args = @_; |
54
|
287
|
|
|
|
|
485
|
my $score = $args{score}; |
55
|
287
|
50
|
|
|
|
636
|
die "Bracket has score of: $score?" unless defined $score; |
56
|
287
|
|
|
|
|
500
|
bless \%args, $self; |
57
|
287
|
|
|
|
|
595
|
$args{floatCheck} = "None"; |
58
|
287
|
|
|
|
|
756
|
return \%args; |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head2 natives |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
@floaters = $group->natives |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
Returns those members who were in this bracket originally, as that was their birthright, their scores being all the same. One is a native of only one bracket, and you cannot change this status except XXX EVEN by naturalization. |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=cut |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
sub natives { |
71
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
72
|
0
|
0
|
|
|
|
0
|
return () unless @{ $self->members }; |
|
0
|
|
|
|
|
0
|
|
73
|
0
|
|
|
|
|
0
|
my $members = $self->members; |
74
|
0
|
|
|
|
|
0
|
my $foreigners = $self->immigrants; |
75
|
|
|
|
|
|
|
my @natives = grep { |
76
|
0
|
|
|
|
|
0
|
my $member = $_->pairingNumber; |
|
0
|
|
|
|
|
0
|
|
77
|
0
|
|
|
|
|
0
|
not grep { $member == $_->pairingNumber } @$foreigners |
|
0
|
|
|
|
|
0
|
|
78
|
|
|
|
|
|
|
} @$members; |
79
|
0
|
|
|
|
|
0
|
return \@natives; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=head2 citizens |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
@floaters = $group->citizens |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
Returns those members who belong to this bracket. These members don't include those have just floated in, even though this floating status may be permanent. One is a citizen of only one bracket, and you cannot change this status except by naturalization. |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=cut |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub citizens { |
92
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
93
|
0
|
0
|
|
|
|
0
|
return () unless @{ $self->members }; |
|
0
|
|
|
|
|
0
|
|
94
|
0
|
|
|
|
|
0
|
my $members = $self->members; |
95
|
0
|
|
|
|
|
0
|
my $foreigners = $self->immigrants; |
96
|
|
|
|
|
|
|
my @natives = grep { |
97
|
0
|
|
|
|
|
0
|
my $member = $_->pairingNumber; |
|
0
|
|
|
|
|
0
|
|
98
|
0
|
|
|
|
|
0
|
not grep { $member == $_->pairingNumber } @$foreigners |
|
0
|
|
|
|
|
0
|
|
99
|
|
|
|
|
|
|
} @$members; |
100
|
0
|
|
|
|
|
0
|
return \@natives; |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=head2 naturalize |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
$citizen = $group->naturalize($foreigner) |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
Gives members who are resident, but not citizens, ie immigrants, having been floated here from other brackets, the same status as natives, making them indistinguishable from them. This will fail if the player is not resident or not an immigrant. Returns the player with their new status. |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=cut |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub naturalize { |
113
|
6
|
|
|
6
|
1
|
9
|
my $self = shift; |
114
|
6
|
|
|
|
|
8
|
my $foreigner = shift; |
115
|
6
|
|
|
|
|
11
|
my $members = $self->residents; |
116
|
|
|
|
|
|
|
return unless any |
117
|
6
|
50
|
|
12
|
|
25
|
{ $_->pairingNumber == $foreigner->pairingNumber } @$members; |
|
12
|
|
|
|
|
27
|
|
118
|
6
|
|
|
|
|
21
|
my $direction = $foreigner->floating; |
119
|
6
|
50
|
33
|
|
|
29
|
return unless $direction eq 'Up' or $direction eq 'Down'; |
120
|
6
|
|
|
|
|
16
|
$foreigner->floating(''); |
121
|
6
|
|
|
|
|
23
|
return $foreigner; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=head2 immigrants |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
@floaters = @{$group->immigrants} |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
Returns those members who are foreigners, having been floated here from other brackets. At any one point a player may or may not be a foreigner. But if they are, they only can be a foreigner in one bracket. |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=cut |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
sub immigrants { |
134
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
135
|
0
|
0
|
|
|
|
0
|
return () unless @{ $self->members }; |
|
0
|
|
|
|
|
0
|
|
136
|
0
|
|
|
|
|
0
|
my $members = $self->residents; |
137
|
0
|
|
|
|
|
0
|
my @immigrants = grep { $_->floating } @$members; |
|
0
|
|
|
|
|
0
|
|
138
|
0
|
|
|
|
|
0
|
return \@immigrants; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=head2 downFloaters |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
@floaters = $group->downFloaters |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
Returns those members downfloated here from higher brackets. |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=cut |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub downFloaters { |
151
|
1
|
|
|
1
|
1
|
3
|
my $self = shift; |
152
|
1
|
|
|
|
|
3
|
my $members = $self->members; |
153
|
1
|
50
|
33
|
|
|
7
|
return () unless @$members and $self->trueHetero; |
154
|
1
|
|
|
|
|
3
|
my %members; |
155
|
1
|
|
|
|
|
2
|
for my $member ( @$members ) |
156
|
|
|
|
|
|
|
{ |
157
|
3
|
50
|
|
|
|
9
|
my $score = defined $member->score? $member->score: 0; |
158
|
3
|
|
|
|
|
10
|
push @{$members{$score}}, $member; |
|
3
|
|
|
|
|
10
|
|
159
|
|
|
|
|
|
|
} |
160
|
1
|
|
|
|
|
5
|
my $min = min keys %members; |
161
|
1
|
|
|
|
|
4
|
delete $members{$min}; |
162
|
1
|
|
|
|
|
3
|
my @floaters = map { @$_ } values %members; |
|
1
|
|
|
|
|
3
|
|
163
|
1
|
|
|
|
|
4
|
return @floaters; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=head2 upFloaters |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
@s1 = $group->upFloaters |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
Returns those members upfloated from the next bracket. |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=cut |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
sub upFloaters { |
176
|
57
|
|
|
57
|
1
|
74
|
my $self = shift; |
177
|
57
|
50
|
|
|
|
69
|
return () unless @{ $self->members }; |
|
57
|
|
|
|
|
116
|
|
178
|
57
|
|
|
|
|
131
|
my @members = $self->residents; |
179
|
57
|
100
|
|
|
|
86
|
grep { $_->floating and $_->floating =~ m/^Up/i } @{ $self->members }; |
|
203
|
|
|
|
|
490
|
|
|
57
|
|
|
|
|
113
|
|
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=head2 residents |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
$pairables = $bracket->residents |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
Returns the members includeable in pairing procedures for this bracket because they haven't been floated out, or because they have been floated in. That is, they are not an emigrant. At any one point, a player is resident in one and only one bracket, unless they are in transit. At some other point, they may be a resident of another bracket. |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=cut |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
sub residents { |
192
|
2259
|
|
|
2259
|
1
|
2989
|
my $self = shift; |
193
|
2259
|
|
|
|
|
4247
|
my $members = $self->members; |
194
|
2259
|
|
|
|
|
2866
|
my @residents; |
195
|
2259
|
|
|
|
|
4306
|
my $floated = $self->emigrants; |
196
|
2259
|
|
|
|
|
4080
|
for my $member (@$members) { |
197
|
|
|
|
|
|
|
push @residents, $member |
198
|
8764
|
50
|
|
0
|
|
50646
|
unless any { $member->pairingNumber == $_->pairingNumber } @$floated; |
|
0
|
|
|
|
|
0
|
|
199
|
|
|
|
|
|
|
} |
200
|
2259
|
|
|
|
|
5219
|
return \@residents; |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=head2 emigrants |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
$bracket->emigrants($member) |
207
|
|
|
|
|
|
|
$gone = $bracket->emigrants |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
Sets whether this citizen will not be included in pairing of this bracket. That is whether they have been floated to another bracket for pairing there. Gets all such members. A player may or may not be an emigrant. They can only stop being an emigrant if they move back to their native bracket. To do this, they have to be processed by 'entry'. |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=cut |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
sub emigrants { |
214
|
2259
|
|
|
2259
|
1
|
2719
|
my $self = shift; |
215
|
2259
|
|
|
|
|
3050
|
my $floater = shift; |
216
|
2259
|
50
|
|
|
|
3863
|
if ($floater) { push @{ $self->{gone} }, $floater; } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
217
|
2259
|
|
|
|
|
4152
|
else { return $self->{gone}; } |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
=head2 exit |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
$bracket->exit($player) |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
Removes $player from the list of members of the bracket. They are now in the air. So make sure they enter another bracket. |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=cut |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
sub exit { |
230
|
575
|
|
|
575
|
1
|
870
|
my $self = shift; |
231
|
575
|
|
|
|
|
1151
|
my $members = $self->members; |
232
|
575
|
|
|
|
|
840
|
my $exiter = shift; |
233
|
575
|
|
|
|
|
1440
|
my $myId = $exiter->pairingNumber; |
234
|
575
|
|
|
|
|
988
|
my @stayers = grep { $_->pairingNumber != $myId } @$members; |
|
1943
|
|
|
|
|
4222
|
|
235
|
575
|
|
|
|
|
1206
|
my $number = $self->number; |
236
|
575
|
50
|
|
|
|
1425
|
croak "Player $myId did not exit Bracket $number" if @stayers == @$members; |
237
|
575
|
|
|
|
|
1253
|
$self->members(\@stayers); |
238
|
|
|
|
|
|
|
#my $immigrants = $self->immigrants; |
239
|
|
|
|
|
|
|
#if ( grep { $_ == $member } @$immigrants ) { |
240
|
|
|
|
|
|
|
# @{ $self->members } = grep { $_ != $member } @$members; |
241
|
|
|
|
|
|
|
#} |
242
|
|
|
|
|
|
|
#else { |
243
|
|
|
|
|
|
|
# $self->emigrants($member); |
244
|
|
|
|
|
|
|
#} |
245
|
575
|
|
|
|
|
2028
|
return; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
=head2 entry |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
$bracket->entry($native) |
252
|
|
|
|
|
|
|
$bracket->entry($foreigner) |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
Registers $foreigner as a resident (and was removing $native from the list of emigrants of this bracket, because they have returned from another bracket as in C12, 13). |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=cut |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
sub entry { |
259
|
575
|
|
|
575
|
1
|
765
|
my $self = shift; |
260
|
575
|
|
|
|
|
1154
|
my $members = $self->residents; |
261
|
575
|
|
|
|
|
838
|
my $enterer = shift; |
262
|
575
|
|
|
|
|
1540
|
my $myId = $enterer->id; |
263
|
575
|
|
|
|
|
1286
|
my $number = $self->number; |
264
|
|
|
|
|
|
|
croak "Player $myId cannot enter Bracket $number. Is already there." if |
265
|
575
|
50
|
|
1268
|
|
2459
|
any { $_->{id} eq $myId } @$members; |
|
1268
|
|
|
|
|
2451
|
|
266
|
575
|
|
|
|
|
1707
|
unshift @$members, $enterer; |
267
|
575
|
|
|
|
|
1252
|
$self->members(\@$members); |
268
|
575
|
|
|
|
|
1832
|
return; |
269
|
|
|
|
|
|
|
} |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
=head2 reentry |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
$bracket->reentry($member) |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
Removes this native (presumably) member from the list of emigrants of this bracket, because they have returned from another bracket as in C12, 13. Returns undef, if $member wasn't an emigrant. Otherwise returns the updated list of emigrants. |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
=cut |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
sub reentry { |
281
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
282
|
0
|
|
|
|
|
0
|
my $returnee = shift; |
283
|
0
|
|
|
|
|
0
|
my $emigrants = $self->emigrants; |
284
|
0
|
0
|
|
0
|
|
0
|
if ( any { $_->pairingNumber == $returnee->pairingNumber } @$emigrants ) { |
|
0
|
|
|
|
|
0
|
|
285
|
|
|
|
|
|
|
my @nonreturnees = grep { |
286
|
0
|
|
|
|
|
0
|
$_->pairingNumber != $returnee->pairingNumber } @$emigrants; |
|
0
|
|
|
|
|
0
|
|
287
|
|
|
|
|
|
|
# @{ $self->{gone} } = @nonreturnees; |
288
|
0
|
|
|
|
|
0
|
$self->{gone} = \@nonreturnees; |
289
|
0
|
|
|
|
|
0
|
return @nonreturnees; |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
#my @updatedlist = grep { $_->id != $returnee->id } @$emigrants; |
292
|
|
|
|
|
|
|
#$self->emigrants($_) for @updatedlist; |
293
|
|
|
|
|
|
|
#return @updatedlist if grep { $_->id == $returnee->id } @$emigrants; |
294
|
0
|
|
|
|
|
0
|
return; |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
=head2 dissolved |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
$group->dissolved(1) |
302
|
|
|
|
|
|
|
$s1 = $group->s1($players) |
303
|
|
|
|
|
|
|
$s1 = $group->s1 |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
Dissolve a bracket, so it is no longer independent, its affairs being controlled by some other group: |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
=cut |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
sub dissolved { |
310
|
6941
|
|
|
6941
|
1
|
8718
|
my $self = shift; |
311
|
6941
|
|
|
|
|
8058
|
my $flag = shift; |
312
|
6941
|
100
|
|
|
|
11299
|
if ( defined $flag ) |
313
|
|
|
|
|
|
|
{ |
314
|
64
|
|
|
|
|
148
|
$self->{dissolved} = $flag; |
315
|
64
|
50
|
|
|
|
205
|
return $flag? 1: 0; |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
else { |
318
|
6877
|
100
|
|
|
|
25175
|
return $self->{dissolved}? 1: 0; |
319
|
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=head2 s1 |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
$group->s1 |
326
|
|
|
|
|
|
|
$s1 = $group->s1($players) |
327
|
|
|
|
|
|
|
$s1 = $group->s1 |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
Getter/setter of the p players in the top half of a homogeneous bracket, or the p downFloaters in a heterogeneous bracket, as an array. A6 |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=cut |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
sub s1 { |
334
|
7091
|
|
|
7091
|
1
|
9016
|
my $self = shift; |
335
|
7091
|
|
|
|
|
8492
|
my $s1 = shift; |
336
|
7091
|
100
|
|
|
|
16947
|
if ( defined $s1 ) { |
|
|
100
|
|
|
|
|
|
337
|
1984
|
|
|
|
|
3123
|
$self->{s1} = $s1; |
338
|
1984
|
|
|
|
|
3859
|
return $s1; |
339
|
|
|
|
|
|
|
} |
340
|
5099
|
|
|
|
|
11437
|
elsif ( $self->{s1} ) { return $self->{s1}; } |
341
|
8
|
|
|
|
|
26
|
else { $self->resetS12; return $self->{s1}; } |
|
8
|
|
|
|
|
28
|
|
342
|
|
|
|
|
|
|
} |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
=head2 s2 |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
$s2 = $group->s2 |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
Getter/Setter of the players in a homogeneous or a heterogeneous bracket who aren't in S1. A6 |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=cut |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
sub s2 { |
354
|
11675
|
|
|
11675
|
1
|
15191
|
my $self = shift; |
355
|
11675
|
|
|
|
|
13968
|
my $s2 = shift; |
356
|
11675
|
100
|
|
|
|
27016
|
if ( defined $s2 ) { |
|
|
50
|
|
|
|
|
|
357
|
3233
|
|
|
|
|
4724
|
$self->{s2} = $s2; |
358
|
3233
|
|
|
|
|
5976
|
return $s2; |
359
|
|
|
|
|
|
|
} |
360
|
8442
|
|
|
|
|
18645
|
elsif ( $self->{s2} ) { return $self->{s2}; } |
361
|
0
|
|
|
|
|
0
|
else { $self->resetS12; return $self->{s2}; } |
|
0
|
|
|
|
|
0
|
|
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
=head2 resetS12 |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
$group->resetS12 |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
Resetter of S1 and S2 to the original members, ranked before exchanges in C8. A6 |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
=cut |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
sub resetS12 { |
374
|
1186
|
|
|
1186
|
1
|
1756
|
my $self = shift; |
375
|
1186
|
|
|
|
|
2379
|
my $number = $self->number; |
376
|
1186
|
|
|
|
|
2739
|
my $members = $self->residents; |
377
|
1186
|
50
|
|
|
|
2859
|
return [] unless $#$members >= 1; |
378
|
1186
|
|
|
|
|
1476
|
my (@s1, @s2); |
379
|
26
|
|
|
26
|
|
51332
|
use Games::Tournament; |
|
26
|
|
|
|
|
48
|
|
|
26
|
|
|
|
|
127602
|
|
380
|
1186
|
100
|
|
|
|
2620
|
if ( $self->hetero ) { |
381
|
149
|
|
|
|
|
205
|
my %scorers; |
382
|
149
|
|
|
|
|
369
|
for my $member (@$members) |
383
|
|
|
|
|
|
|
{ |
384
|
694
|
100
|
|
|
|
1752
|
my $score = defined $member->score? $member->score: 0; |
385
|
694
|
|
|
|
|
1694
|
push @{ $scorers{$score} }, $member; |
|
694
|
|
|
|
|
1967
|
|
386
|
|
|
|
|
|
|
} |
387
|
149
|
|
|
|
|
511
|
my @scores = reverse sort { $a <=> $b } keys %scorers; |
|
161
|
|
|
|
|
685
|
|
388
|
|
|
|
|
|
|
#carp @scores . " different scores in Hetero Bracket $number" |
389
|
|
|
|
|
|
|
# if @scores > 2; |
390
|
149
|
|
|
|
|
216
|
@s2 = @{$scorers{$scores[-1]}}; |
|
149
|
|
|
|
|
414
|
|
391
|
149
|
|
|
|
|
253
|
my %s2 = map { $_->pairingNumber => $_ } @s2; |
|
509
|
|
|
|
|
1278
|
|
392
|
149
|
|
|
|
|
604
|
@s1 = grep { not exists $s2{$_->pairingNumber} } $self->rank(@$members); |
|
694
|
|
|
|
|
1600
|
|
393
|
|
|
|
|
|
|
} |
394
|
|
|
|
|
|
|
else { |
395
|
1037
|
|
|
|
|
2324
|
my $p = $self->p; |
396
|
1037
|
|
|
|
|
4115
|
@s1 = ( $self->rank(@$members) )[ 0 .. $p - 1 ]; |
397
|
1037
|
|
|
|
|
6358
|
@s2 = ( $self->rank(@$members) )[ $p .. $#$members ]; |
398
|
|
|
|
|
|
|
} |
399
|
1186
|
|
|
|
|
6275
|
$self->s1(\@s1); |
400
|
1186
|
|
|
|
|
2752
|
$self->s2(\@s2); |
401
|
1186
|
|
|
|
|
2141
|
my @lastS2ids = reverse map { $_->pairingNumber } @s2; |
|
3167
|
|
|
|
|
7723
|
|
402
|
1186
|
|
|
|
|
2278
|
$self->{lastS2ids} = \@lastS2ids; |
403
|
1186
|
50
|
|
5684
|
|
5333
|
die "undef player in Bracket $number S1, S2" if any { not defined } @s1, @s2; |
|
5684
|
|
|
|
|
7763
|
|
404
|
1186
|
|
|
|
|
4670
|
return; |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
=head2 resetShuffler |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
$previous->entry($_) for @returnees; |
411
|
|
|
|
|
|
|
$previous->resetShuffler; |
412
|
|
|
|
|
|
|
return C7; |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
Take precautions to prevent transposing players who are no longer in the bracket in S2, or to make sure they ARE transposed, when finding a different pairing, before returning from C10,12,13 (C11?). Do this by resetting S1 and S2. Don't use this in the wrong place. We don't want to try the same pairing twice. |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
=cut |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
sub resetShuffler { |
419
|
60
|
|
|
60
|
1
|
98
|
my $self = shift; |
420
|
60
|
|
|
|
|
117
|
my $members = $self->members; |
421
|
60
|
|
|
|
|
140
|
my $s1 = $self->s1; |
422
|
60
|
|
|
|
|
136
|
my $s2 = $self->s2; |
423
|
60
|
|
|
|
|
114
|
my %s1 = map { $_->pairingNumber => $_ } @$s1; |
|
65
|
|
|
|
|
181
|
|
424
|
60
|
|
|
|
|
138
|
my %s2 = map { $_->pairingNumber => $_ } @$s2; |
|
152
|
|
|
|
|
364
|
|
425
|
60
|
|
|
|
|
144
|
my %members = map { $_->pairingNumber => $_ } @$members; |
|
219
|
|
|
|
|
463
|
|
426
|
|
|
|
|
|
|
# my %tally; @tally{keys %members} = (0) x keys %members; |
427
|
65
|
|
|
65
|
|
398
|
my $memberChangeTest = ( (notall { exists $members{$_} } keys %s1) or |
428
|
60
|
|
66
|
152
|
|
351
|
(notall { exists $members{$_} } keys %s2) or (@$s1 + @$s2 != @$members)); |
|
152
|
|
|
|
|
472
|
|
429
|
60
|
100
|
|
|
|
421
|
$self->resetS12 if $memberChangeTest; |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
=head2 p |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
$tables = $group->p |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
Half the number of players in a homogeneous bracket, rounded down to the next lowest integer. Or the number of down floaters in a heterogeneous bracket. Also the number of players in S1, and thus the number of pairings in the pair group. If there are more downfloaters than original members, half the number of players. (See A1,2)A6 |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
=cut |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
sub p { |
442
|
3567
|
|
|
3567
|
1
|
4472
|
my $self = shift; |
443
|
3567
|
|
|
|
|
6732
|
my $members = $self->members; |
444
|
3567
|
|
|
|
|
5370
|
my $n = @$members; |
445
|
3567
|
50
|
|
|
|
7254
|
return 0 unless $n >= 2; |
446
|
3567
|
|
|
|
|
3798
|
my $p; |
447
|
3567
|
100
|
|
|
|
6947
|
if ( $self->hetero ) { |
448
|
378
|
|
|
|
|
438
|
my %scorers; |
449
|
378
|
|
|
|
|
694
|
for my $member ( @$members ) { |
450
|
1926
|
100
|
|
|
|
4862
|
my $score = defined $member->score? $member->score: 0; |
451
|
1926
|
|
|
|
|
6685
|
$scorers{$score}++; |
452
|
|
|
|
|
|
|
} |
453
|
378
|
|
|
|
|
1412
|
my $lowestScore = min keys %scorers; |
454
|
378
|
50
|
|
|
|
895
|
return unless defined $lowestScore; |
455
|
378
|
|
|
|
|
565
|
$p = $n - $scorers{$lowestScore}; |
456
|
378
|
50
|
|
|
|
1218
|
$p = int( $n / 2 ) if $p > $n/2; |
457
|
|
|
|
|
|
|
} |
458
|
|
|
|
|
|
|
else { |
459
|
3189
|
|
|
|
|
5677
|
$p = int( $n / 2 ); |
460
|
|
|
|
|
|
|
} |
461
|
3567
|
|
|
|
|
7291
|
return $p; |
462
|
|
|
|
|
|
|
} |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
=head2 bigGroupP |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
$tables = $group->bigGroupP |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
Half the number of players in a big bracket (group), rounded down to the next lowest integer. Sometimes the number of pairs in a combined bracket, particularly, a heterogeneous bracket and its remainder group is needed. In such cases, p will be just the number of downfloated players, which is not what we want. In a non-heterogeneous bracket, bigGroupP will be the same as p. See C11 |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
=cut |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
sub bigGroupP { |
474
|
29
|
|
|
29
|
1
|
44
|
my $self = shift; |
475
|
29
|
|
|
|
|
62
|
my $members = $self->members; |
476
|
29
|
|
|
|
|
49
|
my $n = @$members; |
477
|
29
|
100
|
|
|
|
195
|
if ( $self->{remainderof} ) |
|
|
50
|
|
|
|
|
|
478
|
|
|
|
|
|
|
{ |
479
|
17
|
|
|
|
|
47
|
my $remaindered = $self->{remainderof}->members; |
480
|
17
|
|
|
|
|
36
|
$n += @$remaindered; |
481
|
|
|
|
|
|
|
} |
482
|
|
|
|
|
|
|
elsif ( $self->{remaindered} ) { |
483
|
0
|
|
|
|
|
0
|
my $heteroMembers = $self->{remainder}->members; |
484
|
0
|
|
|
|
|
0
|
$n += @$heteroMembers; |
485
|
|
|
|
|
|
|
} |
486
|
29
|
50
|
|
|
|
84
|
return 0 unless $n >= 2; |
487
|
29
|
|
|
|
|
58
|
my $p = int( $n / 2 ); |
488
|
29
|
|
|
|
|
84
|
return $p; |
489
|
|
|
|
|
|
|
} |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
=head2 pprime |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
$tables = $group->pprime |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
p is half the number of players in a bracket, but we may have to accept fewer pairings than this number if suitable opponents cannot be found for players, up to the point where p=0. pprime sets/gets this real p number. A8 |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
=cut |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
sub pprime { |
501
|
2079
|
|
|
2079
|
1
|
3112
|
my ( $self, $p ) = @_; |
502
|
2079
|
|
|
|
|
3053
|
my $pprime = $self->{pprime}; |
503
|
2079
|
100
|
|
|
|
5020
|
if ( defined $p ) { $self->{pprime} = $p; } |
|
192
|
100
|
|
|
|
556
|
|
504
|
1880
|
|
|
|
|
4191
|
elsif ( defined $pprime ) { return $pprime; } |
505
|
|
|
|
|
|
|
else { |
506
|
7
|
|
|
|
|
21
|
$self->{pprime} = $self->p; |
507
|
7
|
|
|
|
|
24
|
return $self->{pprime}; |
508
|
|
|
|
|
|
|
} |
509
|
|
|
|
|
|
|
} |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
=head2 bigGroupPprime |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
$tables = $group->bigGroupPprime |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
bigGroupP is half the number of players in a heterogeneous bracket and its remainder group, but we may have to accept fewer pairings than this number if suitable opponents cannot be found for players, up to the point where no players are paired. bigGroupPprime sets/gets this real p number for the combined groups/brackets. A8 |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
=cut |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
sub bigGroupPprime { |
521
|
37
|
|
|
37
|
1
|
72
|
my ( $self, $p ) = @_; |
522
|
37
|
|
|
|
|
79
|
my $bigGroupPprime = $self->{biggrouppprime}; |
523
|
37
|
50
|
|
|
|
141
|
if ( defined $p ) { |
|
|
100
|
|
|
|
|
|
524
|
0
|
|
|
|
|
0
|
$self->{biggrouppprime} = $p; |
525
|
0
|
0
|
|
|
|
0
|
if ( $self->{remainderof} ) { |
|
|
0
|
|
|
|
|
|
526
|
0
|
|
|
|
|
0
|
$self->{remainderof}->{biggrouppprime} = $p; |
527
|
|
|
|
|
|
|
} |
528
|
|
|
|
|
|
|
elsif ( $self->{remainder} ) { |
529
|
0
|
|
|
|
|
0
|
$self->{remainder}->{biggrouppprime} = $p; |
530
|
|
|
|
|
|
|
} |
531
|
0
|
|
|
|
|
0
|
return; |
532
|
|
|
|
|
|
|
} |
533
|
8
|
|
|
|
|
28
|
elsif ( defined $bigGroupPprime ) { return $bigGroupPprime; } |
534
|
|
|
|
|
|
|
else { |
535
|
29
|
|
|
|
|
79
|
$self->{biggrouppprime} = $self->bigGroupP; |
536
|
29
|
|
|
|
|
90
|
return $self->{biggrouppprime}; |
537
|
|
|
|
|
|
|
} |
538
|
|
|
|
|
|
|
} |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
=head2 q |
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
$tables = $group->q |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
Number of players in the score bracket divided by 2 and then rounded up. In a homogeneous group with an even number of players, this is the same as p. A8 |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
=cut |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
sub q { |
550
|
322
|
|
|
322
|
1
|
424
|
my $self = shift; |
551
|
322
|
|
|
|
|
634
|
my $players = $self->members; |
552
|
322
|
100
|
|
|
|
1278
|
my $q = @$players % 2 ? ( $#$players + 2 ) / 2 : ( $#$players + 1 ) / 2; |
553
|
|
|
|
|
|
|
} |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
=head2 x |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
$tables = $group->x |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
Sets the number, ranging from zero to p, of matches in the score bracket in which players will have their preferences unsatisfied. A8 |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
=cut |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
sub x { |
565
|
229
|
|
|
229
|
1
|
342
|
my $self = shift; |
566
|
229
|
|
|
|
|
509
|
my $players = $self->residents; |
567
|
|
|
|
|
|
|
my $numbers = sub { |
568
|
458
|
|
|
458
|
|
620
|
my $n = shift; |
569
|
|
|
|
|
|
|
return scalar grep { |
570
|
458
|
100
|
|
|
|
713
|
$_->preference->role and $_->preference->role eq (ROLES)[$n] } |
|
1894
|
|
|
|
|
4846
|
|
571
|
|
|
|
|
|
|
@$players; |
572
|
229
|
|
|
|
|
815
|
}; |
573
|
229
|
|
|
|
|
580
|
my $w = $numbers->(0); |
574
|
229
|
|
|
|
|
494
|
my $b = $numbers->(1); |
575
|
229
|
|
|
|
|
624
|
my $q = $self->q; |
576
|
229
|
100
|
|
|
|
630
|
my $x = $w >= $b ? $w - $q : $b - $q; |
577
|
229
|
100
|
|
|
|
1641
|
$self->{x} = $x < 0? 0: $x; |
578
|
|
|
|
|
|
|
} |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
=head2 bigGroupX |
582
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
$tables = $group->bigGroupX |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
x is okay for a homogeneous group, uncombined with other groups, but in the case of groups that are interacting to form joined brackets, or in that of a heterogeneous bracket and a remainder group, we need a bigGroupX to tell us how many matches in the total number, ranging from zero to bigGroupP, of matches in the score bracket(s) will have players with unsatisfied preferences. A8 |
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
=cut |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
sub bigGroupX { |
590
|
93
|
|
|
93
|
1
|
126
|
my $self = shift; |
591
|
93
|
|
|
|
|
183
|
my $players = $self->members; |
592
|
|
|
|
|
|
|
my $w = |
593
|
93
|
100
|
|
|
|
176
|
grep { $_->preference->role and $_->preference->role eq (ROLES)[0] } |
|
436
|
|
|
|
|
1105
|
|
594
|
|
|
|
|
|
|
@$players; |
595
|
93
|
|
|
|
|
169
|
my $b = @$players - $w; |
596
|
93
|
|
|
|
|
283
|
my $q = $self->q; |
597
|
93
|
100
|
|
|
|
258
|
my $x = $w >= $b ? $w - $q : $b - $q; |
598
|
93
|
|
|
|
|
117
|
my $bigGroupX = $x; |
599
|
93
|
50
|
|
|
|
330
|
if ( $self->{remainderof} ) { $bigGroupX += $self->{remainderof}->x; } |
|
0
|
50
|
|
|
|
0
|
|
600
|
0
|
|
|
|
|
0
|
elsif ( $self->{remainder} ) { $bigGroupX += $self->{remainder}->x; } |
601
|
93
|
|
|
|
|
176
|
$self->{biggroupx} = $bigGroupX; |
602
|
93
|
|
|
|
|
395
|
return $self->{biggroupx}; |
603
|
|
|
|
|
|
|
} |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
=head2 bigGroupXprime |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
$tables = $group->bigGroupXprime |
609
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
xprime is a revised upper limit on matches where preferences are not satisfied, but in the case of a combined bracket (in particular, a heterogeneous bracket and a remainder group) we need a figure for the total number of preference-violating matches over the 2 sections, because the distribution of such matches may change. bigGroupXprime sets/gets this total x number. A8 |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
=cut |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
sub bigGroupXprime { |
615
|
244
|
|
|
244
|
1
|
363
|
my $self = shift; |
616
|
244
|
|
|
|
|
300
|
my $x = shift; |
617
|
244
|
|
|
|
|
382
|
my $xprime = $self->{biggroupxprime}; |
618
|
244
|
100
|
|
|
|
694
|
if ( defined $x ) { |
|
|
100
|
|
|
|
|
|
619
|
5
|
|
|
|
|
12
|
$self->{biggroupxprime} = $x; |
620
|
5
|
50
|
|
|
|
24
|
if ( $self->{remainderof} ) { |
|
|
50
|
|
|
|
|
|
621
|
0
|
|
|
|
|
0
|
$self->{remainderof}->{biggroupxprime} = $x; |
622
|
|
|
|
|
|
|
} |
623
|
|
|
|
|
|
|
elsif ( $self->{remainder} ) { |
624
|
5
|
|
|
|
|
13
|
$self->{remainder}->{biggroupxprime} = $x |
625
|
|
|
|
|
|
|
} |
626
|
5
|
|
|
|
|
13
|
return; } |
627
|
72
|
|
|
|
|
243
|
elsif ( defined $xprime ) { return $xprime; } |
628
|
|
|
|
|
|
|
else { |
629
|
167
|
100
|
|
|
|
561
|
if ( $self->{remainderof} ) { |
|
|
100
|
|
|
|
|
|
630
|
21
|
|
|
|
|
48
|
my $x = $self->{remainderof}->{biggroupxprime}; |
631
|
21
|
100
|
|
|
|
93
|
return $x if defined $x; |
632
|
|
|
|
|
|
|
} |
633
|
|
|
|
|
|
|
elsif ( $self->{remainder} ) { |
634
|
53
|
|
|
|
|
99
|
$x = $self->{remainder}->{biggroupxprime}; |
635
|
53
|
50
|
|
|
|
285
|
return $x if defined $x; |
636
|
|
|
|
|
|
|
} |
637
|
93
|
|
|
|
|
247
|
else { return $self->bigGroupX; } |
638
|
|
|
|
|
|
|
} |
639
|
|
|
|
|
|
|
} |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
=head2 xprime |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
$tables = $group->xprime |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
x is the lower limit on matches where preferences are not satisfied, but the number of such undesirable matches may be increased if suitable opponents cannot be found for players, up to the point where only players with Absolute preferences have their preferences satisfied. xprime sets/gets this real x number. A8 |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
=cut |
649
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
sub xprime { |
651
|
1716
|
|
|
1716
|
1
|
2375
|
my $self = shift; |
652
|
1716
|
|
|
|
|
2072
|
my $x = shift; |
653
|
1716
|
|
|
|
|
2577
|
my $xprime = $self->{xprime}; |
654
|
1716
|
100
|
|
|
|
4241
|
if ( defined $x ) { $self->{xprime} = $x; return; } |
|
77
|
100
|
|
|
|
134
|
|
|
77
|
|
|
|
|
170
|
|
655
|
1553
|
|
|
|
|
3683
|
elsif ( defined $xprime ) { return $xprime; } |
656
|
|
|
|
|
|
|
else { |
657
|
86
|
|
|
|
|
188
|
$self->{xprime} = $self->x; |
658
|
86
|
|
|
|
|
346
|
return $self->{xprime}; |
659
|
|
|
|
|
|
|
} |
660
|
|
|
|
|
|
|
} |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
=head2 floatCheckWaive |
664
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
$tables = $group->floatCheckWaive |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
There is an ordered sequence in which the checks of compliance with the Relative Criteria B5,6 restriction on recurring floats are relaxed in C9,10. The order is 1. downfloats for players downfloated 2 rounds before, 2. downfloats for players downfloated in the previous round (in C9), 3. upfloats for players floated up 2 rounds before, 4. upfloats for players floated up in the previous round (for players paired with opponents from a higher bracket in a heterogeneous bracket, in C10). (It appears levels are being skipped, eg from B6Down to B6Up or from All to B6Down.) Finally, although it is not explicitly stated, all float checks must be dropped and pairings considered again, before reducing the number of pairs made in the bracket. (This is not entirely correct.) This method sets/gets the float check waive level at the moment. All criteria below that level should be checked for compliance. The possible values in order are 'None', 'B6Down', 'B5Down', 'B6Up', 'B5Up', 'All'. TODO Should there be some way of not requiring the caller to know how to use this method and what the levels are. |
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
=cut |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
sub floatCheckWaive { |
672
|
1187
|
|
|
1187
|
1
|
1559
|
my $self = shift; |
673
|
1187
|
|
|
|
|
2366
|
my $number = $self->number; |
674
|
1187
|
|
|
|
|
1818
|
my $level = shift; |
675
|
1187
|
50
|
66
|
|
|
3928
|
warn "Unknown float level: $level" if |
676
|
|
|
|
|
|
|
$level and $level !~ m/^(?:None|B6Down|B5Down|B6Up|B5Up|All)$/i; |
677
|
1187
|
|
|
|
|
1838
|
my $oldLevel = $self->{floatCheck}; |
678
|
1187
|
100
|
|
|
|
2912
|
if ( defined $level ) { |
|
|
50
|
|
|
|
|
|
679
|
222
|
50
|
66
|
|
|
2443
|
warn |
|
|
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
680
|
|
|
|
|
|
|
"Bracket [$number]'s old float check waive level, $oldLevel is now $level." |
681
|
|
|
|
|
|
|
unless $level eq 'None' or |
682
|
|
|
|
|
|
|
$oldLevel eq 'None' and $level eq 'B6Down' or |
683
|
|
|
|
|
|
|
$oldLevel eq 'B6Down' and $level eq 'B5Down' or |
684
|
|
|
|
|
|
|
$oldLevel eq 'B6Down' and $level eq 'B6Up' or |
685
|
|
|
|
|
|
|
$oldLevel eq 'B5Down' and $level eq 'B6Up' or |
686
|
|
|
|
|
|
|
$oldLevel eq 'B6Up' and $level eq 'B5Up' or |
687
|
|
|
|
|
|
|
$oldLevel eq 'B5Up' and $level eq 'All' or |
688
|
|
|
|
|
|
|
# $oldLevel eq 'B5Down' and $level eq 'All' or |
689
|
|
|
|
|
|
|
$oldLevel eq 'All' and $level eq 'None' or |
690
|
|
|
|
|
|
|
$oldLevel eq 'All' and $level eq 'B6Down'; |
691
|
222
|
|
|
|
|
624
|
$self->{floatCheck} = $level; |
692
|
|
|
|
|
|
|
} |
693
|
965
|
|
|
|
|
4318
|
elsif ( defined $self->{floatCheck} ) { return $self->{floatCheck}; } |
694
|
0
|
|
|
|
|
0
|
else { return; } |
695
|
|
|
|
|
|
|
} |
696
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
=head2 hetero |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
$group->hetero |
701
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
Gets (but doesn't set) whether this group is heterogeneous, ie includes players who have been downfloated from a higher score group, or upfloated from a lower score group, or if it is homogeneous, ie every player has the same score. A group where half or more of the members have come from a higher bracket is regarded as homogeneous. We use the scores of the players, rather than a floating flag. |
703
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
=cut |
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
sub hetero { |
707
|
6964
|
|
|
6964
|
1
|
8810
|
my $self = shift; |
708
|
6964
|
|
|
|
|
7716
|
my @members = @{$self->members}; |
|
6964
|
|
|
|
|
12626
|
|
709
|
6964
|
|
|
|
|
9161
|
my %tally; |
710
|
6964
|
|
|
|
|
10848
|
for my $member ( @members ) { |
711
|
33576
|
100
|
|
|
|
83242
|
my $score = defined $member->score? $member->score: 0; |
712
|
33576
|
|
|
|
|
109379
|
$tally{$score}++ ; |
713
|
|
|
|
|
|
|
} |
714
|
6964
|
|
|
|
|
15677
|
my @range = keys %tally; |
715
|
6964
|
100
|
|
|
|
31932
|
return 0 if @range == 1; |
716
|
1773
|
|
|
|
|
6034
|
my $min = min @range; |
717
|
1773
|
50
|
|
|
|
3529
|
return unless defined $min; |
718
|
1773
|
100
|
|
|
|
7262
|
return 0 if $tally{$min} <= @members/2; |
719
|
1116
|
50
|
|
|
|
7397
|
return 1 if $tally{$min} > @members/2; |
720
|
0
|
|
|
|
|
0
|
return; |
721
|
|
|
|
|
|
|
} |
722
|
|
|
|
|
|
|
|
723
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
=head2 trueHetero |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
$group->trueHetero |
727
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
Gets whether this group is really heterogeneous, ie includes players with different scores, because they been downfloated from a higher score group, or upfloated from a lower score group, even if it is being treated as homogeneous. A group where half or more of the members have come from a higher bracket is regarded as homogeneous, but it is really heterogeneous. |
729
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
=cut |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
sub trueHetero { |
733
|
1
|
|
|
1
|
1
|
2
|
my $self = shift; |
734
|
1
|
|
|
|
|
3
|
my @members = @{$self->members}; |
|
1
|
|
|
|
|
12
|
|
735
|
1
|
|
|
|
|
3
|
my %tally; |
736
|
1
|
|
|
|
|
2
|
for my $member ( @members ) { |
737
|
3
|
50
|
|
|
|
10
|
my $score = defined $member->score? $member->score: 0; |
738
|
3
|
|
|
|
|
13
|
$tally{$score}++; |
739
|
|
|
|
|
|
|
} |
740
|
1
|
|
|
|
|
4
|
my @range = keys %tally; |
741
|
1
|
50
|
|
|
|
4
|
return unless @range; |
742
|
1
|
50
|
|
|
|
3
|
return 0 if @range == 1; |
743
|
1
|
|
|
|
|
6
|
return 1; |
744
|
|
|
|
|
|
|
} |
745
|
|
|
|
|
|
|
|
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
=head2 c7shuffler |
748
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
$nextS2 = $bracket->c7shuffler($firstmismatch) |
750
|
|
|
|
|
|
|
if ( @nextS2 compatible ) |
751
|
|
|
|
|
|
|
{ |
752
|
|
|
|
|
|
|
create match cards; |
753
|
|
|
|
|
|
|
} |
754
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
Gets the next permutation of the second-half players in D1 transposition counting order, as used in C7, that will not have the same incompatible player in the bad position found in the present transposition. If you get an illegal modulus error, check your $firstmismatch is a possible value. |
756
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
=cut |
758
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
sub c7shuffler { |
760
|
1719
|
|
|
1719
|
1
|
3510
|
my $self = shift; |
761
|
1719
|
|
|
|
|
2105
|
my $position = shift; |
762
|
1719
|
|
|
|
|
2024
|
my $bigLastGroup = shift; |
763
|
1719
|
|
|
|
|
3232
|
my $s2 = $self->s2; |
764
|
1719
|
50
|
|
|
|
4061
|
die "C7 shuffle: pos $position past end of S2" if $position > $#$s2; |
765
|
1719
|
|
|
|
|
4765
|
my @players = $self->rank(@$s2); |
766
|
1719
|
50
|
|
|
|
8532
|
@players = $self->reverseRank(@$s2) if $bigLastGroup; |
767
|
|
|
|
|
|
|
# my @players = @$s2; |
768
|
1719
|
|
|
|
|
3752
|
my $p = $self->p; |
769
|
1719
|
|
|
|
|
2211
|
my @pattern; |
770
|
1719
|
|
|
|
|
3189
|
my @copy = @players; |
771
|
1719
|
|
|
|
|
3852
|
for my $i ( 0 .. $#$s2 ) { |
772
|
5381
|
|
|
|
|
6269
|
my $j = 0; |
773
|
5381
|
|
|
|
|
14188
|
$j++ until $s2->[$i]->pairingNumber == $copy[$j]->pairingNumber; |
774
|
5381
|
|
|
|
|
7852
|
$pattern[$i] = $j; |
775
|
5381
|
|
|
|
|
9677
|
splice @copy, $j, 1; |
776
|
|
|
|
|
|
|
} |
777
|
1719
|
|
|
|
|
2702
|
my $value = $pattern[$position]; |
778
|
1719
|
|
|
|
|
1900
|
my @nextPattern; |
779
|
1719
|
|
|
|
|
4175
|
@nextPattern[ 0 .. $position ] = @pattern[ 0 .. $position ]; |
780
|
1719
|
|
|
|
|
4382
|
@nextPattern[ $position + 1 .. $#pattern ] = |
781
|
|
|
|
|
|
|
(0) x ( $#pattern - $position ); |
782
|
1719
|
|
|
|
|
3238
|
for my $digit ( reverse( 0 .. $position ) ) { |
783
|
2730
|
50
|
|
|
|
5701
|
die "${digit}th digit overrun of @pattern \@pattern" if |
784
|
|
|
|
|
|
|
@pattern == $digit; |
785
|
2730
|
|
|
|
|
4574
|
$nextPattern[$digit] = ++$value % ( @pattern - $digit ); |
786
|
2730
|
100
|
|
|
|
6715
|
last unless $nextPattern[$digit] == 0; |
787
|
|
|
|
|
|
|
} |
788
|
1481
|
|
|
|
|
2729
|
continue { $value = $pattern[ $digit - 1 ]; } |
789
|
1719
|
100
|
|
|
|
2840
|
return unless grep { $_ } @nextPattern; |
|
5381
|
|
|
|
|
10586
|
|
790
|
1249
|
|
|
|
|
1392
|
my @permutation; |
791
|
1249
|
|
|
|
|
1930
|
for my $pos (@nextPattern) { |
792
|
4259
|
|
|
|
|
7234
|
push @permutation, splice( @players, $pos, 1 ); |
793
|
|
|
|
|
|
|
} |
794
|
1249
|
|
|
|
|
5423
|
return @permutation; |
795
|
|
|
|
|
|
|
|
796
|
|
|
|
|
|
|
#my @selectS2 = $group->c7shuffler($badpair); |
797
|
|
|
|
|
|
|
#my @unselectS2 = @$s2; |
798
|
|
|
|
|
|
|
#for my $position ( 0 .. $#$s2 ) |
799
|
|
|
|
|
|
|
#{ |
800
|
|
|
|
|
|
|
# my $player = $s2->[$#$s2 - $position]; |
801
|
|
|
|
|
|
|
# splice @unselectS2, $#$s2 - $position, 1 if grep{$_ eq $player} @selectS2; |
802
|
|
|
|
|
|
|
#} |
803
|
|
|
|
|
|
|
#my @newS2 = (@selectS2, @unselectS2); |
804
|
|
|
|
|
|
|
} |
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
=head2 c7iterator |
808
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
$next = $bracket->c7iterator |
810
|
|
|
|
|
|
|
while ( my @s2 = &$next ) |
811
|
|
|
|
|
|
|
{ |
812
|
|
|
|
|
|
|
create match cards unless this permutation is incompatible; |
813
|
|
|
|
|
|
|
} |
814
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
DEPRECATED Creates an iterator for the permutation of the second-half players in D1 transposition counting order, as used in C7. Only as many players as are in S1 can be matched, so we get only the permutations of all the p-length combinations of members of S2. Deprecated because if C1 or C6 finds a player in a certain position in S2 should not be paired with the player in the corresponding position in S1, we need to be able to skip ahead to the next permutation where a different player is in that position. |
816
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
=cut |
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
sub c7iterator { |
820
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
821
|
0
|
|
|
|
|
0
|
my $players = $self->s2; |
822
|
0
|
|
|
|
|
0
|
my $p = $self->p; |
823
|
0
|
|
|
|
|
0
|
my $n = 0; |
824
|
|
|
|
|
|
|
return sub { |
825
|
0
|
|
|
0
|
|
0
|
my @pattern = n_to_pat->( $n, $#$players + 1, $p ); |
826
|
0
|
|
|
|
|
0
|
my @result = permGenerator->( \@pattern, $players ); |
827
|
0
|
|
|
|
|
0
|
print "transposition $n:\t"; |
828
|
0
|
|
|
|
|
0
|
$n++; |
829
|
0
|
|
|
|
|
0
|
return @result; |
830
|
0
|
|
|
|
|
0
|
}; |
831
|
|
|
|
|
|
|
my $permGenerator = sub { |
832
|
0
|
|
|
0
|
|
0
|
my $pattern = shift; |
833
|
0
|
|
|
|
|
0
|
my @items = @{ shift() }; |
|
0
|
|
|
|
|
0
|
|
834
|
0
|
|
|
|
|
0
|
my @r; |
835
|
0
|
|
|
|
|
0
|
for my $pos (@$pattern) { |
836
|
0
|
|
|
|
|
0
|
push @r, splice( @items, $pos, 1 ); |
837
|
|
|
|
|
|
|
} |
838
|
0
|
|
|
|
|
0
|
return @r; |
839
|
0
|
|
|
|
|
0
|
}; |
840
|
|
|
|
|
|
|
my $n_to_pat = sub { |
841
|
0
|
|
|
0
|
|
0
|
my @odometer; |
842
|
0
|
|
|
|
|
0
|
my ( $n, $length, $k ) = @_; |
843
|
0
|
|
|
|
|
0
|
for my $i ( $length - $k + 1 .. $length ) { |
844
|
0
|
|
|
|
|
0
|
unshift @odometer, $n % $i; |
845
|
0
|
|
|
|
|
0
|
$n = int( $n / $i ); |
846
|
|
|
|
|
|
|
} |
847
|
0
|
0
|
|
|
|
0
|
return $n ? () : @odometer; |
848
|
0
|
|
|
|
|
0
|
}; |
849
|
|
|
|
|
|
|
} |
850
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
=head2 c8iterator |
853
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
$next = $bracket->c8iterator |
855
|
|
|
|
|
|
|
while ( my @members = &$next ) |
856
|
|
|
|
|
|
|
{ |
857
|
|
|
|
|
|
|
next if grep {$incompat{$s1[$_]}{$s2[$_]}} 0..$p-1); |
858
|
|
|
|
|
|
|
} |
859
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
Creates an iterator for the exchange of @s1 and @s2 players in D2 order, as used in C8. Exchanges are performed in order of the difference between the pairing numbers of the players exchanged. If the difference is equal, the exchange with the lowest player is to be performed first. XXX Only as many players as in S1 can be matched, so does this mean some exchanges don't have an effect? I don't understand the description when there are an odd number of players. There appears to be a bug with only 3 players. 1 and 2 should be swapped, I think. I think the order of exchanges of 2 players each may also have some small inconsistencies with the FIDE order. |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
=cut |
863
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
sub c8iterator { |
865
|
247
|
|
|
247
|
1
|
377
|
my $self = shift; |
866
|
247
|
|
|
|
|
416
|
my $letter = 'a'; |
867
|
247
|
|
|
|
|
569
|
my $p = $self->p; |
868
|
247
|
|
|
|
|
344
|
my $oddBracket = @{$self->members} % 2; |
|
247
|
|
|
|
|
533
|
|
869
|
247
|
|
|
|
|
322
|
my @exchanges; |
870
|
247
|
100
|
|
|
|
640
|
unless ($oddBracket) |
|
|
50
|
|
|
|
|
|
871
|
|
|
|
|
|
|
{ |
872
|
|
|
|
|
|
|
@exchanges = map { |
873
|
162
|
|
|
|
|
464
|
my $i = $_; |
|
189
|
|
|
|
|
251
|
|
874
|
189
|
|
|
|
|
764
|
map { [ [ $_, $_+$i ] ] } |
|
230
|
|
|
|
|
854
|
|
875
|
|
|
|
|
|
|
reverse( ( max 1, $p-$i ) .. ( min $p-1, 2*($p-1)-$i ) ) |
876
|
|
|
|
|
|
|
} ( 1 .. 2*($p-1)-1 ); |
877
|
|
|
|
|
|
|
} |
878
|
|
|
|
|
|
|
elsif ( $oddBracket ) { |
879
|
85
|
|
|
|
|
132
|
my $pPlus = $p+1; |
880
|
|
|
|
|
|
|
@exchanges = map { |
881
|
85
|
|
|
|
|
246
|
my $i = $_; |
|
109
|
|
|
|
|
128
|
|
882
|
109
|
|
|
|
|
476
|
map { [ [ $_-1, $_+$i-1 ] ] } |
|
129
|
|
|
|
|
538
|
|
883
|
|
|
|
|
|
|
reverse( (max 1, $pPlus-$i) .. (min $pPlus-1, 2*($pPlus-1)-$i) ) |
884
|
|
|
|
|
|
|
} ( 1 .. 2*($pPlus-1)-1 ); |
885
|
|
|
|
|
|
|
} |
886
|
247
|
|
|
|
|
335
|
my @exchanges2; |
887
|
247
|
100
|
|
|
|
594
|
unless ($oddBracket) |
|
|
50
|
|
|
|
|
|
888
|
|
|
|
|
|
|
{ |
889
|
|
|
|
|
|
|
my @s1pair = map { |
890
|
162
|
|
|
|
|
340
|
my $i = $_; |
|
33
|
|
|
|
|
44
|
|
891
|
33
|
|
|
|
|
62
|
map { [ $i - $_, $i ] } 1 .. $i - 1 |
|
37
|
|
|
|
|
115
|
|
892
|
|
|
|
|
|
|
} reverse 2 .. $p - 1; |
893
|
|
|
|
|
|
|
my @s2pair = map { |
894
|
162
|
|
|
|
|
349
|
my $i = $_; |
|
33
|
|
|
|
|
46
|
|
895
|
33
|
|
|
|
|
73
|
map { [ $i, $i + $_ ] } 1 .. 2 * ( $p - 1 ) - $i |
|
37
|
|
|
|
|
121
|
|
896
|
|
|
|
|
|
|
} $p .. 2 * ( $p - 1 ) - 1; |
897
|
|
|
|
|
|
|
@exchanges2 = map { |
898
|
162
|
|
|
|
|
419
|
my $i = $_; |
|
44
|
|
|
|
|
55
|
|
899
|
|
|
|
|
|
|
map { |
900
|
44
|
|
|
|
|
211
|
[ |
901
|
73
|
|
|
|
|
422
|
[ $s1pair[$_][0], $s2pair[ $i - $_ ][0] ], |
902
|
|
|
|
|
|
|
[ $s1pair[$_][1], $s2pair[ $i - $_ ][1] ] |
903
|
|
|
|
|
|
|
] |
904
|
|
|
|
|
|
|
} ( max 0, $i - ( $p - 1 ) * ( $p - 2 ) / 2 + 1 ) |
905
|
|
|
|
|
|
|
.. ( min( ( $p - 1 ) * ( $p - 2 ) / 2 - 1, $i ) ) |
906
|
|
|
|
|
|
|
} 0 .. ( $p - 1 ) * ( $p - 2 ) - 2; |
907
|
|
|
|
|
|
|
} |
908
|
|
|
|
|
|
|
elsif ($oddBracket) |
909
|
|
|
|
|
|
|
{ |
910
|
85
|
|
|
|
|
127
|
my $pPlus = $p+1; |
911
|
|
|
|
|
|
|
my @s1pair = map { |
912
|
85
|
|
|
|
|
291
|
my $i = $_; |
|
3
|
|
|
|
|
4
|
|
913
|
3
|
|
|
|
|
4
|
map { [ $i - $_-1, $i-1 ] } 1 .. $i-1 |
|
7
|
|
|
|
|
18
|
|
914
|
|
|
|
|
|
|
} reverse 3 .. $pPlus - 1; |
915
|
|
|
|
|
|
|
my @s2pair = map { |
916
|
85
|
|
|
|
|
189
|
my $i = $_; |
|
12
|
|
|
|
|
19
|
|
917
|
12
|
|
|
|
|
23
|
map { [ $i-1, $i+$_-1 ] } 1 .. 2 * ( $pPlus - 1 ) - $i |
|
16
|
|
|
|
|
50
|
|
918
|
|
|
|
|
|
|
} $pPlus .. 2 * ( $pPlus - 1 ) - 1; |
919
|
|
|
|
|
|
|
@exchanges2 = map { |
920
|
85
|
|
|
|
|
212
|
my $i = $_; |
|
14
|
|
|
|
|
18
|
|
921
|
|
|
|
|
|
|
map { |
922
|
14
|
|
|
|
|
63
|
[ |
923
|
36
|
|
|
|
|
143
|
[ $s1pair[$_][0], $s2pair[ $i - $_ ][0] ], |
924
|
|
|
|
|
|
|
[ $s1pair[$_][1], $s2pair[ $i - $_ ][1] ] |
925
|
|
|
|
|
|
|
] |
926
|
|
|
|
|
|
|
} ( max 0, $i - ( $pPlus - 1 ) * ( $pPlus - 2 ) / 2 + 1 ) |
927
|
|
|
|
|
|
|
.. ( min( ( $pPlus - 1 ) * ( $pPlus - 2 ) / 2 - 2, $i ) ) |
928
|
|
|
|
|
|
|
} 0 .. ( $pPlus - 1 ) * ( $pPlus - 2 ) - 3; |
929
|
|
|
|
|
|
|
} |
930
|
247
|
|
|
|
|
383
|
push @exchanges, @exchanges2; |
931
|
|
|
|
|
|
|
return sub { |
932
|
553
|
|
|
553
|
|
315294
|
my $exchange = shift @exchanges; |
933
|
553
|
100
|
|
|
|
1590
|
return ("last S1,S2 exchange") unless $exchange; |
934
|
376
|
|
|
|
|
933
|
$self->resetS12; |
935
|
376
|
|
|
|
|
820
|
my $s1 = $self->s1; |
936
|
376
|
|
|
|
|
768
|
my $s2 = $self->s2; |
937
|
376
|
|
|
|
|
939
|
my @members = (@$s1, @$s2); |
938
|
|
|
|
|
|
|
# my @members = @{ $self->members }; |
939
|
|
|
|
|
|
|
( $members[ $_->[0] ], $members[ $_->[1] ] ) = |
940
|
|
|
|
|
|
|
( $members[ $_->[1] ], $members[ $_->[0] ] ) |
941
|
376
|
|
|
|
|
1809
|
for @$exchange; |
942
|
376
|
|
|
|
|
802
|
my $number = $letter++; |
943
|
|
|
|
|
|
|
die "undef player in exchange $number of S1, S2" if |
944
|
376
|
50
|
|
|
|
1466
|
any { not defined } @members; |
|
2329
|
|
|
|
|
2918
|
|
945
|
376
|
|
|
|
|
2563
|
return "exchange $number", @members; |
946
|
|
|
|
|
|
|
} |
947
|
247
|
|
|
|
|
1722
|
} |
948
|
|
|
|
|
|
|
|
949
|
|
|
|
|
|
|
|
950
|
|
|
|
|
|
|
=head2 score |
951
|
|
|
|
|
|
|
|
952
|
|
|
|
|
|
|
$group->score |
953
|
|
|
|
|
|
|
|
954
|
|
|
|
|
|
|
Gets/sets the score of the score group. |
955
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
=cut |
957
|
|
|
|
|
|
|
|
958
|
|
|
|
|
|
|
sub score { |
959
|
380
|
|
|
380
|
1
|
520
|
my $self = shift; |
960
|
380
|
|
|
|
|
485
|
my $score = shift; |
961
|
380
|
50
|
|
|
|
1119
|
if ( defined $score ) { $self->{score} = $score; } |
|
0
|
50
|
|
|
|
0
|
|
962
|
380
|
|
|
|
|
1435
|
elsif ( exists $self->{score} ) { return $self->{score}; } |
963
|
0
|
|
|
|
|
0
|
return; |
964
|
|
|
|
|
|
|
} |
965
|
|
|
|
|
|
|
|
966
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
=head2 number |
968
|
|
|
|
|
|
|
|
969
|
|
|
|
|
|
|
$group->number |
970
|
|
|
|
|
|
|
|
971
|
|
|
|
|
|
|
Gets/sets the bracket's number, a number from 1 to the number of separate brackets, remainder groups and bye groups in the tournament. Don't use this number for anything important. |
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
=cut |
974
|
|
|
|
|
|
|
|
975
|
|
|
|
|
|
|
sub number { |
976
|
9645
|
|
|
9645
|
1
|
12219
|
my $self = shift; |
977
|
9645
|
|
|
|
|
11854
|
my $number = shift; |
978
|
9645
|
50
|
|
|
|
27414
|
if ( defined $number ) { $self->{number} = $number; } |
|
0
|
100
|
|
|
|
0
|
|
979
|
9494
|
|
|
|
|
20788
|
elsif ( exists $self->{number} ) { return $self->{number}; } |
980
|
151
|
|
|
|
|
285
|
return; |
981
|
|
|
|
|
|
|
} |
982
|
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
=head2 badpair |
985
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
$group->badpair |
987
|
|
|
|
|
|
|
|
988
|
|
|
|
|
|
|
Gets/sets the badpair, the position, counting from zero, of the first pair in S1 and S2 for which pairing failed in a previous attempt in C6. This is the first position at which the next ordering of S2 will differ from the previous one. All orderings between these two orderings will not result in a criteria-compliant pairing. |
989
|
|
|
|
|
|
|
|
990
|
|
|
|
|
|
|
=cut |
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
sub badpair { |
993
|
4315
|
|
|
4315
|
1
|
5462
|
my $self = shift; |
994
|
4315
|
|
|
|
|
5201
|
my $badpair = shift; |
995
|
4315
|
100
|
|
|
|
10818
|
if ( defined $badpair ) { $self->{badpair} = $badpair; } |
|
1384
|
100
|
|
|
|
2341
|
|
996
|
2801
|
|
|
|
|
6046
|
elsif ( defined $self->{badpair} ) { return $self->{badpair}; } |
997
|
1514
|
|
|
|
|
2867
|
return; |
998
|
|
|
|
|
|
|
} |
999
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
=head2 members |
1002
|
|
|
|
|
|
|
|
1003
|
|
|
|
|
|
|
$group->members |
1004
|
|
|
|
|
|
|
|
1005
|
|
|
|
|
|
|
Gets/sets the members of the score group as an anonymous array of player objects. The order of this array is important. The first half is paired with the second half. |
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
=cut |
1008
|
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
|
sub members { |
1010
|
18456
|
|
|
18456
|
1
|
22207
|
my $self = shift; |
1011
|
18456
|
|
|
|
|
21474
|
my $members = shift; |
1012
|
18456
|
100
|
|
|
|
49087
|
if ( defined $members ) { $self->{members} = $members; } |
|
2103
|
100
|
|
|
|
3409
|
|
1013
|
16264
|
|
|
|
|
37510
|
elsif ( $self->{members} ) { return $self->{members}; } |
1014
|
2192
|
|
|
|
|
4390
|
return; |
1015
|
|
|
|
|
|
|
} |
1016
|
|
|
|
|
|
|
|
1017
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
=head2 c8swapper |
1019
|
|
|
|
|
|
|
|
1020
|
|
|
|
|
|
|
$pairing->c8swapper |
1021
|
|
|
|
|
|
|
|
1022
|
|
|
|
|
|
|
Gets/sets an iterator through the different exchanges of players in the two halves of the bracket. |
1023
|
|
|
|
|
|
|
|
1024
|
|
|
|
|
|
|
=cut |
1025
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
sub c8swapper { |
1027
|
973
|
|
|
973
|
1
|
1225
|
my $self = shift; |
1028
|
973
|
|
|
|
|
1288
|
my $c8swapper = shift; |
1029
|
973
|
100
|
|
|
|
2900
|
if ( defined $c8swapper ) { $self->{c8swapper} = $c8swapper; } |
|
223
|
100
|
|
|
|
1152
|
|
1030
|
696
|
|
|
|
|
1960
|
elsif ( $self->{c8swapper} ) { return $self->{c8swapper}; } |
1031
|
|
|
|
|
|
|
} |
1032
|
|
|
|
|
|
|
|
1033
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
=head2 _floatCheck |
1035
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
%b65TestResults = _floatCheck( \@testee, $checkLevels ); |
1037
|
|
|
|
|
|
|
|
1038
|
|
|
|
|
|
|
Takes a list representing the pairing of a bracket (see the description for _getNonPaired), and the various up- and down-float check levels. Returns an anonymous hash with keys: (a) 'badpos', the first element of the list responsible for violation of B6 or 5, if there was a violation of any of the levels, (b) 'passer', an anonymous array of the same form as \@testee, if there was no violation of any of the levels, and (c) 'message', a string noting the reason why the pairing is in violation of B6 or 5, and the id of the player involved. If there are multiple violations, the most important one is/should be returned. |
1039
|
|
|
|
|
|
|
|
1040
|
|
|
|
|
|
|
=cut |
1041
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
sub _floatCheck { |
1043
|
272
|
|
|
272
|
|
364
|
my $self = shift; |
1044
|
272
|
|
|
|
|
364
|
my $untested = shift; |
1045
|
272
|
|
|
|
|
516
|
my @paired = @$untested; |
1046
|
272
|
|
|
|
|
754
|
my @nopairs = $self->_getNonPaired(@paired); |
1047
|
272
|
|
|
|
|
417
|
my $levels = shift; |
1048
|
272
|
50
|
33
|
|
|
1434
|
die "Float checks are $levels?" unless $levels and ref($levels) eq 'ARRAY'; |
1049
|
272
|
|
|
|
|
594
|
my $pprime = $self->pprime; |
1050
|
272
|
|
|
|
|
570
|
my $s1 = $self->s1; |
1051
|
272
|
|
|
|
|
359
|
my ($badpos, %badpos); |
1052
|
272
|
|
|
|
|
476
|
my @pairtestee = @paired; |
1053
|
272
|
|
|
|
|
676
|
my @nopairtestee = @nopairs; |
1054
|
272
|
|
|
|
|
591
|
my @pairlevelpasser; |
1055
|
|
|
|
|
|
|
my @nopairlevelpasser; |
1056
|
0
|
|
|
|
|
0
|
my $message; |
1057
|
272
|
|
|
|
|
763
|
B56: for my $level (@$levels) |
1058
|
|
|
|
|
|
|
{ |
1059
|
882
|
|
|
|
|
1046
|
my ($round, $direction, $checkedOne, $id); |
1060
|
882
|
100
|
|
|
|
2573
|
if ( $level =~ m/^B5/i ) { $round = 1; } |
|
367
|
|
|
|
|
534
|
|
1061
|
515
|
|
|
|
|
716
|
else { $round = 2; } |
1062
|
882
|
100
|
|
|
|
3069
|
if( $level =~ m/Down$/i) { $direction = 'Down'; $checkedOne = 0 } |
|
315
|
100
|
|
|
|
481
|
|
|
315
|
|
|
|
|
411
|
|
1063
|
375
|
|
|
|
|
525
|
elsif ( $level =~ m/Up$/i ) { $direction = 'Up'; $checkedOne = 1 } |
|
375
|
|
|
|
|
476
|
|
1064
|
192
|
|
|
|
|
372
|
else { @pairlevelpasser = @pairtestee; last B56 } |
|
192
|
|
|
|
|
423
|
|
1065
|
690
|
|
|
|
|
1447
|
for my $pos ( 0 .. $#$s1 ) { |
1066
|
940
|
100
|
|
|
|
2046
|
next unless defined $pairtestee[$pos]; |
1067
|
937
|
|
|
|
|
1951
|
my @pair = ( $pairtestee[$pos]->[0], $pairtestee[$pos]->[1] ); |
1068
|
937
|
100
|
|
|
|
1371
|
my @score = map { defined $_->score? $_->score: 0 } @pair; |
|
1874
|
|
|
|
|
4864
|
|
1069
|
937
|
|
|
|
|
1892
|
my @float = map { $_->floats( -$round ) } @pair; |
|
1874
|
|
|
|
|
5084
|
|
1070
|
937
|
|
|
|
|
1377
|
my $test = 0; |
1071
|
937
|
50
|
100
|
|
|
4327
|
$test = ( $score[0] == $score[1] or $float[$checkedOne] ne |
1072
|
|
|
|
|
|
|
$direction ) unless $direction eq 'None';# XXX check both? |
1073
|
937
|
100
|
|
|
|
1601
|
if ( $test ) { $pairlevelpasser[$pos] = \@pair; } |
|
869
|
|
|
|
|
2856
|
|
1074
|
|
|
|
|
|
|
else { |
1075
|
68
|
50
|
|
|
|
233
|
$badpos{$level} = defined $badpos{$level}? $badpos{$level}: $pos; |
1076
|
68
|
50
|
|
|
|
144
|
$badpos = defined $badpos? $badpos: $pos; |
1077
|
68
|
|
33
|
|
|
297
|
$id ||= $pair[$checkedOne]->pairingNumber; |
1078
|
|
|
|
|
|
|
} |
1079
|
|
|
|
|
|
|
} |
1080
|
690
|
100
|
100
|
|
|
3124
|
if ($direction ne 'Up' and @nopairtestee and ( not $self->hetero or |
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
1081
|
|
|
|
|
|
|
(grep {defined} @nopairtestee) == 1 )) |
1082
|
|
|
|
|
|
|
{ |
1083
|
|
|
|
|
|
|
#my $potentialDownFloaters = |
1084
|
|
|
|
|
|
|
# grep { grep { defined } @$_ } @nopairtestee; |
1085
|
128
|
|
|
|
|
290
|
for my $pos ( 0 .. $#nopairtestee ) { |
1086
|
314
|
100
|
|
|
|
699
|
next unless defined $nopairtestee[$pos]; |
1087
|
128
|
50
|
33
|
|
|
680
|
my @pair = @{ $nopairtestee[$pos] } if defined |
|
128
|
|
|
|
|
303
|
|
1088
|
|
|
|
|
|
|
$nopairtestee[$pos] and ref $nopairtestee[$pos] eq 'ARRAY'; |
1089
|
128
|
|
|
|
|
188
|
my $tableTest = 0; |
1090
|
128
|
|
|
|
|
142
|
my $idCheck; |
1091
|
128
|
|
|
|
|
222
|
for my $player ( @pair) { |
1092
|
256
|
|
100
|
|
|
875
|
my $test = ( not defined $player or |
1093
|
|
|
|
|
|
|
($player->floats(-$round) ne "Down") ); |
1094
|
256
|
100
|
33
|
|
|
952
|
$idCheck ||= $player->pairingNumber if $player and |
|
|
|
100
|
|
|
|
|
1095
|
|
|
|
|
|
|
not $test; |
1096
|
256
|
100
|
|
|
|
667
|
$tableTest++ if $test; |
1097
|
|
|
|
|
|
|
} |
1098
|
128
|
100
|
|
|
|
252
|
if ( $tableTest >= 2 ) { $nopairlevelpasser[$pos] = \@pair; } |
|
116
|
|
|
|
|
340
|
|
1099
|
|
|
|
|
|
|
else { |
1100
|
12
|
50
|
|
|
|
41
|
$badpos{$level} = defined $badpos{$level}? $badpos{$level}: $pos; |
1101
|
12
|
50
|
|
|
|
28
|
$badpos = defined $badpos? $badpos: $pos; |
1102
|
12
|
50
|
|
|
|
44
|
$id = $idCheck if $idCheck; |
1103
|
|
|
|
|
|
|
} |
1104
|
|
|
|
|
|
|
} |
1105
|
|
|
|
|
|
|
} |
1106
|
690
|
|
|
|
|
1128
|
my @retainables = grep { defined } @pairlevelpasser ;# |
|
884
|
|
|
|
|
2168
|
|
1107
|
|
|
|
|
|
|
# , grep { defined } @nopairlevelpasser; |
1108
|
|
|
|
|
|
|
# my @nonfloaters = grep { grep { defined } @$_ } @retainables; |
1109
|
690
|
100
|
100
|
|
|
3534
|
if ( @retainables < $pprime or keys %badpos ) |
1110
|
|
|
|
|
|
|
# if ( @retainables < $pprime or $badpos ) |
1111
|
|
|
|
|
|
|
{ |
1112
|
80
|
|
|
|
|
103
|
my $badpos; |
1113
|
80
|
|
|
|
|
150
|
for my $nextLevel ( @$levels ) |
1114
|
|
|
|
|
|
|
{ |
1115
|
146
|
100
|
|
|
|
361
|
next unless defined $badpos{ $nextLevel }; |
1116
|
80
|
|
|
|
|
114
|
$badpos = $badpos{ $nextLevel }; |
1117
|
80
|
|
|
|
|
117
|
last; |
1118
|
|
|
|
|
|
|
} |
1119
|
80
|
|
|
|
|
121
|
my $pluspos = $badpos+1; |
1120
|
80
|
|
|
|
|
278
|
$message = |
1121
|
|
|
|
|
|
|
"$level, table $pluspos: $id NOK. Floated $direction $round rounds ago"; |
1122
|
80
|
|
|
|
|
674
|
return badpos => $badpos, passer => undef, message => $message; |
1123
|
|
|
|
|
|
|
} |
1124
|
|
|
|
|
|
|
} |
1125
|
|
|
|
|
|
|
continue { |
1126
|
610
|
|
|
|
|
1243
|
@pairtestee = @pairlevelpasser; |
1127
|
610
|
|
|
|
|
957
|
@nopairtestee = @nopairlevelpasser; |
1128
|
610
|
|
|
|
|
914
|
undef @pairlevelpasser; |
1129
|
610
|
|
|
|
|
1149
|
undef @nopairlevelpasser; |
1130
|
|
|
|
|
|
|
} |
1131
|
192
|
|
|
|
|
1381
|
return badpos => undef, passer => \@pairlevelpasser, message => "B56: OK."; |
1132
|
|
|
|
|
|
|
} |
1133
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
|
1135
|
|
|
|
|
|
|
=head2 _getNonPaired |
1136
|
|
|
|
|
|
|
|
1137
|
|
|
|
|
|
|
$bracket->_getNonPaired([$alekhine,$uwe],undef,[$deepblue,$yournewnike]) |
1138
|
|
|
|
|
|
|
|
1139
|
|
|
|
|
|
|
Takes a list representing the pairing of S1 and S2. Each element of the list is either a 2-element anonymous array ref (an accepted pair of players), or undef (a rejected pair.) Returns an array of the same form, but with the accepted player items replaced by undef and the undef items replaced by the pairs rejected. If there are more players in S2 than S1, those players are represented as [undef,$player]. |
1140
|
|
|
|
|
|
|
|
1141
|
|
|
|
|
|
|
=cut |
1142
|
|
|
|
|
|
|
|
1143
|
|
|
|
|
|
|
sub _getNonPaired { |
1144
|
464
|
|
|
464
|
|
592
|
my $self = shift; |
1145
|
464
|
|
|
|
|
822
|
my @pairables = @_; |
1146
|
464
|
|
|
|
|
999
|
my $s1 = $self->s1; |
1147
|
464
|
|
|
|
|
975
|
my $s2 = $self->s2; |
1148
|
464
|
|
|
|
|
626
|
my @nopairs; |
1149
|
464
|
|
|
|
|
1017
|
for my $pos ( 0..$#pairables ) |
1150
|
|
|
|
|
|
|
{ |
1151
|
599
|
50
|
|
|
|
1539
|
$nopairs[$pos] = [ $s1->[$pos], $s2->[$pos] ] unless |
1152
|
|
|
|
|
|
|
defined $pairables[$pos]; |
1153
|
|
|
|
|
|
|
} |
1154
|
464
|
|
|
|
|
1116
|
for my $pos ( $#pairables+1 .. $#$s1 ) |
1155
|
|
|
|
|
|
|
{ |
1156
|
2
|
|
|
|
|
8
|
$nopairs[$pos] = [ $s1->[$pos], $s2->[$pos] ]; |
1157
|
|
|
|
|
|
|
} |
1158
|
464
|
|
|
|
|
1055
|
for my $pos ( $#$s1+1 .. $#$s2 ) |
1159
|
|
|
|
|
|
|
{ |
1160
|
753
|
|
|
|
|
2003
|
$nopairs[$pos] = [ undef, $s2->[$pos] ]; |
1161
|
|
|
|
|
|
|
} |
1162
|
464
|
|
|
|
|
1554
|
return @nopairs; |
1163
|
|
|
|
|
|
|
} |
1164
|
|
|
|
|
|
|
|
1165
|
|
|
|
|
|
|
|
1166
|
|
|
|
|
|
|
=head1 AUTHOR |
1167
|
|
|
|
|
|
|
|
1168
|
|
|
|
|
|
|
Dr Bean, C<< >> |
1169
|
|
|
|
|
|
|
|
1170
|
|
|
|
|
|
|
=head1 BUGS |
1171
|
|
|
|
|
|
|
|
1172
|
|
|
|
|
|
|
Please report any bugs or feature requests to |
1173
|
|
|
|
|
|
|
C, or through the web interface at |
1174
|
|
|
|
|
|
|
L. |
1175
|
|
|
|
|
|
|
I will be notified, and then you'll automatically be notified of progress on |
1176
|
|
|
|
|
|
|
your bug as I make changes. |
1177
|
|
|
|
|
|
|
|
1178
|
|
|
|
|
|
|
=head1 SUPPORT |
1179
|
|
|
|
|
|
|
|
1180
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
1181
|
|
|
|
|
|
|
|
1182
|
|
|
|
|
|
|
perldoc Games::Tournament::Swiss::Bracket |
1183
|
|
|
|
|
|
|
|
1184
|
|
|
|
|
|
|
You can also look for information at: |
1185
|
|
|
|
|
|
|
|
1186
|
|
|
|
|
|
|
=over 4 |
1187
|
|
|
|
|
|
|
|
1188
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
1189
|
|
|
|
|
|
|
|
1190
|
|
|
|
|
|
|
L |
1191
|
|
|
|
|
|
|
|
1192
|
|
|
|
|
|
|
=item * CPAN Ratings |
1193
|
|
|
|
|
|
|
|
1194
|
|
|
|
|
|
|
L |
1195
|
|
|
|
|
|
|
|
1196
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
1197
|
|
|
|
|
|
|
|
1198
|
|
|
|
|
|
|
L |
1199
|
|
|
|
|
|
|
|
1200
|
|
|
|
|
|
|
=item * Search CPAN |
1201
|
|
|
|
|
|
|
|
1202
|
|
|
|
|
|
|
L |
1203
|
|
|
|
|
|
|
|
1204
|
|
|
|
|
|
|
=back |
1205
|
|
|
|
|
|
|
|
1206
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
1207
|
|
|
|
|
|
|
|
1208
|
|
|
|
|
|
|
See L for the FIDE's Swiss rules. |
1209
|
|
|
|
|
|
|
|
1210
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
1211
|
|
|
|
|
|
|
|
1212
|
|
|
|
|
|
|
Copyright 2006 Dr Bean, all rights reserved. |
1213
|
|
|
|
|
|
|
|
1214
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
1215
|
|
|
|
|
|
|
under the same terms as Perl itself. |
1216
|
|
|
|
|
|
|
|
1217
|
|
|
|
|
|
|
=cut |
1218
|
|
|
|
|
|
|
|
1219
|
|
|
|
|
|
|
1; # End of Games::Tournament::Swiss::Bracket |
1220
|
|
|
|
|
|
|
|
1221
|
|
|
|
|
|
|
# vim: set ts=8 sts=4 sw=4 noet: |