Class: TournamentSystem::Driver

Inherits:
Object
  • Object
show all
Defined in:
lib/tournament_system/driver.rb

Overview

An interface for external tournament data.

To use any tournament system implemented in this gem, simply subclass this class and implement the interface functions.

The interface is designed to be useable with arbitrary data, meaning that as long as your data is consistent it will work with this gem. Be it Ruby on Rails Models or simply integers.

Certain tournament systems will not make use of certain parts of this interface. You can for example leave out ‘#get_team_score` if you’re not using the Swiss tournament system.

This class caches certain calculations/objects, it is designed to be a one-time use with any one tournament system. Reusing an instance is undefined behaviour.

Examples:

Example of Rails models and a tournament system driver

class Tournament < ActiveRecord::Base
  has_many :matches
  has_many :teams
end

class Match < ActiveRecord::Base
  belongs_to :tournament
  belongs_to :team1, class_name: 'Team'
  belongs_to :team2, class_name: 'Team'
  belongs_to :winner, class_name: 'Team'
end

class Team < ActiveRecord::Base
  belongs_to :tournament

  validates :seed, numericality: { only_integer: true }
  validates :points, numericality: { only_integer: true }
end

class Driver < TournamentSystem
  def initialize(tournament)
    @tournament = tournament
  end

  def matches
    @tournament.matches
  end

  def seeded_teams
    @tournament.teams.order(:seed).to_a
  end

  def ranked_teams
    @tournament.teams.order(:points).to_a
  end

  def get_match_winner(match)
    match.winner
  end

  def get_match_teams(match)
    [match.team1, match.team2]
  end

  def get_team_score(team)
    team.points
  end

  def get_team_matches(team)
    @tournament.matches.where(team1: team) +
      @tournament.matches.where(team2: team)
  end

  def build_match(home_team, away_team)
    @tournament.matches.create!(team1: home_team, team2: away_team)
  end
end

Direct Known Subclasses

DriverProxy

Instance Method Summary collapse

Instance Method Details

#build_match(home_team, away_team) ⇒ nil

Required to implement: Called when a match is created by a tournament system.

Examples:

rails

def build_match(home_team, away_team)
  Match.create!(home_team, away_team)
end

Parameters:

  • home_team (team)

    the home team for the match, never nil

  • away_team (team, nil)

    the away team for the match, may be nil for byes.

Returns:

  • (nil)


144
145
146
# File 'lib/tournament_system/driver.rb', line 144

def build_match(home_team, away_team)
  raise 'Not Implemented'
end

#count_duplicate_matches(matches) ⇒ Integer

Count the number of times each pair of teams has played already. Used by tournament systems.

Parameters:

  • matches (Array<match>)

Returns:

  • (Integer)

    the number of duplicate matches



195
196
197
# File 'lib/tournament_system/driver.rb', line 195

def count_duplicate_matches(matches)
  matches.map { |match| matches_hash[Set.new match] }.reduce(0, :+)
end

#create_match(home_team, away_team) ⇒ nil

Create a match. Used by tournament systems.

Specially handles byes, swapping home/away if required.

Parameters:

  • home_team (team, nil)
  • away_team (team, nil)

Returns:

  • (nil)

Raises:

  • when both teams are nil



207
208
209
210
211
212
# File 'lib/tournament_system/driver.rb', line 207

def create_match(home_team, away_team)
  home_team, away_team = away_team, home_team unless home_team
  raise 'Invalid match' unless home_team

  build_match(home_team, away_team)
end

#create_matches(pairs) ⇒ nil

Create a bunch of matches. Used by tournament systems.

Parameters:

  • pairs (Array<Array(team, team)>)

    a collection of pairs

Returns:

  • (nil)

See Also:



219
220
221
222
223
# File 'lib/tournament_system/driver.rb', line 219

def create_matches(pairs)
  pairs.each do |home_team, away_team|
    create_match(home_team, away_team)
  end
end

#get_match_loser(match) ⇒ team?

Get the losing team of a specific match. By default uses #get_match_winner and #get_match_teams to determine which team lost. Override if you have better access to this information.

Returns:

  • (team, nil)

    the lower of the match, if applicable



155
156
157
158
159
160
# File 'lib/tournament_system/driver.rb', line 155

def get_match_loser(match)
  winner = get_match_winner(match)

  return nil unless winner
  get_match_teams(match).reject { |team| team == winner }.first
end

#get_match_teams(match) ⇒ Array(team, team)

Required to implement: Get the pair of teams playing for a match.

Parameters:

  • match

    a match, eg. one returned by #matches

Returns:

  • (Array(team, team))

    the pair of teams playing in the match



113
114
115
# File 'lib/tournament_system/driver.rb', line 113

def get_match_teams(match)
  raise 'Not Implemented'
end

#get_match_winner(match) ⇒ team?

Required to implement: Get the winning team of a match.

Parameters:

  • match

    a match, eg. one returned by #matches

Returns:

  • (team, nil)

    the winner of the match if applicable



105
106
107
# File 'lib/tournament_system/driver.rb', line 105

def get_match_winner(match)
  raise 'Not Implemented'
end

#get_team_matches(team) ⇒ Array<match>

Required to implement: Get the matches a team has participated in.

Parameters:

Returns:

  • (Array<match>)

    a list of matches the team has played in



129
130
131
# File 'lib/tournament_system/driver.rb', line 129

def get_team_matches(team)
  raise 'Not Implemented'
end

#get_team_score(team) ⇒ Number

Required to implement: Get a specific score for a team.

Parameters:

Returns:

  • (Number)

    the score of the team



121
122
123
# File 'lib/tournament_system/driver.rb', line 121

def get_team_score(team)
  raise 'Not Implemented'
end

#loss_count_hashHash{team => Number}

Get a hash of the number of losses of each team. Used by tournament systems.

Returns:

  • (Hash{team => Number})

    a mapping from teams to losses



235
236
237
# File 'lib/tournament_system/driver.rb', line 235

def loss_count_hash
  @loss_count_hash ||= matches.each_with_object(Hash.new(0)) { |match, hash| hash[get_match_loser(match)] += 1 }
end

#match_bye?(match) ⇒ Boolean

Determine whether a specific match was a bye? By default uses #get_match_teams to determine a bye. Override if you have better access to this information.

Returns:

  • (Boolean)


166
167
168
# File 'lib/tournament_system/driver.rb', line 166

def match_bye?(match)
  get_match_teams(match).include?(nil)
end

#matchesArray<match>

Required to implement: Get all matches.

Returns:

  • (Array<match>)


83
84
85
# File 'lib/tournament_system/driver.rb', line 83

def matches
  raise 'Not Implemented'
end

#matches_hashHash{Set(team, team) => Integer}

Get a hash of unique team pairs and their number of occurences. Used by tournament systems.

Returns:

  • (Hash{Set(team, team) => Integer})


180
181
182
# File 'lib/tournament_system/driver.rb', line 180

def matches_hash
  @matches_hash ||= build_matches_hash
end

#non_bye_matchesArray<match>

Get a list of matches that weren’t byes. Used by tournament systems.

Returns:

  • (Array<match>)


173
174
175
# File 'lib/tournament_system/driver.rb', line 173

def non_bye_matches
  matches.reject { |match| match_bye?(match) }
end

#ranked_teamsArray<team>

Required to implement: Get the teams ranked by their current position in the tournament.

Returns:

  • (Array<team>)


97
98
99
# File 'lib/tournament_system/driver.rb', line 97

def ranked_teams
  raise 'Not Implemented'
end

#scores_hashHash{team => Number}

Get a hash of the scores of all ranked teams. Used by tournament systems.

Returns:

  • (Hash{team => Number})

    a mapping from teams to scores



228
229
230
# File 'lib/tournament_system/driver.rb', line 228

def scores_hash
  @scores_hash ||= ranked_teams.map { |team| [team, get_team_score(team)] }.to_h
end

#seeded_teamsArray<team>

Required to implement: Get the teams with their initial seedings.

Returns:

  • (Array<team>)


90
91
92
# File 'lib/tournament_system/driver.rb', line 90

def seeded_teams
  raise 'Not Implemented'
end

#team_matches_hashHash{team => Array<match>}

Get a hash of the matches teams have played in. Used by tournament systems.

Returns:

  • (Hash{team => Array<match>})


187
188
189
# File 'lib/tournament_system/driver.rb', line 187

def team_matches_hash
  @team_matches_hash ||= build_team_matches_hash
end