acts_as_elo 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,17 +2,18 @@
2
2
 
3
3
  ### What is it?
4
4
 
5
- Provides sophisticated yet easy to understand ranking system with minimum changes to the system.
6
- Elo ranking system is heavily used in tournaments, player rankings in chess, sports, leader boards, multiplayer games, ranking of test questions, tasks etc.
5
+ Provides sophisticated yet easy to understand ranking system with minimum changes to the system.
6
+ Elo ranking system is heavily used in tournaments, player rankings in chess, sports, leader boards, multiplayer games, ranking of test questions, tasks etc.
7
7
 
8
8
  Read more about it on [wiki](http://en.wikipedia.org/wiki/Elo_rating_system)
9
9
 
10
10
  ### Usage
11
-
11
+
12
12
  `acts_as_elo` is very easy to use
13
13
 
14
14
  1. Install: `gem install acts_as_elo`
15
- 2. Add `include Acts::Elo` and `acts_as_elo` to your model/record
15
+ 2. Add `include Acts::Elo` and `acts_as_elo`
16
+ 3. Call any of the 3 methods: `elo_win!`, `elo_lose!` and `elo_draw!`
16
17
 
17
18
  ### Example
18
19
 
@@ -30,6 +31,4 @@ jack.elo_rank # => 1200
30
31
  bob.elo_win!(jack)
31
32
  bob.elo_rank # => 1205
32
33
  jack.elo_rank # => 1995
33
- ```
34
-
35
- That's it. No additional classes are involved.
34
+ ```
data/acts_as_elo.gemspec CHANGED
@@ -2,12 +2,12 @@
2
2
  $:.push File.expand_path('../lib', __FILE__)
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'acts_as_elo'
5
- s.version = '0.1.0'
5
+ s.version = '0.2.0'
6
6
  s.platform = Gem::Platform::RUBY
7
7
  s.authors = ['tjbladez']
8
8
  s.email = ['nick@tjbladez.net']
9
9
  s.homepage = 'http://github.com/tjbladez/acts_as_elo'
10
- s.summary = %q{Elo ranking made easy}
10
+ s.summary = %q{Sophisticated ranking made easy}
11
11
  s.description = %q{Provides sophisticated yet easy to understand ranking system with minimum changes to the system}
12
12
 
13
13
  # Load Paths...
@@ -3,10 +3,15 @@ module Acts
3
3
  def self.included(base)
4
4
  base.extend(ClassMethods)
5
5
  end
6
-
6
+
7
7
  module ClassMethods
8
+ # `acts_as_elo` hooks into your object to provide you with the ability to
9
+ # set and get `elo_rank` attribute
10
+ # Available options are:
11
+ # * default_rank - change the starting rank
12
+ # * one_way - limits update of the rank to only self
8
13
  def acts_as_elo(opts = {})
9
- default_rank = opts[:default_rank] || 1200
14
+ default_rank = opts[:default_rank] || 1200
10
15
 
11
16
  unless opts.empty?
12
17
  class << self
@@ -15,42 +20,53 @@ module Acts
15
20
  @acts_as_elo_options = opts
16
21
  end
17
22
 
18
- class_eval do
19
- attr_writer :elo_rank
20
-
21
- define_method(:elo_rank) do
22
- @elo_rank ||= default_rank
23
+ class_eval do
24
+ if Object::const_defined?("ActiveRecord") && self.ancestors.include?(ActiveRecord::Base)
25
+
26
+ define_method(:elo_rank) do
27
+ self[:elo_rank] ||= default_rank
28
+ end
29
+
30
+ else
31
+
32
+ attr_writer :elo_rank
33
+ define_method(:elo_rank) do
34
+ @elo_rank ||= default_rank
35
+ end
36
+
23
37
  end
24
38
  end
25
39
 
26
- include Acts::Elo::InstanceMethods unless self.included_modules.include?(Acts::Elo::InstanceMethods)
40
+ include Acts::Elo::InstanceMethods unless self.included_modules.include?(Acts::Elo::InstanceMethods)
27
41
  end
28
- end
29
-
42
+ end
43
+
30
44
  module InstanceMethods
31
45
  def elo_win!(opponent, opts={})
32
46
  elo_update(opponent, opts.merge!(:result => :win))
33
47
  end
34
-
48
+
35
49
  def elo_lose!(opponent, opts={})
36
50
  elo_update(opponent, opts.merge!(:result => :lose))
37
51
  end
38
-
52
+
39
53
  def elo_draw!(opponent, opts={})
40
54
  elo_update(opponent, opts.merge!(:result => :draw))
41
55
  end
42
-
56
+
43
57
  def elo_update(opponent, opts={})
44
58
  begin
45
59
  if self.class.respond_to?(:acts_as_elo_options) && self.class.acts_as_elo_options[:one_way]
46
60
  one_way = true
47
61
  end
48
62
  one_way ||= opts[:one_way]
63
+ send_opts = {one_way: true}
64
+
65
+ # Formula from: http://en.wikipedia.org/wiki/Elo_rating_system
49
66
  diff = (opponent.elo_rank.to_f - elo_rank.to_f).abs
50
67
  expected = 1 / (1 + 10 ** (diff / 400))
51
- send_opts = {one_way: true}
52
68
 
53
- if opts[:result] == :win
69
+ if opts[:result] == :win
54
70
  points = 1
55
71
  send_opts.merge!(result: :lose)
56
72
  elsif opts[:result] == :lose
@@ -60,14 +76,14 @@ module Acts
60
76
  points = 0.5
61
77
  send_opts.merge!(result: :draw)
62
78
  end
63
-
79
+
64
80
  opponent.elo_update(self, send_opts) unless one_way
65
81
 
66
- @elo_rank = (elo_rank + 10*(points-expected)).round
82
+ self.elo_rank = (elo_rank + 10*(points-expected)).round
67
83
  rescue Exception => e
68
84
  puts "Exception: #{e.message}"
69
85
  end
70
86
  end
71
- end
87
+ end
72
88
  end
73
89
  end
data/test/advance_test.rb CHANGED
@@ -1,19 +1,18 @@
1
1
  require 'pathname'
2
2
  require Pathname.new('.') + 'helper'
3
3
 
4
- # When user answers the question based on the on current rank of the user
4
+ # When user answers the question based on the on current rank of the user
5
5
  # and current rank of the question both user and question ranks will be updated
6
6
  class User
7
7
  include Acts::Elo
8
-
8
+
9
9
  attr_accessor :questions
10
-
11
- acts_as_elo :one_way => true
10
+ acts_as_elo
12
11
  end
13
12
 
14
13
  class Question
15
14
  include Acts::Elo
16
-
15
+
17
16
  attr_accessor :user
18
17
  acts_as_elo
19
18
  end
@@ -21,25 +20,25 @@ end
21
20
 
22
21
  context "User with many questions" do
23
22
  helper(:question) { |user| Question.new.tap {|q| q.user = user} }
24
-
23
+
25
24
  setup { User.new }
26
25
  hookup { topic.questions = [question(topic), question(topic)] }
27
-
26
+
28
27
  asserts(:elo_rank).equals(1200)
29
28
  asserts("questions have default ranks"){ topic.questions.map(&:elo_rank)}.equals([1200, 1200])
30
-
29
+
31
30
  context "when question is answered correctly" do
32
31
  hookup { topic.questions.each {|q| q.elo_rank = 1200 }}
33
32
  hookup { topic.questions.first.elo_lose!(topic)}
34
-
33
+
35
34
  asserts(:elo_rank).equals(1205)
36
35
  asserts("questions have their ranks updated"){ topic.questions.map(&:elo_rank)}.equals([1195, 1200])
37
36
  end
38
-
37
+
39
38
  context "when question is answered incorrectly" do
40
39
  hookup { topic.questions.each {|q| q.elo_rank = 1200 }}
41
40
  hookup { topic.questions.first.elo_win!(topic) }
42
-
41
+
43
42
  asserts(:elo_rank).equals(1195)
44
43
  asserts("questions have their ranks updated"){ topic.questions.map(&:elo_rank)}.equals([1205, 1200])
45
44
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_elo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-11 00:00:00.000000000Z
12
+ date: 2012-03-09 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
16
- requirement: &70308114821680 !ruby/object:Gem::Requirement
16
+ requirement: &70327763632440 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.0.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70308114821680
24
+ version_requirements: *70327763632440
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: riot
27
- requirement: &70308114821280 !ruby/object:Gem::Requirement
27
+ requirement: &70327763631380 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70308114821280
35
+ version_requirements: *70327763631380
36
36
  description: Provides sophisticated yet easy to understand ranking system with minimum
37
37
  changes to the system
38
38
  email:
@@ -75,7 +75,7 @@ rubyforge_project:
75
75
  rubygems_version: 1.8.10
76
76
  signing_key:
77
77
  specification_version: 3
78
- summary: Elo ranking made easy
78
+ summary: Sophisticated ranking made easy
79
79
  test_files:
80
80
  - test/advance_test.rb
81
81
  - test/basic_test.rb