acts_as_elo 0.1.0 → 0.2.0

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.
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