leaderboard 1.0.5 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc CHANGED
@@ -1 +1,2 @@
1
- rvm 1.8.7
1
+ rvm --create 1.8.7@leaderboard_gem
2
+ rvm --create 1.9.2@leaderboard_gem
@@ -1,3 +1,17 @@
1
+ # leaderboard 2.0.0 (2011-08-05)
2
+
3
+ * Change `add_member` to `rank_member` - https://github.com/agoragames/leaderboard/issues/3
4
+ * Added `delete_leaderboard` and `delete_leaderboard_named` - https://github.com/agoragames/leaderboard/issues/2
5
+ * Ability to pass in an existing Redis connection in initializer - https://github.com/agoragames/leaderboard/issues/1
6
+ * Added transaction support for `score_and_rank_for`, `leaders`, `around_me` and `ranked_in_list`
7
+ * Updated initializer to take a leaderboard name, `options` hash and `redis_options` hash
8
+ * Simplified `leaders`, `around_me` and `ranked_in_list` to use an `options` hash with defaults for the previously individual parameters
9
+
10
+ # leaderboard 1.0.6 (unreleased)
11
+
12
+ * Added `disconnect` method
13
+ * Check for invalid page size when changing
14
+
1
15
  # leaderboard 1.0.5 (2011-05-04)
2
16
 
3
17
  * Updated Rakefile to run tests under ruby 1.8.7 and ruby 1.9.2
data/Gemfile CHANGED
@@ -8,5 +8,5 @@ group :development do
8
8
  gem "rcov", ">= 0"
9
9
  end
10
10
 
11
- gem 'redis', "~> 2.1.1"
11
+ gem 'redis', "~> 2.2.0"
12
12
 
@@ -8,7 +8,7 @@ Builds off ideas proposed in http://blog.agoragames.com/2011/01/01/creating-high
8
8
 
9
9
  Install the gem:
10
10
 
11
- gem install leaderboard
11
+ gem "leaderboard", "~> 2.0.0"
12
12
 
13
13
  Make sure your redis server is running! Redis configuration is outside the scope of this README, but
14
14
  check out the Redis documentation, http://redis.io/documentation.
@@ -21,138 +21,163 @@ The gem has been built and tested under Ruby 1.8.7 and Ruby 1.9.2
21
21
 
22
22
  Create a new leaderboard or attach to an existing leaderboard named 'highscores':
23
23
 
24
- ruby-1.8.7-p302 > highscore_lb = Leaderboard.new('highscores')
25
- => #<Leaderboard:0x1018e4250 @page_size=25, @port=6379, @host="localhost", @redis_connection=#<Redis client v2.1.1 connected to redis://localhost:6379/0 (Redis v2.1.10)>, @leaderboard_name="highscores">
26
-
27
- If you need to pass in options for Redis, you can do this with the redis_options parameter:
24
+ ruby-1.9.2-p180 :002 > highscore_lb = Leaderboard.new('highscores')
25
+ => #<Leaderboard:0x0000010307b530 @leaderboard_name="highscores", @page_size=25, @redis_connection=#<Redis client v2.2.2 connected to redis://localhost:6379/0 (Redis v2.2.5)>>
26
+
27
+ If you need to pass in options for Redis, you can do this in the initializer:
28
+
29
+ ruby-1.9.2-p180 :007 > redis_options = {:host => 'localhost', :port => 6379, :db => 1}
30
+ => {:host=>"localhost", :port=>6379, :db=>1}
31
+ ruby-1.9.2-p180 :008 > highscore_lb = Leaderboard.new('highscores', Leaderboard::DEFAULT_OPTIONS, redis_options)
32
+ => #<Leaderboard:0x00000103095200 @leaderboard_name="highscores", @page_size=25, @redis_connection=#<Redis client v2.2.2 connected to redis://localhost:6379/1 (Redis v2.2.5)>>
28
33
 
29
- redis_options = {:host => 'localhost', :port => 6379, :password => 'password', :db => 'some_redis_db'}
30
- highscore_lb = Leaderboard.new('highscores', redis_options[:host], redis_options[:port], Leaderboard::DEFAULT_PAGE_SIZE, redis_options))
34
+ You can pass in an existing connection to Redis using :redis_connection in the Redis options hash:
31
35
 
36
+ ruby-1.9.2-p180 :009 > redis = Redis.new
37
+ => #<Redis client v2.2.2 connected to redis://127.0.0.1:6379/0 (Redis v2.2.5)>
38
+ ruby-1.9.2-p180 :010 > redis_options = {:redis_connection => redis}
39
+ => {:redis_connection=>#<Redis client v2.2.2 connected to redis://127.0.0.1:6379/0 (Redis v2.2.5)>}
40
+ ruby-1.9.2-p180 :011 > highscore_lb = Leaderboard.new('highscores', Leaderboard::DEFAULT_OPTIONS, redis_options)
41
+ => #<Leaderboard:0x000001028791e8 @leaderboard_name="highscores", @page_size=25, @redis_connection=#<Redis client v2.2.2 connected to redis://127.0.0.1:6379/0 (Redis v2.2.5)>>
42
+
32
43
  You can set the page size to something other than the default page size (25):
33
44
 
34
- ruby-1.8.7-p302 > highscore_lb.page_size = 5
45
+ ruby-1.9.2-p180 :012 > highscore_lb.page_size = 5
35
46
  => 5
36
- ruby-1.8.7-p302 > highscore_lb
37
- => #<Leaderboard:0x1018e2130 @leaderboard_name="highscores", @page_size=5, @port=6379, @redis_connection=#<Redis client v2.1.1 connected to redis://localhost:6379/0 (Redis v2.1.10)>, @host="localhost", @redis_options={:host=>"localhost", :port=>6379}>
47
+ ruby-1.9.2-p180 :013 > highscore_lb
48
+ => #<Leaderboard:0x000001028791e8 @leaderboard_name="highscores", @page_size=5, @redis_connection=#<Redis client v2.2.2 connected to redis://127.0.0.1:6379/0 (Redis v2.2.5)>>
38
49
 
39
- Add members to your leaderboard:
50
+ Add members to your leaderboard using rank_member:
40
51
 
41
- ruby-1.8.7-p302 > 1.upto(10) do |index|
42
- ruby-1.8.7-p302 > highscore_lb.add_member("member_#{index}", index)
43
- ruby-1.8.7-p302 ?> end
52
+ ruby-1.9.2-p180 :014 > 1.upto(10) do |index|
53
+ ruby-1.9.2-p180 :015 > highscore_lb.rank_member("member_#{index}", index)
54
+ ruby-1.9.2-p180 :016?> end
44
55
  => 1
45
-
56
+
57
+ You can call rank_member with the same member and the leaderboard will be updated automatically.
58
+
46
59
  Get some information about your leaderboard:
47
60
 
48
- ruby-1.8.7-p302 > highscore_lb.total_members
61
+ ruby-1.9.2-p180 :020 > highscore_lb.total_members
49
62
  => 10
50
- ruby-1.8.7-p302 > highscore_lb.total_pages
63
+ ruby-1.9.2-p180 :021 > highscore_lb.total_pages
51
64
  => 1
52
65
 
53
66
  Get some information about a specific member(s) in the leaderboard:
54
67
 
55
- ruby-1.8.7-p302 > highscore_lb.score_for('member_4')
68
+ ruby-1.9.2-p180 :022 > highscore_lb.score_for('member_4')
56
69
  => 4.0
57
- ruby-1.8.7-p302 > highscore_lb.rank_for('member_4')
70
+ ruby-1.9.2-p180 :023 > highscore_lb.rank_for('member_4')
58
71
  => 7
59
- ruby-1.8.7-p302 > highscore_lb.rank_for('member_10')
72
+ ruby-1.9.2-p180 :024 > highscore_lb.rank_for('member_10')
60
73
  => 1
61
74
 
62
75
  Get page 1 in the leaderboard:
63
76
 
64
- ruby-1.8.7-p302 > highscore_lb.leaders(1)
65
- => [{:member=>"member_10", :rank=>1, :score=>"10"}, {:member=>"member_9", :rank=>2, :score=>"9"}, {:member=>"member_8", :rank=>3, :score=>"8"}, {:member=>"member_7", :rank=>4, :score=>"7"}, {:member=>"member_6", :rank=>5, :score=>"6"}, {:member=>"member_5", :rank=>6, :score=>"5"}, {:member=>"member_4", :rank=>7, :score=>"4"}, {:member=>"member_3", :rank=>8, :score=>"3"}, {:member=>"member_2", :rank=>9, :score=>"2"}, {:member=>"member_1", :rank=>10, :score=>"1"}]
77
+ ruby-1.9.2-p180 :025 > highscore_lb.leaders(1)
78
+ => [{:member=>"member_10", :rank=>1, :score=>10.0}, {:member=>"member_9", :rank=>2, :score=>9.0}, {:member=>"member_8", :rank=>3, :score=>8.0}, {:member=>"member_7", :rank=>4, :score=>7.0}, {:member=>"member_6", :rank=>5, :score=>6.0}, {:member=>"member_5", :rank=>6, :score=>5.0}, {:member=>"member_4", :rank=>7, :score=>4.0}, {:member=>"member_3", :rank=>8, :score=>3.0}, {:member=>"member_2", :rank=>9, :score=>2.0}, {:member=>"member_1", :rank=>10, :score=>1.0}]
66
79
 
80
+ You can pass various options to the calls `leaders`, `around_me` and `ranked_in_list`. Valid options are :with_scores, :with_rank, :use_zero_index_for_rank and :page_size.
81
+ Below is an example of retrieving the first page in the leaderboard without ranks:
82
+
83
+ ruby-1.9.2-p180 :026 > highscore_lb.leaders(1, :with_scores => true, :with_rank => false, :use_zero_index_for_rank => false)
84
+ => [{:member=>"member_10", :score=>9.0}, {:member=>"member_9", :score=>7.0}, {:member=>"member_8", :score=>5.0}, {:member=>"member_7", :score=>3.0}, {:member=>"member_6", :score=>1.0}, {:member=>"member_5", :score=>0.0}, {:member=>"member_4", :score=>0.0}, {:member=>"member_3", :score=>0.0}, {:member=>"member_2", :score=>0.0}, {:member=>"member_1", :score=>0.0}]
85
+
86
+ Below is an example of retrieving the first page in the leaderboard without scores or ranks:
87
+
88
+ ruby-1.9.2-p180 :028 > highscore_lb.leaders(1, :with_scores => false, :with_rank => false)
89
+ => [{:member=>"member_10"}, {:member=>"member_9"}, {:member=>"member_8"}, {:member=>"member_7"}, {:member=>"member_6"}, {:member=>"member_5"}, {:member=>"member_4"}, {:member=>"member_3"}, {:member=>"member_2"}, {:member=>"member_1"}]
90
+
67
91
  Add more members to your leaderboard:
68
92
 
69
- ruby-1.8.7-p302 > 50.upto(95) do |index|
70
- ruby-1.8.7-p302 > highscore_lb.add_member("member_#{index}", index)
71
- ruby-1.8.7-p302 ?> end
93
+ ruby-1.9.2-p180 :029 > 50.upto(95) do |index|
94
+ ruby-1.9.2-p180 :030 > highscore_lb.rank_member("member_#{index}", index)
95
+ ruby-1.9.2-p180 :031?> end
72
96
  => 50
73
- ruby-1.8.7-p302 > highscore_lb.total_pages
97
+ ruby-1.9.2-p180 :032 > highscore_lb.total_pages
74
98
  => 3
75
99
 
76
100
  Get an "Around Me" leaderboard for a member:
77
101
 
78
- ruby-1.8.7-p302 > highscore_lb.around_me('member_53')
79
- => [{:member=>"member_65", :rank=>31, :score=>"65"}, {:member=>"member_64", :rank=>32, :score=>"64"}, {:member=>"member_63", :rank=>33, :score=>"63"}, {:member=>"member_62", :rank=>34, :score=>"62"}, {:member=>"member_61", :rank=>35, :score=>"61"}, {:member=>"member_60", :rank=>36, :score=>"60"}, {:member=>"member_59", :rank=>37, :score=>"59"}, {:member=>"member_58", :rank=>38, :score=>"58"}, {:member=>"member_57", :rank=>39, :score=>"57"}, {:member=>"member_56", :rank=>40, :score=>"56"}, {:member=>"member_55", :rank=>41, :score=>"55"}, {:member=>"member_54", :rank=>42, :score=>"54"}, {:member=>"member_53", :rank=>43, :score=>"53"}, {:member=>"member_52", :rank=>44, :score=>"52"}, {:member=>"member_51", :rank=>45, :score=>"51"}, {:member=>"member_50", :rank=>46, :score=>"50"}, {:member=>"member_10", :rank=>47, :score=>"10"}, {:member=>"member_9", :rank=>48, :score=>"9"}, {:member=>"member_8", :rank=>49, :score=>"8"}, {:member=>"member_7", :rank=>50, :score=>"7"}, {:member=>"member_6", :rank=>51, :score=>"6"}, {:member=>"member_5", :rank=>52, :score=>"5"}, {:member=>"member_4", :rank=>53, :score=>"4"}, {:member=>"member_3", :rank=>54, :score=>"3"}, {:member=>"member_2", :rank=>55, :score=>"2"}]
102
+ ruby-1.9.2-p180 :033 > highscore_lb.around_me('member_53')
103
+ => [{:member=>"member_65", :rank=>31, :score=>65.0}, {:member=>"member_64", :rank=>32, :score=>64.0}, {:member=>"member_63", :rank=>33, :score=>63.0}, {:member=>"member_62", :rank=>34, :score=>62.0}, {:member=>"member_61", :rank=>35, :score=>61.0}, {:member=>"member_60", :rank=>36, :score=>60.0}, {:member=>"member_59", :rank=>37, :score=>59.0}, {:member=>"member_58", :rank=>38, :score=>58.0}, {:member=>"member_57", :rank=>39, :score=>57.0}, {:member=>"member_56", :rank=>40, :score=>56.0}, {:member=>"member_55", :rank=>41, :score=>55.0}, {:member=>"member_54", :rank=>42, :score=>54.0}, {:member=>"member_53", :rank=>43, :score=>53.0}, {:member=>"member_52", :rank=>44, :score=>52.0}, {:member=>"member_51", :rank=>45, :score=>51.0}, {:member=>"member_50", :rank=>46, :score=>50.0}, {:member=>"member_10", :rank=>47, :score=>10.0}, {:member=>"member_9", :rank=>48, :score=>9.0}, {:member=>"member_8", :rank=>49, :score=>8.0}, {:member=>"member_7", :rank=>50, :score=>7.0}, {:member=>"member_6", :rank=>51, :score=>6.0}, {:member=>"member_5", :rank=>52, :score=>5.0}, {:member=>"member_4", :rank=>53, :score=>4.0}, {:member=>"member_3", :rank=>54, :score=>3.0}, {:member=>"member_2", :rank=>55, :score=>2.0}]
80
104
 
81
105
  Get rank and score for an arbitrary list of members (e.g. friends):
82
106
 
83
- ruby-1.8.7-p302 > highscore_lb.ranked_in_list(['member_1', 'member_62', 'member_67'], true)
84
- => [{:rank=>55, :member=>"member_1", :score=>1.0}, {:rank=>33, :member=>"member_62", :score=>62.0}, {:rank=>28, :member=>"member_67", :score=>67.0}]
85
-
107
+ ruby-1.9.2-p180 :034 > highscore_lb.ranked_in_list(['member_1', 'member_62', 'member_67'])
108
+ => [{:member=>"member_1", :rank=>56, :score=>1.0}, {:member=>"member_62", :rank=>34, :score=>62.0}, {:member=>"member_67", :rank=>29, :score=>67.0}]
109
+
86
110
  === Other useful methods
87
111
 
88
- remove_member(member): Remove a member from the leaderboard
89
- total_members_in_score_range(min_score, max_score): Count the number of members within a score range in the leaderboard
90
- change_score_for(member, delta): Change the score for a member by some amount delta (delta could be positive or negative)
91
- check_member?(member): Check to see whether member is in the leaderboard
92
- score_and_rank_for(member, use_zero_index_for_rank = false): Retrieve the score and rank for a member in a single call
93
- remove_members_in_score_range(min_score, max_score): Remove members from the leaderboard within a score range
94
- merge_leaderboards(destination, keys, options = {:aggregate => :min}): Merge leaderboards given by keys with this leaderboard into destination
95
- intersect_leaderboards(destination, keys, options = {:aggregate => :min}): Intersect leaderboards given by keys with this leaderboard into destination
112
+ delete_leaderboard: Delete the current leaderboard
113
+ remove_member(member): Remove a member from the leaderboard
114
+ total_members: Total # of members in the leaderboard
115
+ total_pages: Total # of pages in the leaderboard given the leaderboard's page_size
116
+ total_members_in_score_range(min_score, max_score): Count the number of members within a score range in the leaderboard
117
+ change_score_for(member, delta): Change the score for a member by some amount delta (delta could be positive or negative)
118
+ rank_for(member): Retrieve the rank for a given member in the leaderboard
119
+ score_for(member): Retrieve the score for a given member in the leaderboard
120
+ check_member?(member): Check to see whether member is in the leaderboard
121
+ score_and_rank_for(member): Retrieve the score and rank for a member in a single call
122
+ remove_members_in_score_range(min_score, max_score): Remove members from the leaderboard within a score range
123
+ merge_leaderboards(destination, keys, options = {:aggregate => :min}): Merge leaderboards given by keys with this leaderboard into destination
124
+ intersect_leaderboards(destination, keys, options = {:aggregate => :min}): Intersect leaderboards given by keys with this leaderboard into destination
125
+
126
+ Check the online documentation for more detail, http://rubydoc.info/gems/leaderboard/
96
127
 
97
128
  == Performance Metrics
98
129
 
99
130
  10 million sequential scores insert:
100
131
 
101
- ruby-1.8.7-p302 > insert_time = Benchmark.measure do
102
- ruby-1.8.7-p302 > 1.upto(10000000) do |index|
103
- ruby-1.8.7-p302 > highscore_lb.add_member("member_#{index}", index)
104
- ruby-1.8.7-p302 ?> end
105
- ruby-1.8.7-p302 ?> end
106
- => #<Benchmark::Tms:0x101605660 @label="", @stime=173.61, @total=577.52, @real=911.718175172806, @utime=403.91, @cstime=0.0, @cutime=0.0>
132
+ ruby-1.9.2-p180 :003 > highscore_lb = Leaderboard.new('highscores')
133
+ => #<Leaderboard:0x0000010205fc50 @leaderboard_name="highscores", @page_size=25, @redis_connection=#<Redis client v2.2.2 connected to redis://localhost:6379/0 (Redis v2.2.5)>>
134
+ ruby-1.9.2-p180 :004 > insert_time = Benchmark.measure do
135
+ ruby-1.9.2-p180 :005 > 1.upto(10000000) do |index|
136
+ ruby-1.9.2-p180 :006 > highscore_lb.rank_member("member_#{index}", index)
137
+ ruby-1.9.2-p180 :007?> end
138
+ ruby-1.9.2-p180 :008?> end
139
+ => 323.070000 148.560000 471.630000 (942.068307)
107
140
 
108
141
  Average time to request an arbitrary page from the leaderboard:
109
142
 
110
- ruby-1.8.7-p302 > requests_to_make = 50000
143
+ ruby-1.9.2-p180 :009 > requests_to_make = 50000
111
144
  => 50000
112
- ruby-1.8.7-p302 > lb_request_time = 0
145
+ ruby-1.9.2-p180 :010 > lb_request_time = 0
113
146
  => 0
114
- ruby-1.8.7-p302 > 1.upto(requests_to_make) do
115
- ruby-1.8.7-p302 > lb_request_time += Benchmark.measure do
116
- ruby-1.8.7-p302 > highscore_lb.leaders(rand(highscore_lb.total_pages))
117
- ruby-1.8.7-p302 ?> end.total
118
- ruby-1.8.7-p302 ?> end
147
+ ruby-1.9.2-p180 :011 > 1.upto(requests_to_make) do
148
+ ruby-1.9.2-p180 :012 > lb_request_time += Benchmark.measure do
149
+ ruby-1.9.2-p180 :013 > highscore_lb.leaders(rand(highscore_lb.total_pages))
150
+ ruby-1.9.2-p180 :014?> end.total
151
+ ruby-1.9.2-p180 :015?> end
119
152
  => 1
120
- ruby-1.8.7-p302 >
121
- ruby-1.8.7-p302 > p lb_request_time / requests_to_make
122
- 0.001808
123
- => nil
124
-
153
+ ruby-1.9.2-p180 :016 > p lb_request_time / requests_to_make
154
+ 0.001513999999999998
155
+ => 0.001513999999999998
156
+
125
157
  10 million random scores insert:
126
158
 
127
- ruby-1.8.7-p302 > insert_time = Benchmark.measure do
128
- ruby-1.8.7-p302 > 1.upto(10000000) do |index|
129
- ruby-1.8.7-p302 > highscore_lb.add_member("member_#{index}", rand(50000000))
130
- ruby-1.8.7-p302 ?> end
131
- ruby-1.8.7-p302 ?> end
132
- => #<Benchmark::Tms:0x10164ebf8 @label="", @stime=172.94, @total=577.91, @real=1356.57155895233, @utime=404.97, @cstime=0.0, @cutime=0.0>
159
+ ruby-1.9.2-p180 :018 > insert_time = Benchmark.measure do
160
+ ruby-1.9.2-p180 :019 > 1.upto(10000000) do |index|
161
+ ruby-1.9.2-p180 :020 > highscore_lb.rank_member("member_#{index}", rand(50000000))
162
+ ruby-1.9.2-p180 :021?> end
163
+ ruby-1.9.2-p180 :022?> end
164
+ => 338.480000 155.200000 493.680000 (2188.702475)
133
165
 
134
166
  Average time to request an arbitrary page from the leaderboard:
135
167
 
136
- ruby-1.8.7-p302 > requests_to_make = 50000
137
- => 50000
138
- ruby-1.8.7-p302 > lb_request_time = 0
139
- => 0
140
- ruby-1.8.7-p302 > 1.upto(requests_to_make) do
141
- ruby-1.8.7-p302 > lb_request_time += Benchmark.measure do
142
- ruby-1.8.7-p302 > highscore_lb.leaders(rand(highscore_lb.total_pages))
143
- ruby-1.8.7-p302 ?> end.total
144
- ruby-1.8.7-p302 ?> end
168
+ ruby-1.9.2-p180 :007 > 1.upto(requests_to_make) do
169
+ ruby-1.9.2-p180 :008 > lb_request_time += Benchmark.measure do
170
+ ruby-1.9.2-p180 :009 > highscore_lb.leaders(rand(highscore_lb.total_pages))
171
+ ruby-1.9.2-p180 :010?> end.total
172
+ ruby-1.9.2-p180 :011?> end
145
173
  => 1
146
- ruby-1.8.7-p302 >
147
- ruby-1.8.7-p302 > p lb_request_time / requests_to_make
148
- 0.00179680000000001
149
- => nil
174
+ ruby-1.9.2-p180 :012 > p lb_request_time / requests_to_make
175
+ 0.0014615999999999531
176
+ => 0.0014615999999999531
150
177
 
151
178
  == Future Ideas
152
179
 
153
180
  * Bulk insert
154
- * Atomicity for various operations?
155
- * Is nil? OK to return if Redis returns no data or should it be []?
156
181
 
157
182
  == Contributing to leaderboard
158
183
 
data/Rakefile CHANGED
@@ -89,5 +89,5 @@ task :stop do
89
89
  end
90
90
 
91
91
  task :test_rubies do
92
- system "rvm 1.8.7,1.9.2 rake test"
93
- end
92
+ system "rvm 1.8.7@leaderboard_gem,1.9.2@leaderboard_gem rake test"
93
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.5
1
+ 2.0.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{leaderboard}
8
- s.version = "1.0.5"
8
+ s.version = "2.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["David Czarnecki"]
12
- s.date = %q{2011-05-04}
11
+ s.authors = [%q{David Czarnecki}]
12
+ s.date = %q{2011-08-17}
13
13
  s.description = %q{Leaderboards backed by Redis in Ruby}
14
14
  s.email = %q{dczarnecki@agoragames.com}
15
15
  s.extra_rdoc_files = [
@@ -33,9 +33,9 @@ Gem::Specification.new do |s|
33
33
  "test/test_leaderboard.rb"
34
34
  ]
35
35
  s.homepage = %q{http://github.com/agoragames/leaderboard}
36
- s.licenses = ["MIT"]
37
- s.require_paths = ["lib"]
38
- s.rubygems_version = %q{1.3.7}
36
+ s.licenses = [%q{MIT}]
37
+ s.require_paths = [%q{lib}]
38
+ s.rubygems_version = %q{1.8.6}
39
39
  s.summary = %q{Leaderboards backed by Redis in Ruby}
40
40
  s.test_files = [
41
41
  "test/helper.rb",
@@ -43,22 +43,21 @@ Gem::Specification.new do |s|
43
43
  ]
44
44
 
45
45
  if s.respond_to? :specification_version then
46
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
47
46
  s.specification_version = 3
48
47
 
49
48
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
50
- s.add_runtime_dependency(%q<redis>, ["~> 2.1.1"])
49
+ s.add_runtime_dependency(%q<redis>, ["~> 2.2.0"])
51
50
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
52
51
  s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
53
52
  s.add_development_dependency(%q<rcov>, [">= 0"])
54
53
  else
55
- s.add_dependency(%q<redis>, ["~> 2.1.1"])
54
+ s.add_dependency(%q<redis>, ["~> 2.2.0"])
56
55
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
57
56
  s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
58
57
  s.add_dependency(%q<rcov>, [">= 0"])
59
58
  end
60
59
  else
61
- s.add_dependency(%q<redis>, ["~> 2.1.1"])
60
+ s.add_dependency(%q<redis>, ["~> 2.2.0"])
62
61
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
63
62
  s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
64
63
  s.add_dependency(%q<rcov>, [">= 0"])
@@ -1,42 +1,69 @@
1
1
  require 'redis'
2
2
 
3
3
  class Leaderboard
4
- VERSION = '1.0.5'.freeze
4
+ VERSION = '2.0.0'.freeze
5
5
 
6
6
  DEFAULT_PAGE_SIZE = 25
7
+ DEFAULT_OPTIONS = {
8
+ :page_size => DEFAULT_PAGE_SIZE
9
+ }
10
+
7
11
  DEFAULT_REDIS_HOST = 'localhost'
8
- DEFAULT_REDIS_PORT = 6379
12
+ DEFAULT_REDIS_PORT = 6379
13
+ DEFAULT_REDIS_OPTIONS = {
14
+ :host => DEFAULT_REDIS_HOST,
15
+ :port => DEFAULT_REDIS_PORT
16
+ }
17
+
18
+ DEFAULT_LEADERBOARD_REQUEST_OPTIONS = {
19
+ :with_scores => true,
20
+ :with_rank => true,
21
+ :use_zero_index_for_rank => false,
22
+ :page_size => nil
23
+ }
9
24
 
10
- attr_reader :host
11
- attr_reader :port
12
25
  attr_reader :leaderboard_name
13
26
  attr_accessor :page_size
14
27
 
15
- def initialize(leaderboard_name, host = DEFAULT_REDIS_HOST, port = DEFAULT_REDIS_PORT, page_size = DEFAULT_PAGE_SIZE, redis_options = {})
28
+ def initialize(leaderboard_name, options = DEFAULT_OPTIONS, redis_options = DEFAULT_REDIS_OPTIONS)
16
29
  @leaderboard_name = leaderboard_name
17
- @host = host
18
- @port = port
19
30
 
20
- if page_size < 1
21
- page_size = DEFAULT_PAGE_SIZE
31
+ @page_size = options[:page_size]
32
+ if @page_size < 1
33
+ @page_size = DEFAULT_PAGE_SIZE
22
34
  end
23
35
 
36
+ @redis_connection = redis_options[:redis_connection]
37
+ unless @redis_connection.nil?
38
+ redis_options.delete(:redis_connection)
39
+ end
40
+
41
+ @redis_connection = Redis.new(redis_options) if @redis_connection.nil?
42
+ end
43
+
44
+ def page_size=(page_size)
45
+ page_size = DEFAULT_PAGE_SIZE if page_size < 1
46
+
24
47
  @page_size = page_size
25
-
26
- redis_options = redis_options.dup
27
- redis_options[:host] ||= @host
28
- redis_options[:port] ||= @port
29
-
30
- @redis_options = redis_options
31
-
32
- @redis_connection = Redis.new(@redis_options)
48
+ end
49
+
50
+ def disconnect
51
+ @redis_connection.client.disconnect
52
+ end
53
+
54
+ def delete_leaderboard
55
+ delete_leaderboard_named(@leaderboard_name)
56
+ end
57
+
58
+ def delete_leaderboard_named(leaderboard_name)
59
+ @redis_connection.del(leaderboard_name)
33
60
  end
34
61
 
35
- def add_member(member, score)
36
- add_member_to(@leaderboard_name, member, score)
62
+ def rank_member(member, score)
63
+ rank_member_in(@leaderboard_name, member, score)
37
64
  end
38
65
 
39
- def add_member_to(leaderboard_name, member, score)
66
+ def rank_member_in(leaderboard_name, member, score)
40
67
  @redis_connection.zadd(leaderboard_name, score, member)
41
68
  end
42
69
 
@@ -114,7 +141,17 @@ class Leaderboard
114
141
  end
115
142
 
116
143
  def score_and_rank_for_in(leaderboard_name, member, use_zero_index_for_rank = false)
117
- {:member => member, :score => score_for_in(leaderboard_name, member), :rank => rank_for_in(leaderboard_name, member, use_zero_index_for_rank)}
144
+ responses = @redis_connection.multi do |transaction|
145
+ transaction.zscore(leaderboard_name, member)
146
+ transaction.zrevrank(leaderboard_name, member)
147
+ end
148
+
149
+ responses[0] = responses[0].to_f
150
+ if !use_zero_index_for_rank
151
+ responses[1] = responses[1] + 1 rescue nil
152
+ end
153
+
154
+ {:member => member, :score => responses[0], :rank => responses[1]}
118
155
  end
119
156
 
120
157
  def remove_members_in_score_range(min_score, max_score)
@@ -125,17 +162,17 @@ class Leaderboard
125
162
  @redis_connection.zremrangebyscore(leaderboard_name, min_score, max_score)
126
163
  end
127
164
 
128
- def leaders(current_page, with_scores = true, with_rank = true, use_zero_index_for_rank = false, page_size = nil)
129
- leaders_in(@leaderboard_name, current_page, with_scores, with_rank, use_zero_index_for_rank, page_size)
165
+ def leaders(current_page, options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
166
+ leaders_in(@leaderboard_name, current_page, options)
130
167
  end
131
168
 
132
- def leaders_in(leaderboard_name, current_page, with_scores = true, with_rank = true, use_zero_index_for_rank = false, page_size = nil)
169
+ def leaders_in(leaderboard_name, current_page, options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
133
170
  if current_page < 1
134
171
  current_page = 1
135
172
  end
173
+
174
+ page_size = validate_page_size(options[:page_size]) || @page_size
136
175
 
137
- page_size ||= @page_size
138
-
139
176
  if current_page > total_pages_in(leaderboard_name, page_size)
140
177
  current_page = total_pages_in(leaderboard_name, page_size)
141
178
  end
@@ -148,23 +185,23 @@ class Leaderboard
148
185
  end
149
186
 
150
187
  ending_offset = (starting_offset + page_size) - 1
151
-
152
- raw_leader_data = @redis_connection.zrevrange(leaderboard_name, starting_offset, ending_offset, :with_scores => with_scores)
188
+
189
+ raw_leader_data = @redis_connection.zrevrange(leaderboard_name, starting_offset, ending_offset, :with_scores => false)
153
190
  if raw_leader_data
154
- massage_leader_data(leaderboard_name, raw_leader_data, with_scores, with_rank, use_zero_index_for_rank)
191
+ return ranked_in_list_in(leaderboard_name, raw_leader_data, options)
155
192
  else
156
- return nil
193
+ return []
157
194
  end
158
195
  end
159
196
 
160
- def around_me(member, with_scores = true, with_rank = true, use_zero_index_for_rank = false, page_size = nil)
161
- around_me_in(@leaderboard_name, member, with_scores, with_rank, use_zero_index_for_rank, page_size)
197
+ def around_me(member, options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
198
+ around_me_in(@leaderboard_name, member, options)
162
199
  end
163
200
 
164
- def around_me_in(leaderboard_name, member, with_scores = true, with_rank = true, use_zero_index_for_rank = false, page_size = nil)
201
+ def around_me_in(leaderboard_name, member, options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
165
202
  reverse_rank_for_member = @redis_connection.zrevrank(leaderboard_name, member)
166
203
 
167
- page_size ||= @page_size
204
+ page_size = validate_page_size(options[:page_size]) || @page_size
168
205
 
169
206
  starting_offset = reverse_rank_for_member - (page_size / 2)
170
207
  if starting_offset < 0
@@ -173,26 +210,50 @@ class Leaderboard
173
210
 
174
211
  ending_offset = (starting_offset + page_size) - 1
175
212
 
176
- raw_leader_data = @redis_connection.zrevrange(leaderboard_name, starting_offset, ending_offset, :with_scores => with_scores)
213
+ raw_leader_data = @redis_connection.zrevrange(leaderboard_name, starting_offset, ending_offset, :with_scores => false)
177
214
  if raw_leader_data
178
- massage_leader_data(leaderboard_name, raw_leader_data, with_scores, with_rank, use_zero_index_for_rank)
215
+ return ranked_in_list_in(leaderboard_name, raw_leader_data, options)
179
216
  else
180
- return nil
217
+ return []
181
218
  end
182
219
  end
183
220
 
184
- def ranked_in_list(members, with_scores = true, use_zero_index_for_rank = false)
185
- ranked_in_list_in(@leaderboard_name, members, with_scores, use_zero_index_for_rank)
221
+ def ranked_in_list(members, options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
222
+ ranked_in_list_in(@leaderboard_name, members, options)
186
223
  end
187
224
 
188
- def ranked_in_list_in(leaderboard_name, members, with_scores = true, use_zero_index_for_rank = false)
225
+ def ranked_in_list_in(leaderboard_name, members, options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
189
226
  ranks_for_members = []
190
227
 
191
- members.each do |member|
228
+ responses = @redis_connection.multi do |transaction|
229
+ members.each do |member|
230
+ transaction.zrevrank(leaderboard_name, member) if options[:with_rank]
231
+ transaction.zscore(leaderboard_name, member) if options[:with_scores]
232
+ end
233
+ end
234
+
235
+ members.each_with_index do |member, index|
192
236
  data = {}
193
237
  data[:member] = member
194
- data[:rank] = rank_for_in(leaderboard_name, member, use_zero_index_for_rank)
195
- data[:score] = score_for_in(leaderboard_name, member) if with_scores
238
+ if options[:with_scores]
239
+ if options[:with_rank]
240
+ if options[:use_zero_index_for_rank]
241
+ data[:rank] = responses[index * 2]
242
+ else
243
+ data[:rank] = responses[index * 2] + 1
244
+ end
245
+ end
246
+
247
+ data[:score] = responses[index * 2 + 1].to_f
248
+ else
249
+ if options[:with_rank]
250
+ if options[:use_zero_index_for_rank]
251
+ data[:rank] = responses[index]
252
+ else
253
+ data[:rank] = responses[index] + 1
254
+ end
255
+ end
256
+ end
196
257
 
197
258
  ranks_for_members << data
198
259
  end
@@ -212,29 +273,11 @@ class Leaderboard
212
273
 
213
274
  private
214
275
 
215
- def massage_leader_data(leaderboard_name, leaders, with_scores, with_rank, use_zero_index_for_rank)
216
- member_attribute = true
217
- leader_data = []
218
-
219
- data = {}
220
- leaders.each do |leader_data_item|
221
- if member_attribute
222
- data[:member] = leader_data_item
223
- else
224
- data[:score] = leader_data_item.to_f
225
- data[:rank] = rank_for_in(leaderboard_name, data[:member], use_zero_index_for_rank) if with_rank
226
- leader_data << data
227
- data = {}
228
- end
229
-
230
- if with_scores
231
- member_attribute = !member_attribute
232
- else
233
- leader_data << data
234
- data = {}
235
- end
276
+ def validate_page_size(page_size)
277
+ if page_size && page_size < 1
278
+ page_size = DEFAULT_PAGE_SIZE
236
279
  end
237
280
 
238
- leader_data
281
+ page_size
239
282
  end
240
283
  end
@@ -8,64 +8,92 @@ class TestLeaderboard < Test::Unit::TestCase
8
8
 
9
9
  def teardown
10
10
  @redis_connection.flushdb
11
+ @leaderboard.disconnect
12
+ @redis_connection.client.disconnect
11
13
  end
12
14
 
13
15
  def test_version
14
- assert_equal '1.0.5', Leaderboard::VERSION
16
+ assert_equal '2.0.0', Leaderboard::VERSION
15
17
  end
16
18
 
17
19
  def test_initialize_with_defaults
18
20
  assert_equal 'name', @leaderboard.leaderboard_name
19
- assert_equal 'localhost', @leaderboard.host
20
- assert_equal 6379, @leaderboard.port
21
21
  assert_equal Leaderboard::DEFAULT_PAGE_SIZE, @leaderboard.page_size
22
22
  end
23
23
 
24
+ def test_disconnect
25
+ assert_equal nil, @leaderboard.disconnect
26
+ end
27
+
28
+ def test_will_automatically_reconnect_after_a_disconnect
29
+ assert_equal 0, @leaderboard.total_members
30
+ rank_members_in_leaderboard(5)
31
+ assert_equal 5, @leaderboard.total_members
32
+ assert_equal nil, @leaderboard.disconnect
33
+ assert_equal 5, @leaderboard.total_members
34
+ end
35
+
24
36
  def test_page_size_is_default_page_size_if_set_to_invalid_value
25
- @leaderboard = Leaderboard.new('name', 'localhost', 6379, 0)
37
+ some_leaderboard = Leaderboard.new('name', {:page_size => 0})
26
38
 
27
- assert_equal Leaderboard::DEFAULT_PAGE_SIZE, @leaderboard.page_size
39
+ assert_equal Leaderboard::DEFAULT_PAGE_SIZE, some_leaderboard.page_size
40
+ some_leaderboard.disconnect
28
41
  end
29
42
 
30
- def test_add_member_and_total_members
31
- @leaderboard.add_member('member', 1)
43
+ def test_delete_leaderboard
44
+ rank_members_in_leaderboard
45
+
46
+ assert_equal true, @redis_connection.exists('name')
47
+ @leaderboard.delete_leaderboard
48
+ assert_equal false, @redis_connection.exists('name')
49
+ end
50
+
51
+ def test_can_pass_existing_redis_connection_to_initializer
52
+ @leaderboard = Leaderboard.new('name', Leaderboard::DEFAULT_OPTIONS, {:redis_connection => @redis_connection})
53
+ rank_members_in_leaderboard
54
+
55
+ assert_equal 1, @redis_connection.info["connected_clients"].to_i
56
+ end
57
+
58
+ def test_rank_member_and_total_members
59
+ @leaderboard.rank_member('member', 1)
32
60
 
33
61
  assert_equal 1, @leaderboard.total_members
34
62
  end
35
63
 
36
64
  def test_total_members_in_score_range
37
- add_members_to_leaderboard(5)
65
+ rank_members_in_leaderboard(5)
38
66
 
39
67
  assert_equal 3, @leaderboard.total_members_in_score_range(2, 4)
40
68
  end
41
69
 
42
70
  def test_rank_for
43
- add_members_to_leaderboard(5)
71
+ rank_members_in_leaderboard(5)
44
72
 
45
73
  assert_equal 2, @leaderboard.rank_for('member_4')
46
74
  assert_equal 1, @leaderboard.rank_for('member_4', true)
47
75
  end
48
76
 
49
77
  def test_score_for
50
- add_members_to_leaderboard(5)
78
+ rank_members_in_leaderboard(5)
51
79
 
52
80
  assert_equal 4, @leaderboard.score_for('member_4')
53
81
  end
54
82
 
55
83
  def test_total_pages
56
- add_members_to_leaderboard(10)
84
+ rank_members_in_leaderboard(10)
57
85
 
58
86
  assert_equal 1, @leaderboard.total_pages
59
87
 
60
88
  @redis_connection.flushdb
61
89
 
62
- add_members_to_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE + 1)
90
+ rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE + 1)
63
91
 
64
92
  assert_equal 2, @leaderboard.total_pages
65
93
  end
66
94
 
67
95
  def test_leaders
68
- add_members_to_leaderboard(25)
96
+ rank_members_in_leaderboard(25)
69
97
 
70
98
  assert_equal 25, @leaderboard.total_members
71
99
 
@@ -79,7 +107,7 @@ class TestLeaderboard < Test::Unit::TestCase
79
107
  end
80
108
 
81
109
  def test_leaders_with_multiple_pages
82
- add_members_to_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)
110
+ rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)
83
111
 
84
112
  assert_equal Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1, @leaderboard.total_members
85
113
 
@@ -102,8 +130,21 @@ class TestLeaderboard < Test::Unit::TestCase
102
130
  assert_equal 1, leaders.size
103
131
  end
104
132
 
133
+ def test_leaders_without_retrieving_scores_and_ranks
134
+ rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
135
+
136
+ assert_equal Leaderboard::DEFAULT_PAGE_SIZE, @leaderboard.total_members
137
+ leaders = @leaderboard.leaders(1, {:with_scores => false, :with_ranks => false})
138
+
139
+ member_25 = {:member => 'member_25'}
140
+ assert_equal member_25, leaders[0]
141
+
142
+ member_1 = {:member => 'member_1'}
143
+ assert_equal member_1, leaders[24]
144
+ end
145
+
105
146
  def test_around_me
106
- add_members_to_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)
147
+ rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)
107
148
 
108
149
  assert_equal Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1, @leaderboard.total_members
109
150
 
@@ -118,12 +159,12 @@ class TestLeaderboard < Test::Unit::TestCase
118
159
  end
119
160
 
120
161
  def test_ranked_in_list
121
- add_members_to_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
162
+ rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
122
163
 
123
164
  assert_equal Leaderboard::DEFAULT_PAGE_SIZE, @leaderboard.total_members
124
165
 
125
166
  members = ['member_1', 'member_5', 'member_10']
126
- ranked_members = @leaderboard.ranked_in_list(members, true)
167
+ ranked_members = @leaderboard.ranked_in_list(members, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
127
168
 
128
169
  assert_equal 3, ranked_members.size
129
170
 
@@ -137,8 +178,25 @@ class TestLeaderboard < Test::Unit::TestCase
137
178
  assert_equal 10, ranked_members[2][:score]
138
179
  end
139
180
 
181
+ def test_ranked_in_list_without_scores
182
+ rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
183
+
184
+ assert_equal Leaderboard::DEFAULT_PAGE_SIZE, @leaderboard.total_members
185
+
186
+ members = ['member_1', 'member_5', 'member_10']
187
+ ranked_members = @leaderboard.ranked_in_list(members, {:with_scores => false, :with_rank => true, :use_zero_index_for_rank => false})
188
+
189
+ assert_equal 3, ranked_members.size
190
+
191
+ assert_equal 25, ranked_members[0][:rank]
192
+
193
+ assert_equal 21, ranked_members[1][:rank]
194
+
195
+ assert_equal 16, ranked_members[2][:rank]
196
+ end
197
+
140
198
  def test_remove_member
141
- add_members_to_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
199
+ rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
142
200
 
143
201
  assert_equal Leaderboard::DEFAULT_PAGE_SIZE, @leaderboard.total_members
144
202
 
@@ -149,7 +207,7 @@ class TestLeaderboard < Test::Unit::TestCase
149
207
  end
150
208
 
151
209
  def test_change_score_for
152
- @leaderboard.add_member('member_1', 5)
210
+ @leaderboard.rank_member('member_1', 5)
153
211
  assert_equal 5, @leaderboard.score_for('member_1')
154
212
 
155
213
  @leaderboard.change_score_for('member_1', 5)
@@ -160,22 +218,31 @@ class TestLeaderboard < Test::Unit::TestCase
160
218
  end
161
219
 
162
220
  def test_check_member
163
- @leaderboard.add_member('member_1', 10)
221
+ @leaderboard.rank_member('member_1', 10)
164
222
 
165
223
  assert_equal true, @leaderboard.check_member?('member_1')
166
224
  assert_equal false, @leaderboard.check_member?('member_2')
167
225
  end
168
226
 
169
227
  def test_can_change_page_size_and_have_it_reflected_in_size_of_result_set
170
- add_members_to_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
228
+ rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
171
229
 
172
230
  @leaderboard.page_size = 5
231
+
173
232
  assert_equal 5, @leaderboard.total_pages
174
233
  assert_equal 5, @leaderboard.leaders(1).size
175
234
  end
176
235
 
236
+ def test_cannot_set_page_size_to_invalid_page_size
237
+ rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
238
+
239
+ @leaderboard.page_size = 0
240
+ assert_equal 1, @leaderboard.total_pages
241
+ assert_equal Leaderboard::DEFAULT_PAGE_SIZE, @leaderboard.leaders(1).size
242
+ end
243
+
177
244
  def test_score_and_rank_for
178
- add_members_to_leaderboard
245
+ rank_members_in_leaderboard
179
246
 
180
247
  data = @leaderboard.score_and_rank_for('member_1')
181
248
  assert_equal 'member_1', data[:member]
@@ -184,13 +251,13 @@ class TestLeaderboard < Test::Unit::TestCase
184
251
  end
185
252
 
186
253
  def test_remove_members_in_score_range
187
- add_members_to_leaderboard
254
+ rank_members_in_leaderboard
188
255
 
189
256
  assert_equal 5, @leaderboard.total_members
190
257
 
191
- @leaderboard.add_member('cheater_1', 100)
192
- @leaderboard.add_member('cheater_2', 101)
193
- @leaderboard.add_member('cheater_3', 102)
258
+ @leaderboard.rank_member('cheater_1', 100)
259
+ @leaderboard.rank_member('cheater_2', 101)
260
+ @leaderboard.rank_member('cheater_3', 102)
194
261
 
195
262
  assert_equal 8, @leaderboard.total_members
196
263
 
@@ -205,14 +272,14 @@ class TestLeaderboard < Test::Unit::TestCase
205
272
  end
206
273
 
207
274
  def test_merge_leaderboards
208
- foo = Leaderboard.new('foo')
275
+ foo = Leaderboard.new('foo')
209
276
  bar = Leaderboard.new('bar')
210
277
 
211
- foo.add_member('foo_1', 1)
212
- foo.add_member('foo_2', 2)
213
- bar.add_member('bar_1', 3)
214
- bar.add_member('bar_2', 4)
215
- bar.add_member('bar_3', 5)
278
+ foo.rank_member('foo_1', 1)
279
+ foo.rank_member('foo_2', 2)
280
+ bar.rank_member('bar_1', 3)
281
+ bar.rank_member('bar_2', 4)
282
+ bar.rank_member('bar_3', 5)
216
283
 
217
284
  foobar_keys = foo.merge_leaderboards('foobar', ['bar'])
218
285
  assert_equal 5, foobar_keys
@@ -224,18 +291,22 @@ class TestLeaderboard < Test::Unit::TestCase
224
291
  assert_equal 1, first_leader_in_foobar[:rank]
225
292
  assert_equal 'bar_3', first_leader_in_foobar[:member]
226
293
  assert_equal 5, first_leader_in_foobar[:score]
294
+
295
+ foo.disconnect
296
+ bar.disconnect
297
+ foobar.disconnect
227
298
  end
228
299
 
229
300
  def test_intersect_leaderboards
230
301
  foo = Leaderboard.new('foo')
231
302
  bar = Leaderboard.new('bar')
232
303
 
233
- foo.add_member('foo_1', 1)
234
- foo.add_member('foo_2', 2)
235
- foo.add_member('bar_3', 6)
236
- bar.add_member('bar_1', 3)
237
- bar.add_member('foo_1', 4)
238
- bar.add_member('bar_3', 5)
304
+ foo.rank_member('foo_1', 1)
305
+ foo.rank_member('foo_2', 2)
306
+ foo.rank_member('bar_3', 6)
307
+ bar.rank_member('bar_1', 3)
308
+ bar.rank_member('foo_1', 4)
309
+ bar.rank_member('bar_3', 5)
239
310
 
240
311
  foobar_keys = foo.intersect_leaderboards('foobar', ['bar'], {:aggregate => :max})
241
312
  assert_equal 2, foobar_keys
@@ -247,53 +318,57 @@ class TestLeaderboard < Test::Unit::TestCase
247
318
  assert_equal 1, first_leader_in_foobar[:rank]
248
319
  assert_equal 'bar_3', first_leader_in_foobar[:member]
249
320
  assert_equal 6, first_leader_in_foobar[:score]
321
+
322
+ foo.disconnect
323
+ bar.disconnect
324
+ foobar.disconnect
250
325
  end
251
326
 
252
327
  def test_massage_leader_data_respects_with_scores
253
- add_members_to_leaderboard(25)
328
+ rank_members_in_leaderboard(25)
254
329
 
255
330
  assert_equal 25, @leaderboard.total_members
256
331
 
257
- leaders = @leaderboard.leaders(1, false, false, false)
332
+ leaders = @leaderboard.leaders(1, {:with_scores => false, :with_rank => false})
258
333
  assert_not_nil leaders[0][:member]
259
334
  assert_nil leaders[0][:score]
260
335
  assert_nil leaders[0][:rank]
261
336
 
262
337
  @leaderboard.page_size = 25
263
- leaders = @leaderboard.leaders(1, false, false, false)
338
+ leaders = @leaderboard.leaders(1, {:with_scores => false, :with_rank => false})
264
339
  assert_equal 25, leaders.size
265
340
 
266
341
  @leaderboard.page_size = Leaderboard::DEFAULT_PAGE_SIZE
267
- leaders = @leaderboard.leaders(1, true, true, false)
342
+ leaders = @leaderboard.leaders(1, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
268
343
  assert_not_nil leaders[0][:member]
269
344
  assert_not_nil leaders[0][:score]
270
345
  assert_not_nil leaders[0][:rank]
271
346
 
272
347
  @leaderboard.page_size = 25
273
- leaders = @leaderboard.leaders(1, true, true, false)
348
+ leaders = @leaderboard.leaders(1, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
274
349
  assert_equal 25, leaders.size
275
350
  end
276
351
 
277
352
  def test_total_pages_in_with_new_page_size
278
- add_members_to_leaderboard(25)
353
+ rank_members_in_leaderboard(25)
279
354
 
280
355
  assert_equal 1, @leaderboard.total_pages_in(@leaderboard.leaderboard_name)
281
356
  assert_equal 5, @leaderboard.total_pages_in(@leaderboard.leaderboard_name, 5)
282
357
  end
283
358
 
284
359
  def test_leaders_call_with_new_page_size
285
- add_members_to_leaderboard(25)
360
+ rank_members_in_leaderboard(25)
286
361
 
287
- assert_equal 5, @leaderboard.leaders(1, true, true, false, 5).size
288
- assert_equal 10, @leaderboard.leaders(1, true, true, false, 10).size
289
- assert_equal 10, @leaderboard.leaders(2, true, true, false, 10).size
290
- assert_equal 5, @leaderboard.leaders(3, true, true, false, 10).size
362
+ assert_equal 5, @leaderboard.leaders(1, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS.merge({:page_size => 5})).size
363
+ assert_equal 10, @leaderboard.leaders(1, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS.merge({:page_size => 10})).size
364
+ assert_equal 10, @leaderboard.leaders(2, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS.merge({:page_size => 10})).size
365
+ assert_equal 5, @leaderboard.leaders(3, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS.merge({:page_size => 10})).size
291
366
  end
292
367
 
293
368
  def test_around_me_call_with_new_page_size
294
- add_members_to_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)
369
+ rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)
295
370
 
296
- leaders_around_me = @leaderboard.around_me('member_30', true, true, false, 3)
371
+ leaders_around_me = @leaderboard.around_me('member_30', Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS.merge({:page_size => 3}))
297
372
  assert_equal 3, leaders_around_me.size
298
373
  assert_equal 'member_31', leaders_around_me[0][:member]
299
374
  assert_equal 'member_29', leaders_around_me[2][:member]
@@ -301,9 +376,9 @@ class TestLeaderboard < Test::Unit::TestCase
301
376
 
302
377
  private
303
378
 
304
- def add_members_to_leaderboard(members_to_add = 5)
379
+ def rank_members_in_leaderboard(members_to_add = 5)
305
380
  1.upto(members_to_add) do |index|
306
- @leaderboard.add_member("member_#{index}", index)
381
+ @leaderboard.rank_member("member_#{index}", index)
307
382
  end
308
383
  end
309
384
  end
metadata CHANGED
@@ -1,95 +1,68 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: leaderboard
3
- version: !ruby/object:Gem::Version
4
- hash: 29
5
- prerelease: false
6
- segments:
7
- - 1
8
- - 0
9
- - 5
10
- version: 1.0.5
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - David Czarnecki
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-05-04 00:00:00 -04:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- type: :runtime
23
- prerelease: false
12
+ date: 2011-08-17 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
24
15
  name: redis
25
- version_requirements: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &70114074547140 !ruby/object:Gem::Requirement
26
17
  none: false
27
- requirements:
18
+ requirements:
28
19
  - - ~>
29
- - !ruby/object:Gem::Version
30
- hash: 9
31
- segments:
32
- - 2
33
- - 1
34
- - 1
35
- version: 2.1.1
36
- requirement: *id001
37
- - !ruby/object:Gem::Dependency
38
- type: :development
20
+ - !ruby/object:Gem::Version
21
+ version: 2.2.0
22
+ type: :runtime
39
23
  prerelease: false
24
+ version_requirements: *70114074547140
25
+ - !ruby/object:Gem::Dependency
40
26
  name: bundler
41
- version_requirements: &id002 !ruby/object:Gem::Requirement
27
+ requirement: &70114074545640 !ruby/object:Gem::Requirement
42
28
  none: false
43
- requirements:
29
+ requirements:
44
30
  - - ~>
45
- - !ruby/object:Gem::Version
46
- hash: 23
47
- segments:
48
- - 1
49
- - 0
50
- - 0
31
+ - !ruby/object:Gem::Version
51
32
  version: 1.0.0
52
- requirement: *id002
53
- - !ruby/object:Gem::Dependency
54
33
  type: :development
55
34
  prerelease: false
35
+ version_requirements: *70114074545640
36
+ - !ruby/object:Gem::Dependency
56
37
  name: jeweler
57
- version_requirements: &id003 !ruby/object:Gem::Requirement
38
+ requirement: &70114074543920 !ruby/object:Gem::Requirement
58
39
  none: false
59
- requirements:
40
+ requirements:
60
41
  - - ~>
61
- - !ruby/object:Gem::Version
62
- hash: 7
63
- segments:
64
- - 1
65
- - 5
66
- - 2
42
+ - !ruby/object:Gem::Version
67
43
  version: 1.5.2
68
- requirement: *id003
69
- - !ruby/object:Gem::Dependency
70
44
  type: :development
71
45
  prerelease: false
46
+ version_requirements: *70114074543920
47
+ - !ruby/object:Gem::Dependency
72
48
  name: rcov
73
- version_requirements: &id004 !ruby/object:Gem::Requirement
49
+ requirement: &70114074539440 !ruby/object:Gem::Requirement
74
50
  none: false
75
- requirements:
76
- - - ">="
77
- - !ruby/object:Gem::Version
78
- hash: 3
79
- segments:
80
- - 0
81
- version: "0"
82
- requirement: *id004
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70114074539440
83
58
  description: Leaderboards backed by Redis in Ruby
84
59
  email: dczarnecki@agoragames.com
85
60
  executables: []
86
-
87
61
  extensions: []
88
-
89
- extra_rdoc_files:
62
+ extra_rdoc_files:
90
63
  - LICENSE.txt
91
64
  - README.rdoc
92
- files:
65
+ files:
93
66
  - .document
94
67
  - .rvmrc
95
68
  - CHANGELOG.markdown
@@ -104,40 +77,34 @@ files:
104
77
  - test/helper.rb
105
78
  - test/test.conf
106
79
  - test/test_leaderboard.rb
107
- has_rdoc: true
108
80
  homepage: http://github.com/agoragames/leaderboard
109
- licenses:
81
+ licenses:
110
82
  - MIT
111
83
  post_install_message:
112
84
  rdoc_options: []
113
-
114
- require_paths:
85
+ require_paths:
115
86
  - lib
116
- required_ruby_version: !ruby/object:Gem::Requirement
87
+ required_ruby_version: !ruby/object:Gem::Requirement
117
88
  none: false
118
- requirements:
119
- - - ">="
120
- - !ruby/object:Gem::Version
121
- hash: 3
122
- segments:
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ segments:
123
94
  - 0
124
- version: "0"
125
- required_rubygems_version: !ruby/object:Gem::Requirement
95
+ hash: -2495258638232902776
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
97
  none: false
127
- requirements:
128
- - - ">="
129
- - !ruby/object:Gem::Version
130
- hash: 3
131
- segments:
132
- - 0
133
- version: "0"
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
134
102
  requirements: []
135
-
136
103
  rubyforge_project:
137
- rubygems_version: 1.3.7
104
+ rubygems_version: 1.8.6
138
105
  signing_key:
139
106
  specification_version: 3
140
107
  summary: Leaderboards backed by Redis in Ruby
141
- test_files:
108
+ test_files:
142
109
  - test/helper.rb
143
110
  - test/test_leaderboard.rb