tournament-system 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6c0d51a4fcebbc88d39dfa086acb16f1dc16360b
4
+ data.tar.gz: da0471359dc5f85ecc551a2ce3e8136b0090bd75
5
+ SHA512:
6
+ metadata.gz: c3b7e6f7165e6713e68b7c8a18217ebf3dd1d984ecb362ef4dfa47d6cb7f49a4a78c08ce117027681599124a5f6646b65e23223f5184774ad233f9bcd9a4c05c
7
+ data.tar.gz: a45707695701c74e6c779eb9d248703f2fbcbbc78aa559d0582b19f144914e03b574a1d020dd8f941de2f3b58b9a544103682edc6aca32234667e1257d67cefe
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.reek ADDED
@@ -0,0 +1,13 @@
1
+ # These don't work when using modules as stateless namespaces
2
+ UtilityFunction:
3
+ enabled: false
4
+ FeatureEnvy:
5
+ enabled: false
6
+
7
+ # Doesn't work well with case statements
8
+ TooManyStatements:
9
+ max_statements: 10
10
+
11
+ # Reek isn't good at detecting these, especially with state and blocks
12
+ DuplicateMethodCall:
13
+ max_calls: 2
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --profile
@@ -0,0 +1,31 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+
4
+ # This is fine, really
5
+ Style/FileName:
6
+ Enabled: false
7
+
8
+ # 'old' style
9
+ Style/EmptyMethod:
10
+ EnforcedStyle: expanded
11
+
12
+ # It makes much more sense to group them according to purpose
13
+ Bundler/OrderedGems:
14
+ Enabled: false
15
+
16
+ # Not interchangeable
17
+ Style/ModuleFunction:
18
+ Enabled: false
19
+
20
+ # Doesn't really matter
21
+ Style/FrozenStringLiteralComment:
22
+ Enabled: false
23
+
24
+ # Doesn't really make sense for multiline
25
+ Style/TrailingCommaInLiteral:
26
+ Enabled: false
27
+
28
+ # Tests should be as long as they need to be
29
+ Metrics/BlockLength:
30
+ Exclude:
31
+ - 'spec/**/*'
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm: 2.3.3
4
+ # rainbow gem install script is broken
5
+ before_install:
6
+ - gem update --system
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ # For build scripts
6
+ gem 'rake'
7
+
8
+ # Use rspec for tests
9
+ gem 'rspec'
10
+
11
+ # Test coverage
12
+ gem 'simplecov'
13
+
14
+ # Linting
15
+ gem 'rubocop', '~> 0.47.1'
16
+ gem 'reek'
17
+
18
+ group :test do
19
+ gem 'coveralls', require: false
20
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Benjamin Schaaf
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,96 @@
1
+ # Tournament System
2
+
3
+ [![Build Status](https://travis-ci.org/ozfortress/tournament-system.svg?branch=master)](https://travis-ci.org/ozfortress/tournament-system)
4
+ [![Coverage Status](https://coveralls.io/repos/github/ozfortress/tournament-system/badge.svg?branch=master)](https://coveralls.io/github/ozfortress/tournament-system?branch=master)
5
+
6
+ This is a simple gem that implements numerous tournament systems.
7
+
8
+ It is designed to easily fit into any memory model you might already have.
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'tournament-system'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ ```bash
21
+ $ bundle
22
+ ```
23
+
24
+ Or install it yourself as:
25
+
26
+ ```bash
27
+ $ gem install tournament-system
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ First you need to implement a driver to handle the interface between your data
33
+ and the tournament systems:
34
+
35
+ ```ruby
36
+ class Driver < Tournament::Driver
37
+ def matches_for_round(round)
38
+ ...
39
+ end
40
+
41
+ def seeded_teams
42
+ ...
43
+ end
44
+
45
+ def ranked_teams
46
+ ...
47
+ end
48
+
49
+ def get_match_winner(match)
50
+ ...
51
+ end
52
+
53
+ def get_match_teams(match)
54
+ ...
55
+ end
56
+
57
+ def get_team_score(team)
58
+ ...
59
+ end
60
+
61
+ def build_match(home_team, away_team)
62
+ ...
63
+ end
64
+ end
65
+ ```
66
+
67
+ Then you can simply generate matches for any tournament system using a driver
68
+ instance:
69
+
70
+ ```ruby
71
+ driver = Driver.new
72
+
73
+ # Generate the 3rd round of a single elimination tournament
74
+ Tournament::SingleElimination.generate driver, round: 2
75
+
76
+ # Generate a round for a round robin tournament, guesses round automatically
77
+ Tournament::RoundRobin.generate driver
78
+
79
+ # Generate a round for a swiss system tournament
80
+ # with Dutch pairings (default) with a minimum pair size of 6
81
+ Tournament::Swiss.generate driver, pairer: Tournament::Swiss::Dutch,
82
+ pair_options: { min_pair_size: 6 }
83
+
84
+ # Generate a round for a page playoff system, with an optional bronze match
85
+ Tournament::PagePlayoff.generate driver, bronze_match: true
86
+ ```
87
+
88
+ ## Contributing
89
+
90
+ Bug reports and pull requests are welcome on GitHub at
91
+ https://github.com/ozfortress/tournament-system.
92
+
93
+ ## License
94
+
95
+ The gem is available as open source under the terms of the
96
+ [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,13 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+ require 'rubocop/rake_task'
5
+ require 'reek/rake/task'
6
+
7
+ RSpec::Core::RakeTask.new(:rspec)
8
+ RuboCop::RakeTask.new
9
+ Reek::Rake::Task.new
10
+
11
+ task default: :test
12
+ task test: %w(rspec lint)
13
+ task lint: %w(rubocop reek)
@@ -0,0 +1,9 @@
1
+ require 'tournament/version'
2
+ require 'tournament/driver'
3
+
4
+ require 'tournament/seeder'
5
+
6
+ require 'tournament/swiss'
7
+ require 'tournament/round_robin'
8
+ require 'tournament/page_playoff'
9
+ require 'tournament/single_elimination'
@@ -0,0 +1,60 @@
1
+ module Tournament
2
+ # An interface for external tournament data.
3
+ #
4
+ # To use any tournament system implemented in this gem, simply subclass this
5
+ # class and implement the interface functions.
6
+ # :reek:UnusedParameters
7
+ class Driver
8
+ # rubocop:disable Lint/UnusedMethodArgument
9
+
10
+ # Get the matches played for a particular round
11
+ def matches_for_round(round)
12
+ raise 'Not Implemented'
13
+ end
14
+
15
+ # Get the teams playing with their initial seedings
16
+ def seeded_teams
17
+ raise 'Not Implemented'
18
+ end
19
+
20
+ # Get the teams playing, ranked by their current position in the tournament
21
+ def ranked_teams
22
+ raise 'Not Implemented'
23
+ end
24
+
25
+ # Get the winning team of a match
26
+ def get_match_winner(match)
27
+ raise 'Not Implemented'
28
+ end
29
+
30
+ # Get both teams playing for a match
31
+ def get_match_teams(match)
32
+ raise 'Not Implemented'
33
+ end
34
+
35
+ # Get a specific score for a team
36
+ def get_team_score(team)
37
+ raise 'Not Implemented'
38
+ end
39
+
40
+ # Handle for matches that are created by tournament systems
41
+ def build_match(home_team, away_team)
42
+ raise 'Not Implemented'
43
+ end
44
+
45
+ # rubocop:enable Lint/UnusedMethodArgument
46
+
47
+ # Get the losing team of a specific match
48
+ def get_match_loser(match)
49
+ winner = get_match_winner(match)
50
+ get_match_teams(match).reject { |team| team == winner }.first
51
+ end
52
+
53
+ def create_match(home_team, away_team)
54
+ home_team, away_team = away_team, home_team unless home_team
55
+ raise 'Invalid match' unless home_team
56
+
57
+ build_match(home_team, away_team)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,74 @@
1
+ module Tournament
2
+ # Implements the page playoff system.
3
+ module PagePlayoff
4
+ extend self
5
+
6
+ def generate(driver, options = {})
7
+ teams = driver.ranked_teams
8
+ raise 'Page Playoffs only works with 4 teams' if teams.length != 4
9
+
10
+ round = options[:round] || guess_round(driver)
11
+
12
+ case round
13
+ when 0 then semi_finals(driver, teams)
14
+ when 1 then preliminary_finals(driver)
15
+ when 2 then grand_finals(driver, options)
16
+ else
17
+ raise 'Invalid round number'
18
+ end
19
+ end
20
+
21
+ def total_rounds
22
+ 3
23
+ end
24
+
25
+ def guess_round(driver)
26
+ count = driver.matches.length
27
+
28
+ case count
29
+ when 0 then 0
30
+ when 2 then 1
31
+ when 3 then 2
32
+ else
33
+ raise 'Invalid number of matches'
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def create_matches(driver, matches)
40
+ matches.each do |match|
41
+ driver.create_match match[0], match[1]
42
+ end
43
+ end
44
+
45
+ def semi_finals(driver, teams)
46
+ create_matches driver, [[teams[0], teams[1]], [teams[2], teams[3]]]
47
+ end
48
+
49
+ def preliminary_finals(driver)
50
+ matches = driver.matches
51
+ top_loser = driver.get_match_loser matches[0]
52
+ bottom_winner = driver.get_match_winner matches[1]
53
+
54
+ driver.create_match top_loser, bottom_winner
55
+ end
56
+
57
+ def grand_finals(driver, options)
58
+ matches = driver.matches
59
+ top_winner = driver.get_match_winner matches[0]
60
+ bottom_winner = driver.get_match_winner matches[2]
61
+
62
+ driver.create_match top_winner, bottom_winner
63
+
64
+ bronze_finals(driver, matches) if options[:bronze_match]
65
+ end
66
+
67
+ def bronze_finals(driver, matches)
68
+ prelim_loser = driver.get_match_loser matches[2]
69
+ bottom_semi_loser = driver.get_match_loser matches[1]
70
+
71
+ driver.create_match prelim_loser, bottom_semi_loser
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,59 @@
1
+ module Tournament
2
+ # Implements the round-robin tournament system.
3
+ # Requires a consistent seeder, defaulting to Seeder::None
4
+ module RoundRobin
5
+ extend self
6
+
7
+ def generate(driver, options = {})
8
+ round = options[:round] || guess_round(driver)
9
+
10
+ teams = seed_teams driver.seeded_teams, options
11
+
12
+ teams = rotate_to_round teams, round
13
+
14
+ create_matches driver, teams, round
15
+ end
16
+
17
+ def total_rounds(driver)
18
+ team_count(driver) - 1
19
+ end
20
+
21
+ def guess_round(driver)
22
+ match_count = driver.matches.length
23
+
24
+ match_count / (team_count(driver) / 2)
25
+ end
26
+
27
+ private
28
+
29
+ def team_count(driver)
30
+ count = driver.seeded_teams.length
31
+ count += 1 if count.odd?
32
+ count
33
+ end
34
+
35
+ def seed_teams(teams, options)
36
+ teams << nil if teams.length.odd?
37
+
38
+ seeder = options[:seeder] || Seeder::None
39
+ seeder.seed teams
40
+ end
41
+
42
+ def rotate_to_round(teams, round)
43
+ rotateable = teams[1..-1]
44
+
45
+ [teams[0]] + rotateable.rotate(-round)
46
+ end
47
+
48
+ def create_matches(driver, teams, round)
49
+ teams[0...teams.length / 2].each_with_index do |home_team, index|
50
+ away_team = teams[-index - 1]
51
+
52
+ # Alternate home/away
53
+ home_team, away_team = away_team, home_team if round.odd?
54
+
55
+ driver.create_match(home_team, away_team)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,10 @@
1
+ require 'tournament/seeder/none'
2
+ require 'tournament/seeder/random'
3
+ require 'tournament/seeder/single_bracket'
4
+
5
+ module Tournament
6
+ # Module containing tournament seeders.
7
+ # Seeders are used by systems to define initial conditions.
8
+ module Seeder
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ module Tournament
2
+ module Seeder
3
+ # Implements a fall-through tournament seeder. Does no seeding whatsoever.
4
+ module None
5
+ extend self
6
+
7
+ def seed(teams)
8
+ teams
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ module Tournament
2
+ module Seeder
3
+ # A random seeder.
4
+ class Random
5
+ def initialize(random = nil)
6
+ @random = random
7
+ end
8
+
9
+ def seed(teams)
10
+ teams.shuffle(random: @random)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ module Tournament
2
+ module Seeder
3
+ # A seeder for a single-bracket tournament system.
4
+ # Seeds teams such that the highest expected placing teams should get
5
+ # furthest in the bracket.
6
+ module SingleBracket
7
+ extend self
8
+
9
+ def seed(teams)
10
+ groups = teams.each_slice(2)
11
+
12
+ top_half = groups.map { |pair| pair[0] }
13
+ bottom_half = groups.map { |pair| pair[1] }
14
+
15
+ if top_half.length > 2
16
+ top_half = seed top_half
17
+ bottom_half = seed bottom_half
18
+ end
19
+
20
+ top_half + bottom_half
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,51 @@
1
+ module Tournament
2
+ # Implements the single bracket elimination tournament system.
3
+ module SingleElimination
4
+ extend self
5
+
6
+ def generate(driver, options = {})
7
+ round = options[:round] || raise('Missing option :round')
8
+
9
+ teams = if driver.matches.empty?
10
+ seed_teams driver.seeded_teams, options
11
+ else
12
+ last_matches = driver.matches_for_round(round - 1)
13
+ get_match_winners driver, last_matches
14
+ end
15
+
16
+ create_matches driver, teams
17
+ end
18
+
19
+ def total_rounds(driver)
20
+ total_rounds_for_teams(driver.seeded_teams)
21
+ end
22
+
23
+ private
24
+
25
+ def seed_teams(teams, options)
26
+ padding = 2**total_rounds_for_teams(teams) - teams.length
27
+ teams = [nil] * padding + teams
28
+
29
+ seeder = options[:seeder] || Seeder::SingleBracket
30
+ seeder.seed teams
31
+ end
32
+
33
+ def total_rounds_for_teams(teams)
34
+ team_count = teams.length
35
+
36
+ Math.log2(team_count).ceil
37
+ end
38
+
39
+ def get_match_winners(driver, matches)
40
+ matches.map { |match| driver.get_match_winner(match) }
41
+ end
42
+
43
+ def create_matches(driver, teams)
44
+ teams.each_slice(2) do |slice|
45
+ next if slice.all?(&:nil?)
46
+
47
+ driver.create_match(slice[0], slice[1])
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,39 @@
1
+ require 'tournament/swiss/common'
2
+ require 'tournament/swiss/dutch'
3
+
4
+ module Tournament
5
+ # Implements the swiss tournament system
6
+ module Swiss
7
+ extend self
8
+
9
+ def generate(driver, options = {})
10
+ pairer = options[:pairer] || Dutch
11
+ pairer_options = options[:pair_options] || {}
12
+
13
+ teams = seed_teams driver.ranked_teams, options
14
+
15
+ pairings = pairer.pair driver, teams, pairer_options
16
+
17
+ create_matches driver, pairings
18
+ end
19
+
20
+ def minimum_rounds(driver)
21
+ team_count = driver.seeded_teams.length
22
+
23
+ Math.log2(team_count).ceil
24
+ end
25
+
26
+ private
27
+
28
+ def seed_teams(teams, options)
29
+ seeder = options[:seeder] || Seeder::None
30
+ seeder.seed teams
31
+ end
32
+
33
+ def create_matches(driver, pairings)
34
+ pairings.each do |pair|
35
+ driver.create_match(pair[0], pair[1])
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,110 @@
1
+ module Tournament
2
+ module Swiss
3
+ # Common functions for swiss pairing systems..\
4
+ module Common
5
+ extend self
6
+
7
+ # Iterate over each group, letting a team rollover into the next group
8
+ # if a group has an odd number of teams
9
+ def each_group_with_rollover(groups, group_keys)
10
+ group_keys.each_with_index do |key, index|
11
+ group = groups[key]
12
+ # Drop teams to next group get an even number
13
+ next_key = group_keys[index + 1]
14
+ groups[next_key] << group.pop if group.length.odd? && next_key
15
+
16
+ yield group
17
+ end
18
+ end
19
+
20
+ # Groups teams by the score given by the driver
21
+ def group_teams_by_score(driver, teams)
22
+ groups = teams.group_by { |team| driver.get_team_score team }
23
+ group_keys = groups.keys.sort.reverse.to_a
24
+
25
+ [groups, group_keys]
26
+ end
27
+
28
+ # Merges small groups to the right (if possible) such that all groups
29
+ # are larger than min_size.
30
+ # rubocop:disable Metrics/MethodLength :reek:TooManyStatements
31
+ def merge_small_groups(groups, group_keys, min_size)
32
+ new_keys = []
33
+
34
+ group_keys.each_with_index do |key, index|
35
+ group = groups[key]
36
+
37
+ # Merge small groups into an adjacent group
38
+ if group.length < min_size
39
+ groups.delete(key)
40
+
41
+ # When there is an adjacent lesser group, merge into that one
42
+ new_key = group_keys[index + 1]
43
+ if new_key
44
+ groups[new_key] = group + groups[new_key]
45
+ # If there isn't, merge into the adjacent greater group
46
+ else
47
+ new_key = group_keys[index - 1]
48
+ groups[new_key] += group
49
+ end
50
+ # Leave larger groups the way they are
51
+ else
52
+ new_keys << key
53
+ groups[key] = group
54
+ end
55
+ end
56
+
57
+ new_keys
58
+ end
59
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
60
+
61
+ # Get a set of already played matches. Matches are also sets
62
+ def matches_set(driver)
63
+ existing_matches = Set.new
64
+ driver.matches.each do |match|
65
+ match_teams = driver.get_match_teams match
66
+ existing_matches.add Set.new match_teams
67
+ end
68
+ existing_matches
69
+ end
70
+
71
+ # Check whether any match has already been played
72
+ def any_match_exists?(matches, existing_matches)
73
+ matches.any? { |match| existing_matches.include?(Set.new(match)) }
74
+ end
75
+
76
+ # Count the number of matches already played
77
+ def count_existing_matches(matches, existing_matches)
78
+ matches.count { |match| existing_matches.include?(Set.new(match)) }
79
+ end
80
+
81
+ # Finds the first permutation of teams that has a unique pairing.
82
+ # If none are found, the pairing that has the least duplicate matches
83
+ # is returned.
84
+ # rubocop:disable Metrics/MethodLength
85
+ def first_permutation_pairing(teams, existing_matches)
86
+ min_dups = Float::INFINITY
87
+ best_matches = nil
88
+
89
+ # Find the first permutation that has no duplicate matches
90
+ # Or the permutation with the least duplicate matches
91
+ teams.permutation.each do |variation|
92
+ matches = (yield variation).to_a
93
+ dup_count = count_existing_matches(matches, existing_matches)
94
+
95
+ # Quick exit when there are no duplicates
96
+ return matches if dup_count.zero?
97
+
98
+ # Update best stats as we go along
99
+ if dup_count < min_dups
100
+ min_dups = dup_count
101
+ best_matches = matches
102
+ end
103
+ end
104
+ # rubocop:enable Metrics/MethodLength
105
+
106
+ best_matches
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,62 @@
1
+ module Tournament
2
+ module Swiss
3
+ # A simplified Dutch pairing system implementation.
4
+ module Dutch
5
+ extend self
6
+ extend Common
7
+
8
+ def pair(driver, teams, options = {})
9
+ return dutch_pairing(teams) if driver.matches.empty?
10
+
11
+ groups, group_keys = group_teams_by_score(driver, teams)
12
+
13
+ min_pair_size = options[:min_pair_size] || 4
14
+ group_keys = merge_small_groups(groups, group_keys, min_pair_size)
15
+
16
+ pair_groups driver, groups, group_keys
17
+ end
18
+
19
+ private
20
+
21
+ def dutch_pairing(teams)
22
+ half = teams.length / 2
23
+ top = teams[0...half]
24
+ bottom = teams[half..-1]
25
+ top << nil if top.length < bottom.length
26
+
27
+ top.zip(bottom).to_a
28
+ end
29
+
30
+ def pair_groups(driver, groups, group_keys)
31
+ existing_matches = matches_set(driver)
32
+
33
+ matches = []
34
+ each_group_with_rollover(groups, group_keys) do |group|
35
+ matches += pair_group(group, existing_matches)
36
+ end
37
+
38
+ matches
39
+ end
40
+
41
+ def pair_group(group, existing_matches)
42
+ pairs = dutch_pairing(group)
43
+
44
+ if any_match_exists?(pairs, existing_matches)
45
+ first_permutation_pairing(group, existing_matches) do |perm_pairs|
46
+ dutch_pairing(perm_pairs)
47
+ end
48
+ else
49
+ pairs
50
+ end
51
+ end
52
+
53
+ def fix_matches(teams, pairs, existing_matches)
54
+ if any_match_exists?(pairs, existing_matches)
55
+ first_permutation_pairing(teams, existing_matches)
56
+ else
57
+ pairs
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,3 @@
1
+ module Tournament
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'tournament-system'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'tournament-system'
9
+ spec.version = Tournament::VERSION
10
+ spec.authors = ['Benjamin Schaaf']
11
+ spec.email = ['ben.schaaf@gmail.com']
12
+
13
+ spec.summary = 'Implements various tournament systems'
14
+ # TODO: Write a description
15
+ # spec.description =
16
+ spec.homepage = 'https://github.com/ozfortress/tournament-system'
17
+ spec.license = 'MIT'
18
+
19
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
20
+ f.match(%r{^(test|spec|features)/})
21
+ end
22
+ spec.bindir = 'exe'
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ['lib']
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.14'
27
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tournament-system
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Benjamin Schaaf
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-03-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ description:
28
+ email:
29
+ - ben.schaaf@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".gitignore"
35
+ - ".reek"
36
+ - ".rspec"
37
+ - ".rubocop.yml"
38
+ - ".travis.yml"
39
+ - Gemfile
40
+ - LICENSE
41
+ - README.md
42
+ - Rakefile
43
+ - lib/tournament-system.rb
44
+ - lib/tournament/driver.rb
45
+ - lib/tournament/page_playoff.rb
46
+ - lib/tournament/round_robin.rb
47
+ - lib/tournament/seeder.rb
48
+ - lib/tournament/seeder/none.rb
49
+ - lib/tournament/seeder/random.rb
50
+ - lib/tournament/seeder/single_bracket.rb
51
+ - lib/tournament/single_elimination.rb
52
+ - lib/tournament/swiss.rb
53
+ - lib/tournament/swiss/common.rb
54
+ - lib/tournament/swiss/dutch.rb
55
+ - lib/tournament/version.rb
56
+ - tournament-system.gemspec
57
+ homepage: https://github.com/ozfortress/tournament-system
58
+ licenses:
59
+ - MIT
60
+ metadata: {}
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 2.6.10
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Implements various tournament systems
81
+ test_files: []