elo_rating 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 234b746cfd73febb6fafd5c60bba73541f30bd98
4
- data.tar.gz: 4a563d7890683bcdbf076d20e1440d4148f5030f
3
+ metadata.gz: 72c73870b99ccb9fa0eb8d5ada07c4104af74f33
4
+ data.tar.gz: f60fde89bad3ca68a36baf083dca5fa112da4a57
5
5
  SHA512:
6
- metadata.gz: 019a19ba4502f0e88bfcefbdee250b7ab61295d0970fa6d79ebb20ff23e286e5fee2c9b88fcf5c306068fadec480eab929198581861bd45ea158b08c012bae12
7
- data.tar.gz: 374d0bff359bdb950cddc367815ba32e4f6ea771d6cf6931ee8863036d9a6371872bd99a8917257f5a84cb2725b185eddfc64515927065a42da0ae38029d4988
6
+ metadata.gz: 059f1564f4fbbc9064660f6ae6be567faed7e3c0787f3340a62718923b4b9f224e69cb6bc8f5281d0834c7559490aa16370f0d45c2119d347fb37bca8eb893a3
7
+ data.tar.gz: f2c8fea968c72d13c49f00e77fb7a3934c3afe2f3c05d714ace015f7fbf5c3c113447772ef67cff9c3f92330d53d3cac4ce4dd172d0404349991c7f7a794595b
data/.gitignore CHANGED
@@ -1,4 +1,3 @@
1
1
  Guardfile
2
- Gemfile
3
2
  Gemfile.lock
4
- doc/
3
+ pkg
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # elo_rating
2
2
 
3
- `elo_rating` helps you calculate [Elo ratings](https://en.wikipedia.org/wiki/Elo_rating_system), a rating system used primary for Chess.
3
+ `elo_rating` helps you calculate [Elo ratings](https://en.wikipedia.org/wiki/Elo_rating_system), a rating system used primary for Chess, but can be used anywhere you want to determine an absolute ordering of things by doing many comparisons of a small number of things.
4
4
 
5
5
  It can handle multiple players in one game and allows for custom K-factor functions.
6
6
 
@@ -20,9 +20,11 @@ gem 'elo_rating'
20
20
 
21
21
  ## Usage
22
22
 
23
- Say you have two players, both have ratings of 2000. The second player wins. To
24
- determine both player's updated ratings:
23
+ Say you have two players playing against each other in a match, both with initial ratings of 2000.
25
24
 
25
+ The second player wins.
26
+
27
+ To determine both player's updated ratings:
26
28
 
27
29
  ```ruby
28
30
  match = EloRating::Match.new
@@ -31,13 +33,19 @@ match.add_player(rating: 2000, winner: true)
31
33
  match.updated_ratings # => [1988, 2012]
32
34
  ```
33
35
 
34
- The first player's rating goes down 12 points and the second player's goes up 12 points.
36
+ This tells us that the first player's rating should go down 12 points and the second player's should go up 12 points.
37
+
38
+ You can chain the same function calls to achieve the same result:
39
+
40
+ ```ruby
41
+ EloRating::Match.new.add_player(rating: 2000).add_player(rating: 2000, winner: true).updated_ratings # => [1988, 2012]
42
+ ```
35
43
 
36
44
  ### >2 players
37
45
 
38
- Most Elo rating calculators only allow for matches of just 2 players, but the
39
- formula can be extended games with more players by calculating rating adjustments
40
- for each player against each of their opponents.
46
+ Most Elo rating calculators only allow for matches of just 2 players, but the formula can be extended to games of any number of players.
47
+
48
+ We can do this by combining the rating adjustments for each pairing of players into one big adjustment.
41
49
 
42
50
  Say you have three players, rated 1900, 2000, and 2000. They are playing a game
43
51
  like [Monopoly](https://en.wikipedia.org/wiki/Monopoly_(game)) where there is
@@ -52,21 +60,26 @@ match.add_player(rating: 2000)
52
60
  match.updated_ratings # => [1931, 1985, 1985]
53
61
  ```
54
62
 
63
+ This is calculated as if the first player beat both of the other players and the other two players tied.
64
+
55
65
  ### Ranked games
56
66
 
57
- Some games like [Mario Kart](https://en.wikipedia.org/wiki/Mario_Kart) have
58
- multiple, ranked winners. Let's say you have three players like before, rated
59
- 1900, 2000, and 2000. Instead of indicating the winner, you can specify the
60
- ranks:
67
+ Some games like [Mario Kart](https://en.wikipedia.org/wiki/Mario_Kart) have multiple, ranked winners.
68
+
69
+ Let's say you have three players like before, rated 1900, 2000, and 2000, who came in first place, second place, and third place respectively.
70
+
71
+ Instead of indicating the winner, you can specify their places:
61
72
 
62
73
  ```ruby
63
74
  match = EloRating::Match.new
64
- match.add_player(rating: 1900, rank: 1)
65
- match.add_player(rating: 2000, rank: 2)
66
- match.add_player(rating: 2000, rank: 3)
75
+ match.add_player(rating: 1900, place: 1)
76
+ match.add_player(rating: 2000, place: 2)
77
+ match.add_player(rating: 2000, place: 3)
67
78
  match.updated_ratings # => [1973, 1997, 1931]
68
79
  ```
69
80
 
81
+ This is calculated as if the first player beat both of the other players and the second player beat the third.
82
+
70
83
  ## Elo rating functions
71
84
 
72
85
  The functions used in the above calculations are available for use directly:
@@ -83,10 +96,11 @@ The player rated 1900 has a 36% chance of winning.
83
96
 
84
97
  ### Rating adjustment
85
98
 
86
- You can use the expected score and the results of an actual match to determine
87
- how an Elo rating should change.
99
+ You can use the expected score and the results of an actual match to determine how an Elo rating should change.
100
+
101
+ The `EloRating.rating_adjustment` function takes an expected score and an actual score and returns how much a rating should go up or down.
88
102
 
89
- Let's say we have the expected rating from above of 0.36. If the first player rated 1900 won the match, their actual score would be 1.
103
+ Let's say we have the expected rating from above of 0.36 and the first player rated 1900 won the match, making their actual score 1.
90
104
 
91
105
  We can use this to determine how much their rating should change:
92
106
 
@@ -94,7 +108,7 @@ We can use this to determine how much their rating should change:
94
108
  EloRating.rating_adjustment(0.36, 1) # => 15.36
95
109
  ```
96
110
 
97
- Their rating should go up about 15 points if they win.
111
+ This means their rating should now be 1915.
98
112
 
99
113
  ## K-factor
100
114
 
@@ -106,18 +120,27 @@ It defaults to 24:
106
120
  EloRating::k_factor # => 24
107
121
  ```
108
122
 
109
- You can change this to any number. With a lower K-factor, ratings are less volatile and change slower:
123
+ You can change this to any number. With a lower K-factor, ratings are less volatile and change slower. Compare:
110
124
 
111
125
  ```ruby
112
126
  EloRating::k_factor = 10
113
127
  match = EloRating::Match.new
114
128
  match.add_player(rating: 2000, winner: true)
115
129
  match.add_player(rating: 2000)
116
- match.updated_ratings # => [1995, 2005]
130
+ match.updated_ratings # => [2005, 1995]
131
+ ```
132
+
133
+ to:
134
+
135
+ ```ruby
136
+ EloRating::k_factor = 20
137
+ match = EloRating::Match.new
138
+ match.add_player(rating: 2000, winner: true)
139
+ match.add_player(rating: 2000)
140
+ match.updated_ratings # => [2010, 1990]
117
141
  ```
118
142
 
119
- You can also pass a block to provide a custom function to calculate the K-factor
120
- based on the player's rating:
143
+ You can also pass a block to provide a custom function to calculate the K-factor based on the player's rating:
121
144
 
122
145
  ```ruby
123
146
  EloRating::set_k_factor do |rating|
@@ -132,8 +155,7 @@ EloRating::set_k_factor do |rating|
132
155
  end
133
156
  ```
134
157
 
135
- You can provide a rating to `EloRating.rating_adjustment` that will be used in
136
- your custom K-factor function:
158
+ Then you can provide a rating to `EloRating.rating_adjustment` that will be used in your custom K-factor function:
137
159
 
138
160
  ```ruby
139
161
  EloRating.rating_adjustment(0.75, 0) # => -24.0
@@ -141,13 +163,13 @@ EloRating.rating_adjustment(0.75, 0, rating: 2200) # => -18.0
141
163
  EloRating.rating_adjustment(0.75, 0, rating: 2500) # => -12.0
142
164
  ```
143
165
 
144
- You can also specify a K-factor for a single rating adjustment:
166
+ You can also just specify a K-factor directly for a single rating adjustment:
145
167
 
146
168
  ```ruby
147
169
  EloRating.rating_adjustment(0.75, 0, k_factor: 24) # => -18.0
148
170
  ```
149
171
 
150
- Note: custom K-factor functions must not raise any exceptions when the rating is nil:
172
+ *Note*: custom K-factor functions must not raise any exceptions when the rating is nil:
151
173
 
152
174
  ```ruby
153
175
  EloRating::set_k_factor do |rating|
@@ -155,3 +177,18 @@ EloRating::set_k_factor do |rating|
155
177
  end
156
178
  # => ArgumentError: Error encountered in K-factor block when passed nil rating: undefined method `/' for nil:NilClass
157
179
  ```
180
+
181
+ ## Thanks
182
+
183
+ Thanks to:
184
+
185
+ * Divergent Informatics for their [multiplayer Elo
186
+ calculator](http://elo.divergentinformatics.com/) used to verify calculations used in the development of this gem
187
+ * [Ian Hecker](https://github.com/iain) for the original [Elo](https://github.com/iain/elo).
188
+
189
+ ## License
190
+
191
+ Copyright © 2014 Maxwell Holder.
192
+
193
+ It is free software, and may be redistributed under the terms specified in the
194
+ LICENSE file.
data/Rakefile CHANGED
@@ -1,2 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+ RSpec::Core::RakeTask.new(:spec)
4
+
5
+ task :default => :spec
2
6
 
@@ -2,15 +2,16 @@
2
2
  # This class represents a single game between a number of players.
3
3
  class EloRating::Match
4
4
 
5
+ # All the players of the match.
5
6
  attr_reader :players
6
7
 
7
- # Creates a new match
8
+ # Creates a new match with no players.
8
9
  def initialize
9
10
  @players = []
10
11
  end
11
12
 
12
13
  # Adds a player to the match
13
- #
14
+ #
14
15
  # ==== Attributes
15
16
  # * +rating+: the Elo rating of the player
16
17
  # * +winner+ (optional): boolean, whether this player is the winner of the match
@@ -86,7 +87,8 @@ class EloRating::Match
86
87
  def rating_adjustment_against(opponent)
87
88
  EloRating.rating_adjustment(
88
89
  expected_score_against(opponent),
89
- actual_score_against(opponent)
90
+ actual_score_against(opponent),
91
+ rating: rating
90
92
  )
91
93
  end
92
94
 
@@ -1,3 +1,3 @@
1
1
  module EloRating
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/elo_rating.rb CHANGED
@@ -29,7 +29,7 @@ module EloRating
29
29
  # end
30
30
  # end
31
31
  #
32
- # Raises an ArgumentError if an exception is encountered when calling the provided block with nil as the argument
32
+ # Raises an +ArgumentError+ if an exception is encountered when calling the provided block with nil as the argument
33
33
  def self.set_k_factor(&k_factor)
34
34
  k_factor.call(nil)
35
35
  @k_factor = k_factor
data/spec/match_spec.rb CHANGED
@@ -28,6 +28,20 @@ describe EloRating::Match do
28
28
  expect(match.updated_ratings).to eql [1931, 1997, 1973]
29
29
  end
30
30
  end
31
+ context 'custom K-factor function' do
32
+ it 'uses the custom K-factor function' do
33
+ EloRating::set_k_factor do |rating|
34
+ rating || 0
35
+ end
36
+
37
+ match = EloRating::Match.new
38
+ match.add_player(rating: 2000)
39
+ match.add_player(rating: 2000, winner: true)
40
+ expect(match.updated_ratings).not_to eql [2000, 2000]
41
+
42
+ EloRating::k_factor = 24
43
+ end
44
+ end
31
45
  context 'multiple winners specified' do
32
46
  it 'raises an error' do
33
47
  match = EloRating::Match.new
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elo_rating
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max Holder
@@ -90,8 +90,6 @@ extra_rdoc_files: []
90
90
  files:
91
91
  - ".gitignore"
92
92
  - Gemfile
93
- - Gemfile.lock
94
- - Guardfile
95
93
  - LICENSE
96
94
  - README.md
97
95
  - Rakefile
data/Gemfile.lock DELETED
@@ -1,63 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- elo_rating (0.3.0)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- celluloid (0.15.2)
10
- timers (~> 1.1.0)
11
- coderay (1.1.0)
12
- diff-lcs (1.2.5)
13
- ffi (1.9.3)
14
- formatador (0.2.5)
15
- guard (2.6.1)
16
- formatador (>= 0.2.4)
17
- listen (~> 2.7)
18
- lumberjack (~> 1.0)
19
- pry (>= 0.9.12)
20
- thor (>= 0.18.1)
21
- guard-rspec (4.2.10)
22
- guard (~> 2.1)
23
- rspec (>= 2.14, < 4.0)
24
- listen (2.7.9)
25
- celluloid (>= 0.15.2)
26
- rb-fsevent (>= 0.9.3)
27
- rb-inotify (>= 0.9)
28
- lumberjack (1.0.7)
29
- method_source (0.8.2)
30
- pry (0.10.0)
31
- coderay (~> 1.1.0)
32
- method_source (~> 0.8.1)
33
- slop (~> 3.4)
34
- rake (10.3.1)
35
- rb-fsevent (0.9.4)
36
- rb-inotify (0.9.5)
37
- ffi (>= 0.5.0)
38
- rspec (3.0.0)
39
- rspec-core (~> 3.0.0)
40
- rspec-expectations (~> 3.0.0)
41
- rspec-mocks (~> 3.0.0)
42
- rspec-core (3.0.2)
43
- rspec-support (~> 3.0.0)
44
- rspec-expectations (3.0.2)
45
- diff-lcs (>= 1.2.0, < 2.0)
46
- rspec-support (~> 3.0.0)
47
- rspec-mocks (3.0.2)
48
- rspec-support (~> 3.0.0)
49
- rspec-support (3.0.2)
50
- slop (3.5.0)
51
- thor (0.19.1)
52
- timers (1.1.0)
53
-
54
- PLATFORMS
55
- ruby
56
-
57
- DEPENDENCIES
58
- bundler (~> 1.6)
59
- elo_rating!
60
- guard
61
- guard-rspec
62
- rake
63
- rspec
data/Guardfile DELETED
@@ -1,24 +0,0 @@
1
- # A sample Guardfile
2
- # More info at https://github.com/guard/guard#readme
3
-
4
- guard :rspec do
5
- watch(%r{^spec/.+_spec\.rb$})
6
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
- watch('spec/spec_helper.rb') { "spec" }
8
-
9
- # Rails example
10
- watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
- watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
- watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
- watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
- watch('config/routes.rb') { "spec/routing" }
15
- watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
-
17
- # Capybara features specs
18
- watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
19
-
20
- # Turnip features and steps
21
- watch(%r{^spec/acceptance/(.+)\.feature$})
22
- watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
23
- end
24
-