Module: EloRankable

Defined in:
lib/elo_rankable.rb,
lib/elo_rankable/version.rb,
lib/elo_rankable/calculator.rb,
lib/elo_rankable/elo_ranking.rb,
lib/elo_rankable/configuration.rb,
lib/elo_rankable/has_elo_ranking.rb,
lib/generators/elo_rankable/install/install_generator.rb

Overview

EloRankable provides methods for recording Elo-based ranking results for multiplayer matches, winner-vs-all matches, and draws between players. It expects player objects to respond to ‘elo_ranking` and `beat!` methods, and includes configuration support.

Example usage:

EloRankable.record_multiplayer_match([player1, player2, player3])
EloRankable.record_winner_vs_all(winner, [loser1, loser2])
EloRankable.record_draw(player1, player2)

Configuration can be customized via EloRankable.configure.

Errors:

EloRankable::InvalidMatchError - Raised for invalid match scenarios.
ArgumentError - Raised for invalid arguments or player objects.

Defined Under Namespace

Modules: Generators, HasEloRanking Classes: Calculator, Configuration, EloRanking, Error, InvalidMatchError

Constant Summary collapse

VERSION =
'0.2.2'

Class Method Summary collapse

Class Method Details

.configObject



31
32
33
# File 'lib/elo_rankable.rb', line 31

def config
  @config ||= Configuration.new
end

.configure {|config| ... } ⇒ Object

Yields:



35
36
37
# File 'lib/elo_rankable.rb', line 35

def configure
  yield(config) if block_given?
end

.record_draw(player1, player2) ⇒ Object

Record a draw between two players

Raises:

  • (ArgumentError)


83
84
85
86
87
88
89
90
91
# File 'lib/elo_rankable.rb', line 83

def record_draw(player1, player2)
  raise ArgumentError, 'Player1 cannot be nil' if player1.nil?
  raise ArgumentError, 'Player2 cannot be nil' if player2.nil?
  raise ArgumentError, 'Cannot record draw with same player' if player1 == player2
  raise ArgumentError, 'Player1 must respond to elo_ranking' unless player1.respond_to?(:elo_ranking)
  raise ArgumentError, 'Player2 must respond to elo_ranking' unless player2.respond_to?(:elo_ranking)

  Calculator.update_ratings_for_draw(player1, player2)
end

.record_multiplayer_match(players) ⇒ Object

Record a multiplayer match where players are ranked by their position in the array Higher-indexed players are treated as having lost to lower-indexed ones

Raises:



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/elo_rankable.rb', line 41

def record_multiplayer_match(players)
  raise InvalidMatchError, 'Need at least 2 players for a match' if players.length < 2

  # Validate input array
  raise ArgumentError, 'Players array cannot contain nil values' if players.any?(&:nil?)

  # Check for duplicates
  raise ArgumentError, 'Players array cannot contain duplicate players' if players.uniq.length != players.length

  # Validate all players respond to elo_ranking
  invalid_players = players.reject { |p| p.respond_to?(:elo_ranking) }
  raise ArgumentError, 'All players must respond to elo_ranking' unless invalid_players.empty?

  # Process all pairwise combinations
  players.each_with_index do |player1, i|
    players[(i + 1)..].each do |player2|
      player1.beat!(player2)
    end
  end
end

.record_winner_vs_all(winner, losers) ⇒ Object

Record a single winner vs all others match

Raises:

  • (ArgumentError)


63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/elo_rankable.rb', line 63

def record_winner_vs_all(winner, losers)
  # Validate winner
  raise ArgumentError, 'Winner cannot be nil' if winner.nil?
  raise ArgumentError, 'Winner must respond to elo_ranking' unless winner.respond_to?(:elo_ranking)

  # Validate losers array
  raise InvalidMatchError, 'Need at least 1 loser' if losers.empty?
  raise ArgumentError, 'Losers array cannot contain nil values' if losers.any?(&:nil?)
  raise InvalidMatchError, 'Winner cannot be in losers list' if losers.include?(winner)

  # Validate all losers respond to elo_ranking
  invalid_losers = losers.reject { |p| p.respond_to?(:elo_ranking) }
  raise ArgumentError, 'All losers must respond to elo_ranking' unless invalid_losers.empty?

  losers.each do |loser|
    winner.beat!(loser)
  end
end