- NAME
- SYNOPSIS
- DESCRIPTION
- METHODS
- new
- matchPlayers
- message
- logreport
- start
- next
- prev
- c1
- rejectionTest
- c2
- c3
- c4
- c5
- c6pairs
- c6others
- c7
- c8
- c9
- c10
- c11
- c12
- c13
- bye
- c14
- colors
- brackets
- bracketOrder
- firstBracket
- lastBracket
- nextBracket
- previousBracket
- index
- round
- thisBracket
- byer
- paired
- nonpaired
- matches
- whoPlayedWho
- colorClashes
- incompatibles
- byes
- penultpPrime
- floatCriteriaInForce

- AUTHOR
- BUGS
- SUPPORT
- ACKNOWLEDGEMENTS
- COPYRIGHT & LICENSE

# NAME

Games::Tournament::Swiss::Procedure::FIDE - FIDE Swiss Rules Based on Rating 04.1

# SYNOPSIS

```
$tourney = Games::Tournament::Swiss->new( rounds => 2, entrants => [ $a, $b, $c ] );
%groups = $tourney->formBrackets;
$pairing = $tourney->pairing( \%groups );
@pairs = $pairing->matchPlayers;
...
```

# DESCRIPTION

FIDE Swiss Rules C 04.1 Based on Rating describes an algorithm to pair players. The algorithm starts with the highest bracket, and then pairs each bracket in turn. ending with the lowest bracket, floating players up and down to find acceptable matches, but also undoing pairings in higher score groups, if this will help the pairing of lower score groups. This module pairs players on the basis of that algorithm.

# METHODS

## new

` $pairing = Games::Tournament::Swiss::Procedure->new( \@groups );`

Creates a FIDE C 04.1 algorithm object on a reference to a list of scoregroups ordered by score, the group with highest score first, the one with lowest score last. This object has a matches accessor to the games (cards) the algorithm has made, an incompatibles accessor to previous matches ofthe players, a stack of groups previous to this one at this point in the pairing to which we can go back and XXX. This constructor is called in the Games::Tournament::Swiss::pairing method.

## matchPlayers

` @pairs = $pairing->matchPlayers;`

Run the FIDE C 04.1 algorithm adding matches to $pairing->matches. NOTE: At one point in deveopment of this module, I was passing round the args, rather than storing them in the object, because of problems with storing. What were those problems? What does matchPlayers return? Is it a hash or the matches or what?

## message

` $pairing->message;`

Something about the success or failure of the pairing procedure as far as it concerns the user. This is not a message about the success or failure of the Games::Tournament::Swiss::Procedure::FIDE code as in 'warn', or a logging of the progress of the players in their brackets through the FIDE pairing procedure as in 'log', or a message about a problem coding the FIDE algorithm, as in 'ERROR'.

## logreport

` $pairing->logreport('C6: Pairing S1 and S2');`

Accumulates a log in string form, of the progress of the players in their brackets through the FIDE pairing procedure, using the logging methods of Games::Tournament, and returning the log accumulated if no arguments are passed.

## start

` $pairing->start;`

Start at the start before the first bracket. Go to the next bracket.

## next

` $pairing->next;`

Pair the next bracket. End if this is the last bracket. Die if we are not pairing any bracket now.

## prev

` $pairing->prev;`

Pair the previous bracket. End if this is the first bracket.

## c1

` $pairing->c1;`

If the score group contains a player for whom no opponent can be found (B1,B2), and if this player is a downfloater, go to C12 to find another player to downfloat instead. Or if this is the last group, go to C13. Otherwise, downfloat the unpairable player.

## rejectionTest

` ($message, @unpairables) = $pairing->rejectionTest(@members)`

Returns the unpairable players in a score bracket, if it contains players for whom no opponent can be found (B1,B2). This is useful in C1, but it is also useful in pairing a remainder group, where we want to know the same thing but don't want to take the same action as in C1. It would be convenient to know that the group is unpairable as-is, without going through all the C6,7,8,9,10 computations.

## c2

` $pairing->c2`

Determine x according to A8. But only if xprime has not been defined for the bracket (remainder group) by C11. See B4 and http://chesschat.org/showthread.php?p=173273#post173273

## c3

` $pairing->c3`

Determine p according to A6.

## c4

` $pairing->c4`

The highest players in S1, the others in S2.

## c5

` $pairing->c5`

Order the players in S1 and S2 according to A2.

## c6pairs

` Games::Tournament::Swiss::Procedure->c6pairs($group, $matches)`

Pair the pprime players in the top half of the scoregroup in order with their counterparts in the bottom half, and return an array of tentative Games::Tournament::Card matches if B1, B2 and the relaxable B4-6 tests pass. In addition, as part of the B6,5 tests, check none of the UNpaired players in a homogeneous bracket were downfloated in the round before (B5) or the round before that (B6), or that there is not only one UNpaired, previously-downfloated player in a heterogeneous group, special-cased following Bill Gletsos' advice at http://chesschat.org/showpost.php?p=142260&postcount=158. If more than pprime tables are paired, we take the first pprime tables.

## c6others

` Games::Tournament::Swiss::Procedure->c6others($group, $matches)`

After pairing players, if there are remaining players in a homogeneous group, float them down to the next score group and continue with C1 (NEXT). In a heterogeneous group, start at C2 with the remaining players, now a homogeneous remainder group.

## c7

```
$next = $pairing->c7
while ( my @s2 = &$next )
{
create match cards unless this permutation is incompatible;
}
```

Apply a new transposition of S2 according to D1 and restart at C6. But take precautions to prevent transposing players who are no longer in the bracket, when finding a different pairing, returning from C10,12,13. In particular, when returning from C10, stop when the last alternative pairing for the lowest downfloater has been tried.

## c8

```
$next = $pairing->c8
while ( my ($s1, $s2) = &$next )
{
create match cards unless this exchange is incompatible;
}
```

In case of a homogeneous (remainder) group: apply a new exchange between S1 and S2 according to D2. Restart at C5.

## c9

` Games::Tournament::Swiss::Procedure->c9`

Drop, in order, criterion B6 (no identical float to 2 rounds before) and B5 (no identical float to previous round) for downfloats and restart at C4.

## c10

` Games::Tournament::Swiss::Procedure->c10`

In case of a homogeneous remainder group: undo the pairing of the lowest moved down player paired and try to find a different opponent for this player by restarting at C7. If no alternative pairing for this player exists then drop criterion B6 first and then B5 for upfloats and restart at C2 (C4 to avoid p, x resetting.) If we are in a C13 loop (check penultpPrime), avoid the C10 procedure. Why?

## c11

` Games::Tournament::Swiss::Procedure->c11`

As long as x (xprime) is less than p: increase it by 1. When pairing a remainder group undo all pairings of players moved down also. Restart at C3. (We were restarting at C7 after resetting the C7shuffler (Why?) We restart at C4 (to avoid resetting p) the 1st time, and C7 after that).

## c12

` Games::Tournament::Swiss::Procedure->c12`

If the group contains a player who cannot be paired without violating B1 or B2 and this is a heterogeneous group, undo the pairing of the previous score bracket. If in this previous score bracket a pairing can be made whereby another player will be moved down to the current one, and this now allows p pairing to be made then this pairing in the previous score bracket will be accepted. (If there was only one (or two) players in the previous score bracket, obviously (heh-heh) there is no use going back and trying to find another pairing). Using a c12repaired flag to tell if this is the 2nd time through (but what if this is a backtrack to a different bracket?).

## c13

` Games::Tournament::Swiss::Procedure->c13`

If the lowest score group contains a player who cannot be paired without violating B1 or B2 or who, if they are the only player in the group, cannot be given a bye (B1b), the pairing of the penultimate score bracket is undone. Try to find another pairing in the penultimate score bracket which will allow a pairing in the lowest score bracket. If in the penultimate score bracket p becomes zero (i.e. no pairing can be found which will allow a correct pairing for the lowest score bracket) then the two lowest score brackets are joined into a new lowest score bracket. Because now another score bracket is the penultimate one C13 can be repeated until an acceptable pairing is obtained. XXX Perhaps all the players from the old penultimate bracket were floated down. eg, t/cc6619.t. As a hack unfloat only those with the same score as the new penultimate bracket.

TODO not finding a pairing is not a program ERROR, but a LAST state.

## bye

` $self->bye`

The last, singular, unpairable player is given a bye. B2

## c14

` Games::Tournament::Swiss::Procedure->c14`

Decrease p (pprime) by 1 (and if the original value of x was greater than zero decrease x by 1 as well). As long as p is unequal to zero restart at C4. (At C13, if this is final bracket, because this means it is unpairable.) If p equals zero the entire score bracket is moved down to the next one. Restart with this score bracket at C1. (If it is the penultimate bracket, and the final bracket is unpairable, the final bracket is moved up, but I guess that's the same thing. C13 )

## colors

```
$next = $pairing->c7
while ( my @s2 = &$next )
{
create match cards unless this permutation is incompatible;
}
```

After an acceptable pairing is achieved that doesn't violate the one-time match only principle (B1) and the 2-game maximum on difference between play in one role over that in the other role (B2), roles are allocated so as to grant the preferences of both players, or grant the stronger preference, or grant the opposite roles to those they had when they last played a round in different roles, or grant the preference of the higher ranked player, in that order. (E) A Games::Tournament::Card object, records round, contestants, (undefined) result, and floats (A4).

## brackets

` $pairing->brackets`

Gets/sets all the brackets which we are pairing. The order of this array is important. The brackets are paired in order. I was storing these as an anonymous array of score group (bracket) objects. But the problem of remainder groups has forced me to store as a hash.

## bracketOrder

` $pairing->bracketOrder`

Gets an array of homogeneous and heterogeneous brackets in order with remainder groups (iff they have been given bracket status and only until this status is withdrawn) coming after the heterogeneous groups from which they are formed. This ordered array is necessary, because remainder groups come into being and it is difficult to move back to them. Do we re-pair the remainder group, or the whole group from which it came? Remember to keep control of remainder groups' virtual bracket status with the dissolved field. This method depends on each bracket having an index made up of the bracket score and a 'Remainder' or other appropriate suffix, if it is a remainder or other kind of sub-bracket. We rely on the lexico ordering of the suffixes.

TODO No need to create scoresAndTags list of lists here. Just do @index{@indexes} = map { m/^(\d*\.?\d+)(\D.*)?$/; {score => $1, tag => $2||'' } } @indexes;

## firstBracket

` $pairing->firstBracket`

Gets the firstBracket. This is the undissolved bracket with the highest score.

## lastBracket

` $pairing->lastBracket`

Gets the lastBracket. With the joining of score brackets and addition of remainder groups, this bracket may change.

## nextBracket

` $pairing->nextBracket`

Gets the nextBracket to that which we are pairing now. This may or may not be a remainder group, depending on whether they have been given virtual bracket status.

## previousBracket

` $pairing->previousBracket`

Gets the previousBracket to that which we are pairing now. This may or may not be a remainder group, depending on whether they have been given virtual bracket status.

## index

` $pairing->index($bracket)`

Gets the index of $bracket, possibly a changing label, because remainder groups coming into being and are given virtual bracket status.

## round

` $pairing->round`

What round is this round's results we're pairing on the basis of?

## thisBracket

```
$pairing->thisBracket
$pairing->thisBracket($pairing->firstBracket)
```

What bracket is this? Gets/sets a string of the form $score, or ${score}Remainder if it is a remainder group. (In C10, create an 'C10Repair' group.) You need to set this when moving from one bracket to another. And test the value returned. If no bracket is set, undef is returned.

## byer

` $group->byer`

Gets/sets the player set to take the bye.

## paired

` $group->paired`

Gets/sets an array of paired players, arranged pair by pair, in the bracket being paired.

## nonpaired

` $group->nonpaired`

Gets/sets an array of nonpaired players in the bracket being paired.

## matches

` $group->matches`

Gets/sets the matches which we have made. Returned is an anonymous hash of the matches in the round, keyed on a bracket index. Each value of the hash is an anonymous array of the matches in that bracket. So to get each actual match, you need to break up the matches in the individual brackets.

## whoPlayedWho

` $group->whoPlayedWho`

Gets/sets a anonymous hash, keyed on the pairing numbers of the opponents, of the preference of individual pairs of @grandmasters, if they both have the same absolute preference, and so can't play each other. This has probably been calculated by Games::Tournament::Swiss::whoPlayedWho B1a

## colorClashes

` $group->colorClashes`

Gets/sets a anonymous hash, keyed on the pairing numbers of the opponents, of their preference, if (and only if) they both have an Absolute preference for the same role and so can't play each other. This has probably been calculated by Games::Tournament::Swiss::colorClashes B2a

## incompatibles

` $group->incompatibles`

Gets/sets a anonymous hash, keyed on the pairing numbers of the opponents, of a previous round in which individual pairs of @grandmasters, if any, met. Or of their preference if they both have an Absolute preference for the same role and can't play each other. This has probably been calculated by Games::Tournament::Swiss::incompatibles. B1

## byes

```
$group->byes
return BYE unless $group->byes->{$id}
```

Gets/sets a anonymous hash, keyed on ids, not pairing numbers of players, of a previous round in which these players had a bye. This has probably been calculated by Games::Tournament::Swiss::byes. B1

## penultpPrime

```
$pairing->penultpPrime
$pairing->penultpPrime($previousBracket->pprime)
```

Gets/sets an accessor to the number of pairs in the penultimate bracket. When this reaches 0, the penultimate and final brackets are joined. C14

## floatCriteriaInForce

` $group->floatCriteriaInForce( $group->floatCheckWaive )`

Given the last criterion at which level checks have been waived, returns an anonymous array of the levels below this level for which checking is still in force. B5,6 C6,9,10 TODO All is nice, but creates problems.

# AUTHOR

Dr Bean, `<drbean, followed by the at mark (@), cpan, then a dot, and finally, org>`

# BUGS

Please report any bugs or feature requests to `bug-games-tournament-swiss at rt.cpan.org`

, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Games-Tournament-Swiss. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

# SUPPORT

You can find documentation for this module with the perldoc command.

` perldoc Games::Tournament::Swiss`

You can also look for information at:

AnnoCPAN: Annotated CPAN documentation

CPAN Ratings

RT: CPAN's request tracker

http://rt.cpan.org/NoAuth/Bugs.html?Dist=Games-Tournament-Swiss

Search CPAN

# ACKNOWLEDGEMENTS

See http://www.fide.com/official/handbook.asp?level=C04 for the FIDE's Swiss rules.

# COPYRIGHT & LICENSE

Copyright 2006 Dr Bean, all rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.