/swissper

A Ruby gem for pairing Swiss tournaments

Primary LanguageRubyMIT LicenseMIT

Swissper

Swissper lets you generate swiss pairings for tournaments of all kinds.

Installation

Add this line to your application's Gemfile:

gem 'swissper'

And then execute:

$ bundle

Or install it yourself as:

$ gem install swissper

Usage

Use Swissper.pair(players, options) where players is an array of objects, and options is an optional hash of options.

The player objects you pass can be any type of object you like, so long as there are no duplicates. There is a simple Swissper::Player class available for ease of use.

player1 = Swissper::Player.new
player2 = Swissper::Player.new

Swissper.pair([player1, player2])
# [
#   [#<Swissper::Player:0x007ffc22e456d0 @delta=0, @exclude=[]>, #<Swissper::Player:0x007ffc22e3d318 @delta=0, @exclude=[]>]
# ]

Swissper.pair returns an array of tuples, each of which contains exactly two objects. These objects will be the objects you pass in.

Making players more likely to play

If the player is an object that responds to delta, Swissper will weight pairings so that players with similar deltas are more likely to be paired. In a typical tournament, the delta value might be the player's ranking, or points they've scored.

jack = Swissper::Player.new
jack.delta = 3
jill = Swissper::Player.new
jill.delta = 3
hansel = Swissper::Player.new
hansel.delta = 0
gretel = Swissper::Player.new
gretel.delta = 0

Swissper.pair([jack, jill, hansel, gretel])
# outputs:
[
  [#<Swissper::Player:0x007ffc209fd7a0 @delta=0, @exclude=[]>, #<Swissper::Player:0x007ffc22d34818 @delta=0, @exclude=[]>],
  [#<Swissper::Player:0x007ffc209f4df8 @delta=3, @exclude=[]>, #<Swissper::Player:0x007ffc21846ca8 @delta=3, @exclude=[]>]
]

You can customise the method called on the player objects with the delta_key option.

Swissper.pair(players, delta_key: :tournament_points)
# The player objects should respond to `tournament_points`

### Avoiding specific pairings

You're likely to need to avoid repeat pairings, such as players who have already faced each other. You can pass an array of players to be avoided to the exclude method of each player.

jack = Swissper::Player.new
jill = Swissper::Player.new
hansel = Swissper::Player.new
gretel = Swissper::Player.new

jack.exclude = [jill, hansel]

Swissper.pair([jack, jill, hansel, gretel])
# [
#   [#<Swissper::Player:0x007fe1b89a1f18 @delta=0, @exclude=[]>, #<Swissper::Player:0x007fe1b8bacb78 @delta=0, @exclude=[]>],
#   [#<Swissper::Player:0x007fe1b8bf4428 @delta=0, @exclude=[#<Swissper::Player:0x007fe1b8bacb78 @delta=0, @exclude=[]>, #<Swissper::Player:0x007fe1b89a1f18 @delta=0, @exclude=[]>]>, #<Swissper::Player:0x007fe1b8b15fc0 @delta=0, @exclude=[]>]
# ]

Players cannot be paired against players returned from the exclude method. In this example, Jack was paired with Gretel because that was the only valid remaining opponent for him.

You can customise this key with the exclude_key option.

Swissper.pair(players, exclude_key: :previous_opponents)
# Player objects should respond to `previous_opponents`

Byes

If your array of players contains an odd number, one player will be paired with the Swissper::Bye class.

You can prevent players from receiving byes (e.g. if they've already received one) by passing Swissper::Bye in the exclude parameter of any player.

snap = Swissper::Player.new
crackle = Swissper::Player.new
pop = Swissper::Player.new

snap.exclude = [Swissper::Bye]
crackle.exclude = [Swissper::Bye]

Swissper.pair([snap, crackle, pop])
# [
#   [Swissper::Bye, #<Swissper::Player:0x007fb2f99cb838 @delta=0, @exclude=[]>],
#   [#<Swissper::Player:0x007fb2f9accac0 @delta=0, @exclude=[Swissper::Bye]>, #<Swissper::Player:0x007fb2f91a8f98 @delta=0, @exclude=[Swissper::Bye]>]
# ]

Please don't manually pass in Swissper::Bye in your array of players, passing in an odd-length array is the correct way to use byes.

Bye delta

Byes have a default delta of -1 by default, but you can override this with the bye_delta option.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/muyjohno/swissper.

License

The gem is available as open source under the terms of the MIT License.