The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Games::Tournament::Swiss - FIDE Swiss Same-Rank Contestant Pairing

SYNOPSIS

    @Games::Tournament::Swiss::roles = qw/Black White/;
    $tourney = Games::Tournament::Swiss->new($rounds, \@entrants);
    @rankedPlayers = $tourney->assignPairingNumbers;
    $tourney->initializePreferences;


    ...

    $tourney->collectCards(@games);
    @groups = $tourney->formBrackets($round);
    $round5 = $tourney->pairing( \@groups );
    $matches = $round5->matchPlayers;
    $round5->allocateColors;

DESCRIPTION

In a Swiss tournament, there is a pre-declared number of rounds, each contestant meets every other contestant zero or one times, and in each round contestants are paired with other players with the same, or similar, scores.

METHODS

assignPairingNumbers

 @rankings = $tourney->assignPairingNumbers;

Sets the participants pairing numbers, sorting on rating, title and name, and substitutes this for the id they had before (The id was, but is no longer, saved as oldId. But don't change id to pairingNumber. It will change with late entries.) This function uses Games::Tournament::rank. Before the first round, all scores are usually 0. A2

initializePreferences

 @rankings = $tourney->initializePreferences;

Before the first round, the color (role) preference of the highest ranked player and the other odd-numbered players in the top half of the rankings is determined by lot. The preference of the even-numbered players in the top half is given to the other color. If there is only one player in the tournament, the preference is not initialized. The method assumes all entrants have a preference attribute. This accessor is given the player by the Games::Tournament::Contestant::Swiss constructor. We take care to put the players back in the same order that we got them from entrants method. Users may rely on the original order being maintained in web app cookies. E5

recreateCards

 $tourney->recreateCards( {
     round => $round,
     opponents => { 1 => 2, 2 => 1, 3 => 'Bye', 4 => '-' },
     roles => { 1 => 'W', 2 => 'B', 3 => 'Bye', 4 => '-' },
     floats => { 1 => 'U', 2=> 'D', 3 => 'Down', 4 => 'Not' }
 } )

From hashes of the opponents, roles and floats for each player in a round (as provided by a pairing table), draws up the original game cards for each of the matches of the round. Returned is a list of Games::Tournament::Card objects, with undefined result fields. Pairing numbers are not used. Ids are used. Pairing numbers change with late entries.

collectCards

 $play = $tourney->collectCards( @games );
  next if $htable->{$player1->id}->{$player2->id};

Records @games after they have been played. Stored as $tourney's play field, keyed on round and ids of players. Returns the new play field. Updates player scores, preferences, unless the player forfeited the game or had a Bye. TODO Die (or warn) if game has no results TODO This has non-Swiss subclass elements I could factor out into a method in Games::Tournament. TODO What if player is matched more than one time in the round, filling in for someone? XXX It looks like all the games have to be the same round, or you have to collect all cards in one round before collecting cards in following rounds. XXX I'm having problems with recording roles. I want to be lazy about it, and trust the card I get back before the next round. The problem with this is, I may be getting the role from the wrong place. It should come from the card, and is a role which was assigned in the previous round, and is only now being recorded, at this point between the previous round and the next round. Or is the problem copying by value rather than reference of the entrants? Now I also need to record floats. It would be good to do this at the same time as I record roles. The card is the appropriate place to get this info according to A4.

orderPairings

 @schedule = $tourney->orderPairings( @games );

Tables are ordered by scores of the player with the higher score at the table, then the total scores of the players (in other words, the scores of the other player), then the A2 ranking of the higher-ranked player, in that order. F1

publishCards

 $schedule = $tourney->publishCards( @games );

Stores @games, perhaps before they have been played, as $tourney's play field, keyed on round and ids of players. Returns the games in F1 ordering.

myCard

 $game = $tourney->myCard(round => 4, player => 13301616);

Finds match from $tourney's play accessor, which is keyed on round and IDS of players. 'player' is id of player.

formBrackets

 @groups = $tourney->formBrackets

Returns for the next round a hash of Games::Tournament::Swiss::Bracket objects grouping contestants with the same score, keyed on score. Late entrants without a score cause the program to die. Some groups may have odd numbers of players, etc, and players will have to be floated to other score groups. A number, from 1 to the total number of brackets, reflecting the order of pairing, is given to each bracket.

pairing

 $pairing = $tourney->pairing( \@groups );

Returns a Games::Tournament::Swiss::Procedure object. Groups are Games::Tournament::Swiss::Brackets objects of contestants with the same score and they are ordered by score, the group with the highest score first, and the group with the lowest score last. This is the point where round i becomes round i+1. But the program is expected to update the Games::Tournament::Swiss object itself. (Why?)

compatible

        $games = $tourney->compatible
        next if $games->{$alekhine->pairingNumber}->{$capablanca->pairingNumber}

Returns an anonymous hash, keyed on the ids of @grandmasters, indicating whether or not the individual @grandmasters could play each other in the next round. But what is the next round? This method uses the whoPlayedWho and colorClashes methods to remove incompatible players.

whoPlayedWho

        $games = $tourney->whoPlayedWho
        next if $games->{$alekhine->pairingNumber}->
            {$capablanca->pairingNumber}

Returns an anonymous hash, keyed on the ids of the tourney's entrants, of the round in which individual entrants met. Don't forget to collect scorecards in the appropriate games first! (No tracking of how many times players have met if they have met more than once!) Do you know what round it is? B1 XXX Unplayed pairings are not considered illegal in future rounds. F2 See also Games::Tournament::met.

colorClashes

        $nomatch = $tourney->colorClashes
        next if $nomatch->{$alekhine->id}->{$capablanca->id}

Returns an anonymous hash, keyed on the ids of the tourney's entrants, of a color (role) if 2 of the individual @grandmasters both have an absolute preference for it in the next round and so can't play each other (themselves). Don't forget to collect scorecards in the appropriate games first! B2

byesGone

        next if $tourney->byesGone($grandmasters)

Returns an anonymous hash of either the round in which the tourney's entrants had a 'Bye' or the empty string, keyed on @$grandmasters' ids. If a grandmaster had more than one bye, the last one is returned. Don't forget to collect scorecards in the appropriate games first! B1

incompatibles

        $nomatch = $tourney->incompatibles(@grandmasters)
        next if $nomatch->{$alekhine->id}->{$capablanca->id}

Collates information from the whoPlayedWho and colorClashes methods to show who cannot be matched or given a bye in the next round, returning an anonymous hash keyed on the ids of @grandmasters. B1,2 C1,6

medianScore

 $group = $tourney->medianScore($round)

Returns the score equal to half the number of rounds that have been played. Half the contestants will have scores above or equal to this score and half will have ones equal to or below it, assuming everyone has played every round. What IS the number of rounds played, again?

rounds

        $tourney->rounds

Gets/sets the total number of rounds to be played in the competition

size

$size = 'Maxi' if $tourney->size > 2**$tourney->rounds

Gets the number of entrants

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:

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.