tournament-system 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []