multiplayer_elo 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/lib/multiplayer_elo/elo_manager.rb +38 -0
- data/lib/multiplayer_elo/version.rb +1 -1
- data/lib/multiplayer_elo.rb +5 -1
- data/spec/acts_as_rateable_spec.rb +3 -4
- data/spec/elo_manager_spec.rb +61 -0
- data/spec/spec_helper.rb +0 -1
- metadata +5 -6
- data/lib/multiplayer_elo/rating_manager.rb +0 -26
- data/lib/multiplayer_elo/test_user.rb +0 -7
- data/spec/ratings_manager_spec.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c78e907b29d478234ebdcabcaf56be21c6e8fdb
|
4
|
+
data.tar.gz: e1fc166fb70c4f4a260c81da114db054c8571735
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01c87d2c6fbaf2ae12d85bd8cd77cde5bf2887ccacaf0ba2e569753ba65d92bdd75f3a3ff9105bd17b13028d32ebaf85b2bfee247eda023fb47b3e727bed14cc
|
7
|
+
data.tar.gz: cd45fe6a281b9047963e6cfd47510750df1a20ca4a3abd21a6b282f0eced385a23e5ff975f5d552cff7ae21742efe9a16caee54148be76091bc9993b99432de9
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class EloManager
|
2
|
+
attr_accessor :k_factor
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@k_factor = 20
|
6
|
+
end
|
7
|
+
|
8
|
+
def expected_percentage(elo1, elo2)
|
9
|
+
1.0 / ( 1.0 + ( 10.0 ** ((elo2.to_f - elo1.to_f) / 400.0) ) )
|
10
|
+
end
|
11
|
+
|
12
|
+
# result is 0 for a loss 1 for a win or .5 for a tie
|
13
|
+
def points_change(elo1, elo2, result)
|
14
|
+
(@k_factor.to_f * (result.to_f - expected_percentage(elo1, elo2))).round
|
15
|
+
end
|
16
|
+
|
17
|
+
def evaulate_results(results)
|
18
|
+
results.each do |i|
|
19
|
+
elo_change = 0
|
20
|
+
results.each do |j|
|
21
|
+
next if i == j
|
22
|
+
|
23
|
+
# we are using places so first place < 2nd place means a win
|
24
|
+
if i[:place] > j[:place]
|
25
|
+
winner = 0
|
26
|
+
elsif i[:place] == j[:place]
|
27
|
+
winner = 0.5
|
28
|
+
else
|
29
|
+
winner = 1
|
30
|
+
end
|
31
|
+
|
32
|
+
elo_change += points_change(i[:elo], j[:elo], winner)
|
33
|
+
end
|
34
|
+
|
35
|
+
i[:new_elo] = i[:elo] + elo_change
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/multiplayer_elo.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require "multiplayer_elo/version"
|
2
2
|
require 'multiplayer_elo/rating_manager'
|
3
|
+
require 'multiplayer_elo/elo_manager'
|
3
4
|
|
4
5
|
module MultiplayerElo
|
5
6
|
module Rateable
|
7
|
+
extend ActiveSupport::Concern
|
6
8
|
|
7
9
|
module ClassMethods
|
8
10
|
def acts_as_rateable(options = {})
|
@@ -10,4 +12,6 @@ module MultiplayerElo
|
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
13
|
-
end
|
15
|
+
end
|
16
|
+
|
17
|
+
ActiveRecord::Base.send(:include, MultiplayerElo::Rateable)
|
@@ -2,10 +2,9 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe MultiplayerElo do
|
4
4
|
it 'adding acts_as_rateable should be included in active record' do
|
5
|
-
|
6
|
-
|
7
|
-
acts_as_rateable
|
8
|
-
end
|
5
|
+
class Foo < ActiveRecord::Base
|
6
|
+
acts_as_rateable
|
9
7
|
end
|
10
8
|
end
|
9
|
+
|
11
10
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EloManager do
|
4
|
+
before(:all) do
|
5
|
+
@elo_manager = EloManager.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should have a default k-factor of 20' do
|
9
|
+
expect(@elo_manager.k_factor).to eq(20)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should have a method to predict the chance of a player to win' do
|
13
|
+
expect(@elo_manager.expected_percentage(1500,1500)).to eq (0.5)
|
14
|
+
expect(@elo_manager.expected_percentage(2000,1500)).to be > (0.94)
|
15
|
+
expect(@elo_manager.expected_percentage(2000,1500)).to be < (0.95)
|
16
|
+
expect(@elo_manager.expected_percentage(1500,2000)).to be > (0.05)
|
17
|
+
expect(@elo_manager.expected_percentage(1500,2000)).to be < (0.06)
|
18
|
+
expect(@elo_manager.expected_percentage(1500,1600)).to be > (0.24)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should have a method which tells you the points change for 2 elos' do
|
22
|
+
expect(@elo_manager.points_change(1500,1500, 1)).to eq(10)
|
23
|
+
expect(@elo_manager.points_change(1510,1490, 1)).to eq(9)
|
24
|
+
expect(@elo_manager.points_change(1500,2000, 1)).to eq(19)
|
25
|
+
expect(@elo_manager.points_change(1500,1500, 0)).to eq(-10)
|
26
|
+
expect(@elo_manager.points_change(1500,1500, 0.5)).to eq(0)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should have a method which returns the new elo in the result' do
|
30
|
+
game_results = [{id: 1, elo: 1500, place: 1}, {id: 2, elo: 1500, place: 2}]
|
31
|
+
results = @elo_manager.evaulate_results(game_results)
|
32
|
+
expect(results[0].keys).to eq([:id, :elo, :place, :new_elo])
|
33
|
+
expect(results[0][:new_elo]).to eq(1510)
|
34
|
+
expect(results[1][:new_elo]).to eq(1490)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should support multiple players' do
|
38
|
+
players = [ {id: 1, elo: 1500, place: 1}, {id: 2, elo: 1500, place: 2},
|
39
|
+
{id: 3, elo: 1500, place: 3}, {id: 4, elo: 1500, place: 4} ]
|
40
|
+
|
41
|
+
results = @elo_manager.evaulate_results(players)
|
42
|
+
|
43
|
+
expect(results[0][:new_elo]).to eq(1530)
|
44
|
+
expect(results[1][:new_elo]).to eq(1510)
|
45
|
+
expect(results[2][:new_elo]).to eq(1490)
|
46
|
+
expect(results[3][:new_elo]).to eq(1470)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should support ties' do
|
50
|
+
players = [ {id: 1, elo: 1500, place: 1}, {id: 2, elo: 1500, place: 2},
|
51
|
+
{id: 3, elo: 1500, place: 2}, {id: 4, elo: 1500, place: 3} ]
|
52
|
+
|
53
|
+
results = @elo_manager.evaulate_results(players)
|
54
|
+
|
55
|
+
expect(results[0][:new_elo]).to eq(1530)
|
56
|
+
expect(results[1][:new_elo]).to eq(1500)
|
57
|
+
expect(results[2][:new_elo]).to eq(1500)
|
58
|
+
expect(results[3][:new_elo]).to eq(1470)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: multiplayer_elo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Marks
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -93,12 +93,11 @@ files:
|
|
93
93
|
- README.md
|
94
94
|
- Rakefile
|
95
95
|
- lib/multiplayer_elo.rb
|
96
|
-
- lib/multiplayer_elo/
|
97
|
-
- lib/multiplayer_elo/test_user.rb
|
96
|
+
- lib/multiplayer_elo/elo_manager.rb
|
98
97
|
- lib/multiplayer_elo/version.rb
|
99
98
|
- multiplayer_elo.gemspec
|
100
99
|
- spec/acts_as_rateable_spec.rb
|
101
|
-
- spec/
|
100
|
+
- spec/elo_manager_spec.rb
|
102
101
|
- spec/spec_helper.rb
|
103
102
|
homepage: ''
|
104
103
|
licenses:
|
@@ -126,5 +125,5 @@ specification_version: 4
|
|
126
125
|
summary: Elo library for single and multiplayer games
|
127
126
|
test_files:
|
128
127
|
- spec/acts_as_rateable_spec.rb
|
129
|
-
- spec/
|
128
|
+
- spec/elo_manager_spec.rb
|
130
129
|
- spec/spec_helper.rb
|
@@ -1,26 +0,0 @@
|
|
1
|
-
class RatingManager
|
2
|
-
@k_factor = 20
|
3
|
-
|
4
|
-
def self.expected_percentage(elo1, elo2)
|
5
|
-
1.0 / ( 1.0 + ( 10.0 ** ((elo2.to_f - elo1.to_f) / 400.0) ) )
|
6
|
-
end
|
7
|
-
|
8
|
-
def self.update_ratings!(player1, player2, winner=1)
|
9
|
-
|
10
|
-
percent = self.expected_percentage(player1.rating, player2.rating)
|
11
|
-
points = (percent * @k_factor.to_f).round
|
12
|
-
|
13
|
-
case winner
|
14
|
-
when 1
|
15
|
-
player1.rating += (@k_factor - points)
|
16
|
-
player2.rating -= (@k_factor - points)
|
17
|
-
when 2
|
18
|
-
player2.rating += points
|
19
|
-
player1.rating -= points
|
20
|
-
else
|
21
|
-
difference = (@k_factor.to_f * (0.5 - percent)).round
|
22
|
-
player1.rating += difference
|
23
|
-
player2.rating -= difference
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe RatingManager do
|
4
|
-
|
5
|
-
it 'should update the ranking of the winner and loser' do
|
6
|
-
winning_player = TestUser.new
|
7
|
-
losing_player = TestUser.new
|
8
|
-
|
9
|
-
RatingManager.update_ratings!(winning_player, losing_player, 1)
|
10
|
-
expect(winning_player.rating).to eq(1510)
|
11
|
-
expect(losing_player.rating).to eq(1490)
|
12
|
-
|
13
|
-
RatingManager.update_ratings!(winning_player, losing_player, 1)
|
14
|
-
expect(winning_player.rating).to eq(1519)
|
15
|
-
expect(losing_player.rating).to eq(1481)
|
16
|
-
|
17
|
-
RatingManager.update_ratings!(winning_player, losing_player, 0)
|
18
|
-
expect(winning_player.rating).to eq(1518)
|
19
|
-
expect(losing_player.rating).to eq(1482)
|
20
|
-
|
21
|
-
winning_player.rating = 1500
|
22
|
-
losing_player.rating = 2000
|
23
|
-
RatingManager.update_ratings!(losing_player, winning_player, 2)
|
24
|
-
expect(winning_player.rating).to eq(1519)
|
25
|
-
expect(losing_player.rating).to eq(1981)
|
26
|
-
|
27
|
-
end
|
28
|
-
end
|