leaderboard 2.5.0 → 3.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/.rvmrc +0 -1
- data/CHANGELOG.markdown +7 -0
- data/README.markdown +31 -26
- data/Rakefile +2 -1
- data/lib/leaderboard/version.rb +1 -1
- data/lib/leaderboard.rb +41 -71
- data/spec/leaderboard_spec.rb +66 -74
- data/spec/reverse_leaderboard_spec.rb +54 -60
- data/spec/version_spec.rb +1 -1
- metadata +6 -9
data/.rvmrc
CHANGED
data/CHANGELOG.markdown
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## leaderboard 3.0.0.rc1 (2012-11-08)
|
4
|
+
|
5
|
+
* Removes `:use_zero_index_for_rank_option` as valid option for requesting data from the leaderboard. [Original proposal](https://github.com/agoragames/leaderboard/pull/27)
|
6
|
+
* Optional member data is stored in a single hash. [Original proposal](https://github.com/agoragames/leaderboard/pull/26)
|
7
|
+
* Adds `:sort_by` as valid option for requesting data from the leaderboard. [Original proposal](https://github.com/agoragames/leaderboard/pull/30)
|
8
|
+
* Removes `:with_scores` and `:with_ranks` as valid options for requesting data from the leaderboard.
|
9
|
+
|
3
10
|
## leaderboard 2.5.0 (2012-10-12)
|
4
11
|
|
5
12
|
* Added `members_from_rank_range` and `members_from_rank_range_in` methods to be able to retrieve members from a leaderboard in a given rank range.
|
data/README.markdown
CHANGED
@@ -119,30 +119,34 @@ Get some information about your leaderboard:
|
|
119
119
|
=> 1
|
120
120
|
```
|
121
121
|
|
122
|
-
The `rank_member` call will also accept an optional
|
123
|
-
be used to store other information about a given member in the leaderboard. This
|
124
|
-
may be useful in situations where you are storing member IDs in the leaderboard and
|
125
|
-
you want to be able to store a member name for display.
|
122
|
+
The `rank_member` call will also accept an optional string member data that could
|
123
|
+
be used to store other information about a given member in the leaderboard. This
|
124
|
+
may be useful in situations where you are storing member IDs in the leaderboard and
|
125
|
+
you want to be able to store a member name for display. You could use JSON to
|
126
|
+
encode a Hash of member data. Example:
|
126
127
|
|
127
128
|
```ruby
|
128
|
-
|
129
|
+
require 'json'
|
130
|
+
highscore_lb.rank_member('84849292', 1, JSON.generate({'username' => 'member_name'})
|
129
131
|
```
|
130
132
|
|
131
133
|
You can retrieve, update and remove the optional member data using the
|
132
134
|
`member_data_for`, `update_member_data` and `remove_member_data` calls. Example:
|
133
135
|
|
134
136
|
```ruby
|
135
|
-
highscore_lb.member_data_for('84849292')
|
137
|
+
JSON.parse(highscore_lb.member_data_for('84849292'))
|
136
138
|
=> {"username"=>"member_name"}
|
137
139
|
|
138
|
-
highscore_lb.update_member_data('84849292', {'last_updated' => Time.now, 'username' => 'updated_member_name'})
|
139
|
-
=> "OK"
|
140
|
-
highscore_lb.member_data_for('84849292')
|
140
|
+
highscore_lb.update_member_data('84849292', JSON.generate({'last_updated' => Time.now, 'username' => 'updated_member_name'}))
|
141
|
+
=> "OK"
|
142
|
+
JSON.parse(highscore_lb.member_data_for('84849292'))
|
141
143
|
=> {"username"=>"updated_member_name", "last_updated"=>"2012-06-09 09:11:06 -0400"}
|
142
144
|
|
143
145
|
highscore_lb.remove_member_data('84849292')
|
144
146
|
```
|
145
147
|
|
148
|
+
If you delete the leaderboard, ALL of the member data is deleted as well.
|
149
|
+
|
146
150
|
Get some information about a specific member(s) in the leaderboard:
|
147
151
|
|
148
152
|
```ruby
|
@@ -162,23 +166,10 @@ Get page 1 in the leaderboard:
|
|
162
166
|
highscore_lb.leaders(1)
|
163
167
|
=> [{: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}]
|
164
168
|
```
|
165
|
-
|
166
|
-
You can pass various options to the calls `leaders`, `around_me` and `ranked_in_list`.
|
167
|
-
Valid options are `:
|
168
|
-
|
169
|
-
without ranks:
|
170
|
-
|
171
|
-
```ruby
|
172
|
-
highscore_lb.leaders(1, :with_rank => false)
|
173
|
-
=> [{: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}]
|
174
|
-
```
|
175
|
-
|
176
|
-
Below is an example of retrieving the first page in the leaderboard without scores or ranks:
|
177
|
-
|
178
|
-
```ruby
|
179
|
-
highscore_lb.leaders(1, :with_scores => false, :with_rank => false)
|
180
|
-
=> [{: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"}]
|
181
|
-
```
|
169
|
+
|
170
|
+
You can pass various options to the calls `leaders`, `around_me` and `ranked_in_list`.
|
171
|
+
Valid options are `:with_member_data`, `:page_size` and `:sort_option`. Valid values for
|
172
|
+
`:sort_option` are `:none` (default), `:score` and `:rank`.
|
182
173
|
|
183
174
|
You can also use the `members` and `members_in` methods as aliases for the `leaders` and `leaders_in` methods.
|
184
175
|
|
@@ -231,6 +222,20 @@ members = highscore_lb.members_from_rank_range(1, 5)
|
|
231
222
|
=> [{:member=>"member_95", :rank=>1, :score=>95.0}, {:member=>"member_94", :rank=>2, :score=>94.0}, {:member=>"member_93", :rank=>3, :score=>93.0}, {:member=>"member_92", :rank=>4, :score=>92.0}, {:member=>"member_91", :rank=>5, :score=>91.0}]
|
232
223
|
```
|
233
224
|
|
225
|
+
The option `:sort_option` is useful for retrieving an arbitrary list of
|
226
|
+
members from a given leaderboard where you would like the data sorted
|
227
|
+
when returned. The follow examples demonstrate its use:
|
228
|
+
|
229
|
+
```ruby
|
230
|
+
friends = highscore_lb.ranked_in_list(['member_6', 'member_1', 'member_10'], :sort_by => :rank)
|
231
|
+
=> [{:member=>"member_10", :rank=>47, :score=>10.0}, {:member=>"member_6", :rank=>51, :score=>6.0}, {:member=>"member_1", :rank=>56, :score=>1.0}]
|
232
|
+
```
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
friends = highscore_lb.ranked_in_list(['member_6', 'member_1', 'member_10'], :sort_by => :score)
|
236
|
+
=> [{:member=>"member_1", :rank=>56, :score=>1.0}, {:member=>"member_6", :rank=>51, :score=>6.0}, {:member=>"member_10", :rank=>47, :score=>10.0}]
|
237
|
+
```
|
238
|
+
|
234
239
|
### Ranking multiple members in a leaderboard at once
|
235
240
|
|
236
241
|
Insert multiple data items for members and their associated scores:
|
data/Rakefile
CHANGED
@@ -10,6 +10,7 @@ end
|
|
10
10
|
|
11
11
|
task :default => :spec
|
12
12
|
|
13
|
+
desc "Run the specs against Ruby 1.8.7 and 1.9.3"
|
13
14
|
task :test_rubies do
|
14
|
-
system "rvm 1.8.7@leaderboard_gem,1.9.
|
15
|
+
system "rvm 1.8.7@leaderboard_gem,1.9.3@leaderboard_gem do rake spec"
|
15
16
|
end
|
data/lib/leaderboard/version.rb
CHANGED
data/lib/leaderboard.rb
CHANGED
@@ -27,17 +27,13 @@ class Leaderboard
|
|
27
27
|
}
|
28
28
|
|
29
29
|
# Default options when requesting data from a leaderboard.
|
30
|
-
# +:with_scores+ true: Return scores along with the member names.
|
31
|
-
# +:with_rank+ true: Return ranks along with the member names.
|
32
30
|
# +:with_member_data+ false: Return member data along with the member names.
|
33
|
-
# +:use_zero_index_for_rank+ false: If you want to 0-index ranks.
|
34
31
|
# +:page_size+ nil: The default page size will be used.
|
32
|
+
# +:sort_by+ :none: The default sort for a call to `ranked_in_list`.
|
35
33
|
DEFAULT_LEADERBOARD_REQUEST_OPTIONS = {
|
36
|
-
:with_scores => true,
|
37
|
-
:with_rank => true,
|
38
34
|
:with_member_data => false,
|
39
|
-
:
|
40
|
-
:
|
35
|
+
:page_size => nil,
|
36
|
+
:sort_by => :none
|
41
37
|
}
|
42
38
|
|
43
39
|
# Name of the leaderboard.
|
@@ -103,7 +99,10 @@ class Leaderboard
|
|
103
99
|
#
|
104
100
|
# @param leaderboard_name [String] Name of the leaderboard.
|
105
101
|
def delete_leaderboard_named(leaderboard_name)
|
106
|
-
@redis_connection.
|
102
|
+
@redis_connection.multi do |transaction|
|
103
|
+
transaction.del(leaderboard_name)
|
104
|
+
transaction.del(member_data_key(leaderboard_name))
|
105
|
+
end
|
107
106
|
end
|
108
107
|
|
109
108
|
# Rank a member in the leaderboard.
|
@@ -124,9 +123,7 @@ class Leaderboard
|
|
124
123
|
def rank_member_in(leaderboard_name, member, score, member_data)
|
125
124
|
@redis_connection.multi do |transaction|
|
126
125
|
transaction.zadd(leaderboard_name, score, member)
|
127
|
-
if member_data
|
128
|
-
transaction.hmset(member_data_key(leaderboard_name, member), *member_data.to_a.flatten)
|
129
|
-
end
|
126
|
+
transaction.hset(member_data_key(leaderboard_name), member, member_data) if member_data
|
130
127
|
end
|
131
128
|
end
|
132
129
|
|
@@ -146,7 +143,7 @@ class Leaderboard
|
|
146
143
|
#
|
147
144
|
# @return Hash of optional member data.
|
148
145
|
def member_data_for_in(leaderboard_name, member)
|
149
|
-
@redis_connection.
|
146
|
+
@redis_connection.hget(member_data_key(leaderboard_name), member)
|
150
147
|
end
|
151
148
|
|
152
149
|
# Update the optional member data for a given member in the leaderboard.
|
@@ -163,7 +160,7 @@ class Leaderboard
|
|
163
160
|
# @param member [String] Member name.
|
164
161
|
# @param member_data [Hash] Optional member data.
|
165
162
|
def update_member_data_in(leaderboard_name, member, member_data)
|
166
|
-
@redis_connection.
|
163
|
+
@redis_connection.hset(member_data_key(leaderboard_name), member, member_data)
|
167
164
|
end
|
168
165
|
|
169
166
|
# Remove the optional member data for a given member in the leaderboard.
|
@@ -178,7 +175,7 @@ class Leaderboard
|
|
178
175
|
# @param leaderboard_name [String] Name of the leaderboard.
|
179
176
|
# @param member [String] Member name.
|
180
177
|
def remove_member_data_in(leaderboard_name, member)
|
181
|
-
@redis_connection.
|
178
|
+
@redis_connection.hdel(member_data_key(leaderboard_name), member)
|
182
179
|
end
|
183
180
|
|
184
181
|
# Rank an array of members in the leaderboard.
|
@@ -218,7 +215,7 @@ class Leaderboard
|
|
218
215
|
def remove_member_from(leaderboard_name, member)
|
219
216
|
@redis_connection.multi do |transaction|
|
220
217
|
transaction.zrem(leaderboard_name, member)
|
221
|
-
transaction.del(member_data_key(leaderboard_name, member)
|
218
|
+
transaction.del(member_data_key(leaderboard_name), member)
|
222
219
|
end
|
223
220
|
end
|
224
221
|
|
@@ -299,33 +296,23 @@ class Leaderboard
|
|
299
296
|
# Retrieve the rank for a member in the leaderboard.
|
300
297
|
#
|
301
298
|
# @param member [String] Member name.
|
302
|
-
#
|
303
|
-
#
|
299
|
+
#
|
304
300
|
# @return the rank for a member in the leaderboard.
|
305
|
-
def rank_for(member
|
306
|
-
rank_for_in(@leaderboard_name, member
|
301
|
+
def rank_for(member)
|
302
|
+
rank_for_in(@leaderboard_name, member)
|
307
303
|
end
|
308
304
|
|
309
305
|
# Retrieve the rank for a member in the named leaderboard.
|
310
306
|
#
|
311
307
|
# @param leaderboard_name [String] Name of the leaderboard.
|
312
308
|
# @param member [String] Member name.
|
313
|
-
#
|
314
|
-
#
|
309
|
+
#
|
315
310
|
# @return the rank for a member in the leaderboard.
|
316
|
-
def rank_for_in(leaderboard_name, member
|
311
|
+
def rank_for_in(leaderboard_name, member)
|
317
312
|
if @reverse
|
318
|
-
|
319
|
-
return @redis_connection.zrank(leaderboard_name, member)
|
320
|
-
else
|
321
|
-
return @redis_connection.zrank(leaderboard_name, member) + 1 rescue nil
|
322
|
-
end
|
313
|
+
return @redis_connection.zrank(leaderboard_name, member) + 1 rescue nil
|
323
314
|
else
|
324
|
-
|
325
|
-
return @redis_connection.zrevrank(leaderboard_name, member)
|
326
|
-
else
|
327
|
-
return @redis_connection.zrevrank(leaderboard_name, member) + 1 rescue nil
|
328
|
-
end
|
315
|
+
return @redis_connection.zrevrank(leaderboard_name, member) + 1 rescue nil
|
329
316
|
end
|
330
317
|
end
|
331
318
|
|
@@ -370,21 +357,19 @@ class Leaderboard
|
|
370
357
|
# Retrieve the score and rank for a member in the leaderboard.
|
371
358
|
#
|
372
359
|
# @param member [String] Member name.
|
373
|
-
# @param use_zero_index_for_rank [boolean, false] If the returned rank should be 0-indexed.
|
374
360
|
#
|
375
361
|
# @return the score and rank for a member in the leaderboard as a Hash.
|
376
|
-
def score_and_rank_for(member
|
377
|
-
score_and_rank_for_in(@leaderboard_name, member
|
362
|
+
def score_and_rank_for(member)
|
363
|
+
score_and_rank_for_in(@leaderboard_name, member)
|
378
364
|
end
|
379
365
|
|
380
366
|
# Retrieve the score and rank for a member in the named leaderboard.
|
381
367
|
#
|
382
368
|
# @param leaderboard_name [String]Name of the leaderboard.
|
383
369
|
# @param member [String] Member name.
|
384
|
-
# @param use_zero_index_for_rank [boolean, false] If the returned rank should be 0-indexed.
|
385
370
|
#
|
386
371
|
# @return the score and rank for a member in the named leaderboard as a Hash.
|
387
|
-
def score_and_rank_for_in(leaderboard_name, member
|
372
|
+
def score_and_rank_for_in(leaderboard_name, member)
|
388
373
|
responses = @redis_connection.multi do |transaction|
|
389
374
|
transaction.zscore(leaderboard_name, member)
|
390
375
|
if @reverse
|
@@ -395,11 +380,9 @@ class Leaderboard
|
|
395
380
|
end
|
396
381
|
|
397
382
|
responses[0] = responses[0].to_f
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
{:member => member, :score => responses[0], :rank => responses[1]}
|
383
|
+
responses[1] = responses[1] + 1 rescue nil
|
384
|
+
|
385
|
+
{:member => member, :score => responses[0], :rank => responses[1]}
|
403
386
|
end
|
404
387
|
|
405
388
|
# Remove members from the leaderboard in a given score range.
|
@@ -795,38 +778,19 @@ class Leaderboard
|
|
795
778
|
responses = @redis_connection.multi do |transaction|
|
796
779
|
members.each do |member|
|
797
780
|
if @reverse
|
798
|
-
transaction.zrank(leaderboard_name, member)
|
781
|
+
transaction.zrank(leaderboard_name, member)
|
799
782
|
else
|
800
|
-
transaction.zrevrank(leaderboard_name, member)
|
783
|
+
transaction.zrevrank(leaderboard_name, member)
|
801
784
|
end
|
802
|
-
transaction.zscore(leaderboard_name, member)
|
785
|
+
transaction.zscore(leaderboard_name, member)
|
803
786
|
end
|
804
787
|
end
|
805
788
|
|
806
789
|
members.each_with_index do |member, index|
|
807
790
|
data = {}
|
808
791
|
data[:member] = member
|
809
|
-
|
810
|
-
|
811
|
-
if leaderboard_options[:use_zero_index_for_rank]
|
812
|
-
data[:rank] = responses[index * 2]
|
813
|
-
else
|
814
|
-
data[:rank] = responses[index * 2] + 1 rescue nil
|
815
|
-
end
|
816
|
-
|
817
|
-
data[:score] = responses[index * 2 + 1].to_f
|
818
|
-
else
|
819
|
-
data[:score] = responses[index].to_f
|
820
|
-
end
|
821
|
-
else
|
822
|
-
if leaderboard_options[:with_rank]
|
823
|
-
if leaderboard_options[:use_zero_index_for_rank]
|
824
|
-
data[:rank] = responses[index]
|
825
|
-
else
|
826
|
-
data[:rank] = responses[index] + 1 rescue nil
|
827
|
-
end
|
828
|
-
end
|
829
|
-
end
|
792
|
+
data[:rank] = responses[index * 2] + 1 rescue nil
|
793
|
+
data[:score] = responses[index * 2 + 1].to_f
|
830
794
|
|
831
795
|
if leaderboard_options[:with_member_data]
|
832
796
|
data[:member_data] = member_data_for_in(leaderboard_name, member)
|
@@ -835,6 +799,13 @@ class Leaderboard
|
|
835
799
|
ranks_for_members << data
|
836
800
|
end
|
837
801
|
|
802
|
+
case leaderboard_options[:sort_by]
|
803
|
+
when :rank
|
804
|
+
ranks_for_members = ranks_for_members.sort_by { |member| member[:rank] }
|
805
|
+
when :score
|
806
|
+
ranks_for_members = ranks_for_members.sort_by { |member| member[:score] }
|
807
|
+
end
|
808
|
+
|
838
809
|
ranks_for_members
|
839
810
|
end
|
840
811
|
|
@@ -861,11 +832,10 @@ class Leaderboard
|
|
861
832
|
# Key for retrieving optional member data.
|
862
833
|
#
|
863
834
|
# @param leaderboard_name [String] Name of the leaderboard.
|
864
|
-
#
|
865
|
-
#
|
866
|
-
|
867
|
-
|
868
|
-
"#{leaderboard_name}:member_data:#{member}"
|
835
|
+
#
|
836
|
+
# @return a key in the form of +leaderboard_name:member_data+
|
837
|
+
def member_data_key(leaderboard_name)
|
838
|
+
"#{leaderboard_name}:member_data"
|
869
839
|
end
|
870
840
|
|
871
841
|
# Validate and return the page size. Returns the +DEFAULT_PAGE_SIZE+ if the page size is less than 1.
|
data/spec/leaderboard_spec.rb
CHANGED
@@ -40,8 +40,10 @@ describe 'Leaderboard' do
|
|
40
40
|
rank_members_in_leaderboard
|
41
41
|
|
42
42
|
@redis_connection.exists('name').should be_true
|
43
|
+
@redis_connection.exists('name:member_data').should be_true
|
43
44
|
@leaderboard.delete_leaderboard
|
44
45
|
@redis_connection.exists('name').should be_false
|
46
|
+
@redis_connection.exists('name:member_data').should be_false
|
45
47
|
end
|
46
48
|
|
47
49
|
it 'should allow you to pass in an existing redis connection in the initializer' do
|
@@ -67,7 +69,6 @@ describe 'Leaderboard' do
|
|
67
69
|
rank_members_in_leaderboard(5)
|
68
70
|
|
69
71
|
@leaderboard.rank_for('member_4').should be(2)
|
70
|
-
@leaderboard.rank_for('member_4', true).should be(1)
|
71
72
|
end
|
72
73
|
|
73
74
|
it 'should return the correct score when calling score_for' do
|
@@ -160,70 +161,57 @@ describe 'Leaderboard' do
|
|
160
161
|
it 'should allow you to retrieve members in a given score range' do
|
161
162
|
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
|
162
163
|
|
163
|
-
members = @leaderboard.members_from_score_range(10, 15
|
164
|
+
members = @leaderboard.members_from_score_range(10, 15)
|
164
165
|
|
165
|
-
member_15 = {:member => 'member_15'}
|
166
|
+
member_15 = {:member => 'member_15', :score => 15.0, :rank => 11}
|
166
167
|
members[0].should eql(member_15)
|
167
168
|
|
168
|
-
member_10 = {:member => 'member_10'}
|
169
|
+
member_10 = {:member => 'member_10', :score => 10.0, :rank => 16}
|
169
170
|
members[5].should eql(member_10)
|
170
171
|
|
171
|
-
members = @leaderboard.members_from_score_range(10, 15, {:
|
172
|
+
members = @leaderboard.members_from_score_range(10, 15, {:with_member_data => true})
|
172
173
|
|
173
|
-
member_15 = {:member => 'member_15', :rank => 11, :score => 15.0, :member_data => {
|
174
|
-
members[0].should
|
174
|
+
member_15 = {:member => 'member_15', :rank => 11, :score => 15.0, :member_data => {:member_name => 'Leaderboard member 15'}.to_s}
|
175
|
+
members[0].should == member_15
|
175
176
|
|
176
|
-
member_10 = {:member => 'member_10', :rank => 16, :score => 10.0, :member_data => {
|
177
|
-
members[5].should
|
178
|
-
end
|
179
|
-
|
180
|
-
it 'should allow you to retrieve leaders without scores and ranks' do
|
181
|
-
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
|
182
|
-
|
183
|
-
@leaderboard.total_members.should be(Leaderboard::DEFAULT_PAGE_SIZE)
|
184
|
-
leaders = @leaderboard.leaders(1, {:with_scores => false, :with_rank => false})
|
185
|
-
|
186
|
-
member_25 = {:member => 'member_25'}
|
187
|
-
leaders[0].should eql(member_25)
|
188
|
-
|
189
|
-
member_1 = {:member => 'member_1'}
|
190
|
-
leaders[24].should eql(member_1)
|
177
|
+
member_10 = {:member => 'member_10', :rank => 16, :score => 10.0, :member_data => {:member_name => 'Leaderboard member 10'}.to_s}
|
178
|
+
members[5].should == member_10
|
191
179
|
end
|
192
180
|
|
193
181
|
it 'should allow you to retrieve leaders with extra data' do
|
194
182
|
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
|
195
183
|
|
196
184
|
@leaderboard.total_members.should be(Leaderboard::DEFAULT_PAGE_SIZE)
|
197
|
-
leaders = @leaderboard.leaders(1, {:
|
198
|
-
|
199
|
-
member_25 = {:member => 'member_25', :member_data => { "member_name" => "Leaderboard member 25" }}
|
200
|
-
leaders[0].should eql(member_25)
|
185
|
+
leaders = @leaderboard.leaders(1, {:with_member_data => true})
|
201
186
|
|
202
|
-
|
203
|
-
leaders[
|
187
|
+
member_25 = {:member => 'member_25', :score => 25.0, :rank => 1, :member_data => { :member_name => "Leaderboard member 25" }.to_s }
|
188
|
+
leaders[0].should == member_25
|
189
|
+
|
190
|
+
member_1 = {:member => 'member_1', :score => 1.0, :rank => 25, :member_data => { :member_name => "Leaderboard member 1" }.to_s }
|
191
|
+
leaders[24].should == member_1
|
204
192
|
end
|
205
193
|
|
206
194
|
it 'should allow you to retrieve optional member data' do
|
207
195
|
@leaderboard.rank_member('member_id', 1, {'username' => 'member_name', 'other_data_key' => 'other_data_value'})
|
208
196
|
|
209
|
-
@leaderboard.member_data_for('unknown_member').should
|
210
|
-
@leaderboard.member_data_for('member_id').should
|
197
|
+
@leaderboard.member_data_for('unknown_member').should be_nil
|
198
|
+
@leaderboard.member_data_for('member_id').should == {'username' => 'member_name', 'other_data_key' => 'other_data_value'}.to_s
|
211
199
|
end
|
212
200
|
|
213
201
|
it 'should allow you to update optional member data' do
|
214
202
|
@leaderboard.rank_member('member_id', 1, {'username' => 'member_name'})
|
215
203
|
|
216
|
-
@leaderboard.member_data_for('member_id').should
|
217
|
-
@leaderboard.update_member_data('member_id', {'other_data_key' => 'other_data_value'})
|
218
|
-
@leaderboard.member_data_for('member_id').should
|
204
|
+
@leaderboard.member_data_for('member_id').should == {'username' => 'member_name'}.to_s
|
205
|
+
@leaderboard.update_member_data('member_id', {'username' => 'member_name', 'other_data_key' => 'other_data_value'})
|
206
|
+
@leaderboard.member_data_for('member_id').should == {'username' => 'member_name', 'other_data_key' => 'other_data_value'}.to_s
|
219
207
|
end
|
220
208
|
|
221
209
|
it 'should allow you to remove optional member data' do
|
222
210
|
@leaderboard.rank_member('member_id', 1, {'username' => 'member_name'})
|
223
211
|
|
224
|
-
@leaderboard.member_data_for('member_id').should
|
212
|
+
@leaderboard.member_data_for('member_id').should == {'username' => 'member_name'}.to_s
|
225
213
|
@leaderboard.remove_member_data('member_id')
|
226
|
-
@leaderboard.member_data_for('member_id').should
|
214
|
+
@leaderboard.member_data_for('member_id').should be_nil
|
227
215
|
end
|
228
216
|
|
229
217
|
it 'should allow you to call leaders with various options that respect the defaults for the options not passed in' do
|
@@ -231,33 +219,7 @@ describe 'Leaderboard' do
|
|
231
219
|
|
232
220
|
leaders = @leaderboard.leaders(1, :page_size => 1)
|
233
221
|
leaders.size.should be(1)
|
234
|
-
|
235
|
-
leaders = @leaderboard.leaders(1, :with_rank => false)
|
236
|
-
leaders.size.should be(Leaderboard::DEFAULT_PAGE_SIZE)
|
237
|
-
member_26 = {:member => 'member_26', :score => 26.0}
|
238
|
-
member_25 = {:member => 'member_25', :score => 25.0}
|
239
|
-
member_24 = {:member => 'member_24', :score => 24.0}
|
240
|
-
leaders[0].should eql(member_26)
|
241
|
-
leaders[1].should eql(member_25)
|
242
|
-
leaders[2].should eql(member_24)
|
243
|
-
|
244
|
-
leaders = @leaderboard.leaders(1, :with_scores => false)
|
245
|
-
leaders.size.should be(Leaderboard::DEFAULT_PAGE_SIZE)
|
246
|
-
member_26 = {:member => 'member_26', :rank => 1}
|
247
|
-
member_25 = {:member => 'member_25', :rank => 2}
|
248
|
-
leaders[0].should eql(member_26)
|
249
|
-
leaders[1].should eql(member_25)
|
250
|
-
|
251
|
-
leaders = @leaderboard.leaders(1, :with_scores => false, :with_rank => false)
|
252
|
-
leaders.size.should be(Leaderboard::DEFAULT_PAGE_SIZE)
|
253
|
-
member_26 = {:member => 'member_26'}
|
254
|
-
member_25 = {:member => 'member_25'}
|
255
|
-
leaders[0].should eql(member_26)
|
256
|
-
leaders[1].should eql(member_25)
|
257
|
-
|
258
|
-
leaders = @leaderboard.leaders(1, :with_rank => false, :page_size => 1)
|
259
|
-
leaders.size.should be(1)
|
260
|
-
member_26 = {:member => 'member_26', :score => 26.0}
|
222
|
+
member_26 = {:member => 'member_26', :score => 26.0, :rank => 1}
|
261
223
|
leaders[0].should eql(member_26)
|
262
224
|
end
|
263
225
|
|
@@ -268,8 +230,7 @@ describe 'Leaderboard' do
|
|
268
230
|
@leaderboard.member_at(26)[:rank].should eql(26)
|
269
231
|
@leaderboard.member_at(50)[:rank].should eql(50)
|
270
232
|
@leaderboard.member_at(51).should be_nil
|
271
|
-
@leaderboard.member_at(1, :with_member_data => true)[:member_data].should
|
272
|
-
@leaderboard.member_at(1, :use_zero_index_for_rank => true)[:rank].should eql(0)
|
233
|
+
@leaderboard.member_at(1, :with_member_data => true)[:member_data].should == {:member_name => 'Leaderboard member 50'}.to_s
|
273
234
|
end
|
274
235
|
|
275
236
|
it 'should return the correct information when calling around_me' do
|
@@ -313,8 +274,7 @@ describe 'Leaderboard' do
|
|
313
274
|
@leaderboard.total_members.should be(Leaderboard::DEFAULT_PAGE_SIZE)
|
314
275
|
|
315
276
|
members = ['member_1', 'member_5', 'member_10']
|
316
|
-
ranked_members = @leaderboard.ranked_in_list(members, {:
|
317
|
-
|
277
|
+
ranked_members = @leaderboard.ranked_in_list(members, {:with_rank => true})
|
318
278
|
ranked_members.size.should be(3)
|
319
279
|
ranked_members[0][:rank].should be(25)
|
320
280
|
ranked_members[1][:rank].should be(21)
|
@@ -450,19 +410,15 @@ describe 'Leaderboard' do
|
|
450
410
|
foobar.disconnect
|
451
411
|
end
|
452
412
|
|
453
|
-
it 'should respect
|
413
|
+
it 'should respect options in the massage_leader_data method' do
|
454
414
|
rank_members_in_leaderboard(25)
|
455
415
|
|
456
416
|
@leaderboard.total_members.should be(25)
|
457
417
|
|
458
|
-
leaders = @leaderboard.leaders(1
|
418
|
+
leaders = @leaderboard.leaders(1)
|
459
419
|
leaders[0][:member].should_not be_nil
|
460
|
-
leaders[0][:score].
|
461
|
-
leaders[0][:rank].
|
462
|
-
|
463
|
-
@leaderboard.page_size = 25
|
464
|
-
leaders = @leaderboard.leaders(1, {:with_scores => false, :with_rank => false})
|
465
|
-
leaders.size.should be(25)
|
420
|
+
leaders[0][:score].should_not be_nil
|
421
|
+
leaders[0][:rank].should_not be_nil
|
466
422
|
|
467
423
|
@leaderboard.page_size = Leaderboard::DEFAULT_PAGE_SIZE
|
468
424
|
leaders = @leaderboard.leaders(1, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
|
@@ -638,4 +594,40 @@ describe 'Leaderboard' do
|
|
638
594
|
members[0][:score].to_i.should be(25)
|
639
595
|
members[24][:member].should eql('member_1')
|
640
596
|
end
|
597
|
+
|
598
|
+
it 'should sort by rank if the :sort_by option is set to :rank' do
|
599
|
+
rank_members_in_leaderboard(25)
|
600
|
+
|
601
|
+
members = ['member_5', 'member_1', 'member_10']
|
602
|
+
ranked_members = @leaderboard.ranked_in_list(members, :sort_by => :rank)
|
603
|
+
|
604
|
+
ranked_members.size.should be(3)
|
605
|
+
|
606
|
+
ranked_members[0][:rank].should be(16)
|
607
|
+
ranked_members[0][:score].should eql(10.0)
|
608
|
+
|
609
|
+
ranked_members[1][:rank].should be(21)
|
610
|
+
ranked_members[1][:score].should eql(5.0)
|
611
|
+
|
612
|
+
ranked_members[2][:rank].should be(25)
|
613
|
+
ranked_members[2][:score].should eql(1.0)
|
614
|
+
end
|
615
|
+
|
616
|
+
it 'should sort by score if the :sort_by option is set to :score' do
|
617
|
+
rank_members_in_leaderboard(25)
|
618
|
+
|
619
|
+
members = ['member_5', 'member_1', 'member_10']
|
620
|
+
ranked_members = @leaderboard.ranked_in_list(members, :sort_by => :score)
|
621
|
+
|
622
|
+
ranked_members.size.should be(3)
|
623
|
+
|
624
|
+
ranked_members[0][:rank].should be(25)
|
625
|
+
ranked_members[0][:score].should eql(1.0)
|
626
|
+
|
627
|
+
ranked_members[1][:rank].should be(21)
|
628
|
+
ranked_members[1][:score].should eql(5.0)
|
629
|
+
|
630
|
+
ranked_members[2][:rank].should be(16)
|
631
|
+
ranked_members[2][:score].should eql(10.0)
|
632
|
+
end
|
641
633
|
end
|
@@ -16,7 +16,6 @@ describe 'Leaderboard (reverse option)' do
|
|
16
16
|
rank_members_in_leaderboard(5)
|
17
17
|
|
18
18
|
@leaderboard.rank_for('member_4').should be(4)
|
19
|
-
@leaderboard.rank_for('member_4', true).should be(3)
|
20
19
|
end
|
21
20
|
|
22
21
|
it 'should return the correct list when calling leaders' do
|
@@ -52,32 +51,19 @@ describe 'Leaderboard (reverse option)' do
|
|
52
51
|
|
53
52
|
members = @leaderboard.members_from_score_range(10, 15, {:with_scores => false, :with_rank => false})
|
54
53
|
|
55
|
-
member_10 = {:member => 'member_10'}
|
54
|
+
member_10 = {:member => 'member_10', :score => 10.0, :rank => 10}
|
56
55
|
members[0].should eql(member_10)
|
57
56
|
|
58
|
-
member_15 = {:member => 'member_15'}
|
57
|
+
member_15 = {:member => 'member_15', :score => 15.0, :rank => 15}
|
59
58
|
members[5].should eql(member_15)
|
60
59
|
|
61
|
-
members = @leaderboard.members_from_score_range(10, 15, {:
|
60
|
+
members = @leaderboard.members_from_score_range(10, 15, {:with_member_data => true})
|
62
61
|
|
63
|
-
member_10 = {:member => 'member_10', :rank => 10, :score => 10.0, :member_data => {
|
64
|
-
members[0].should
|
65
|
-
|
66
|
-
member_15 = {:member => 'member_15', :rank => 15, :score => 15.0, :member_data => {'member_name' => 'Leaderboard member 15'}}
|
67
|
-
members[5].should eql(member_15)
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'should allow you to retrieve leaders without scores and ranks' do
|
71
|
-
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
|
72
|
-
|
73
|
-
@leaderboard.total_members.should be(Leaderboard::DEFAULT_PAGE_SIZE)
|
74
|
-
leaders = @leaderboard.leaders(1, {:with_scores => false, :with_rank => false})
|
62
|
+
member_10 = {:member => 'member_10', :rank => 10, :score => 10.0, :member_data => {:member_name => 'Leaderboard member 10'}.to_s}
|
63
|
+
members[0].should == member_10
|
75
64
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
member_25 = {:member => 'member_25'}
|
80
|
-
leaders[24].should eql(member_25)
|
65
|
+
member_15 = {:member => 'member_15', :rank => 15, :score => 15.0, :member_data => {:member_name => 'Leaderboard member 15'}.to_s}
|
66
|
+
members[5].should == member_15
|
81
67
|
end
|
82
68
|
|
83
69
|
it 'should allow you to call leaders with various options that respect the defaults for the options not passed in' do
|
@@ -86,33 +72,14 @@ describe 'Leaderboard (reverse option)' do
|
|
86
72
|
leaders = @leaderboard.leaders(1, :page_size => 1)
|
87
73
|
leaders.size.should be(1)
|
88
74
|
|
89
|
-
leaders = @leaderboard.leaders(1
|
75
|
+
leaders = @leaderboard.leaders(1)
|
90
76
|
leaders.size.should be(Leaderboard::DEFAULT_PAGE_SIZE)
|
91
|
-
member_1 = {:member => 'member_1', :score => 1.0}
|
92
|
-
member_2 = {:member => 'member_2', :score => 2.0}
|
93
|
-
member_3 = {:member => 'member_3', :score => 3.0}
|
77
|
+
member_1 = {:member => 'member_1', :score => 1.0, :rank => 1}
|
78
|
+
member_2 = {:member => 'member_2', :score => 2.0, :rank => 2}
|
79
|
+
member_3 = {:member => 'member_3', :score => 3.0, :rank => 3}
|
94
80
|
leaders[0].should eql(member_1)
|
95
81
|
leaders[1].should eql(member_2)
|
96
82
|
leaders[2].should eql(member_3)
|
97
|
-
|
98
|
-
leaders = @leaderboard.leaders(1, :with_scores => false)
|
99
|
-
leaders.size.should be(Leaderboard::DEFAULT_PAGE_SIZE)
|
100
|
-
member_1 = {:member => 'member_1', :rank => 1}
|
101
|
-
member_2 = {:member => 'member_2', :rank => 2}
|
102
|
-
leaders[0].should eql(member_1)
|
103
|
-
leaders[1].should eql(member_2)
|
104
|
-
|
105
|
-
leaders = @leaderboard.leaders(1, :with_scores => false, :with_rank => false)
|
106
|
-
leaders.size.should be(Leaderboard::DEFAULT_PAGE_SIZE)
|
107
|
-
member_1 = {:member => 'member_1'}
|
108
|
-
member_2 = {:member => 'member_2'}
|
109
|
-
leaders[0].should eql(member_1)
|
110
|
-
leaders[1].should eql(member_2)
|
111
|
-
|
112
|
-
leaders = @leaderboard.leaders(1, :with_rank => false, :page_size => 1)
|
113
|
-
leaders.size.should be(1)
|
114
|
-
member_1 = {:member => 'member_1', :score => 1.0}
|
115
|
-
leaders[0].should eql(member_1)
|
116
83
|
end
|
117
84
|
|
118
85
|
it 'should return a single member when calling member_at' do
|
@@ -122,8 +89,7 @@ describe 'Leaderboard (reverse option)' do
|
|
122
89
|
@leaderboard.member_at(26)[:rank].should eql(26)
|
123
90
|
@leaderboard.member_at(50)[:rank].should eql(50)
|
124
91
|
@leaderboard.member_at(51).should be_nil
|
125
|
-
@leaderboard.member_at(1, :with_member_data => true)[:member_data].should
|
126
|
-
@leaderboard.member_at(1, :use_zero_index_for_rank => true)[:rank].should eql(0)
|
92
|
+
@leaderboard.member_at(1, :with_member_data => true)[:member_data].should == {:member_name => 'Leaderboard member 1'}.to_s
|
127
93
|
end
|
128
94
|
|
129
95
|
it 'should return the correct information when calling around_me' do
|
@@ -167,8 +133,7 @@ describe 'Leaderboard (reverse option)' do
|
|
167
133
|
@leaderboard.total_members.should be(Leaderboard::DEFAULT_PAGE_SIZE)
|
168
134
|
|
169
135
|
members = ['member_1', 'member_5', 'member_10']
|
170
|
-
ranked_members = @leaderboard.ranked_in_list(members, {:with_scores => false, :with_rank => true
|
171
|
-
|
136
|
+
ranked_members = @leaderboard.ranked_in_list(members, {:with_scores => false, :with_rank => true})
|
172
137
|
ranked_members.size.should be(3)
|
173
138
|
|
174
139
|
ranked_members[0][:rank].should be(1)
|
@@ -261,29 +226,22 @@ describe 'Leaderboard (reverse option)' do
|
|
261
226
|
foobar.disconnect
|
262
227
|
end
|
263
228
|
|
264
|
-
it 'should respect
|
229
|
+
it 'should respect options in the massage_leader_data method' do
|
265
230
|
rank_members_in_leaderboard(25)
|
266
231
|
|
267
232
|
@leaderboard.total_members.should be(25)
|
268
233
|
|
269
|
-
leaders = @leaderboard.leaders(1
|
234
|
+
leaders = @leaderboard.leaders(1)
|
270
235
|
leaders[0][:member].should_not be_nil
|
271
|
-
leaders[0][:score].
|
272
|
-
leaders[0][:rank].
|
273
|
-
|
274
|
-
@leaderboard.page_size = 25
|
275
|
-
leaders = @leaderboard.leaders(1, {:with_scores => false, :with_rank => false})
|
276
|
-
leaders.size.should be(25)
|
236
|
+
leaders[0][:score].should_not be_nil
|
237
|
+
leaders[0][:rank].should_not be_nil
|
277
238
|
|
278
239
|
@leaderboard.page_size = Leaderboard::DEFAULT_PAGE_SIZE
|
279
240
|
leaders = @leaderboard.leaders(1, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
|
241
|
+
leaders.size.should be(25)
|
280
242
|
leaders[0][:member].should_not be_nil
|
281
243
|
leaders[0][:score].should_not be_nil
|
282
244
|
leaders[0][:rank].should_not be_nil
|
283
|
-
|
284
|
-
@leaderboard.page_size = 25
|
285
|
-
leaders = @leaderboard.leaders(1, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
|
286
|
-
leaders.size.should be(25)
|
287
245
|
end
|
288
246
|
|
289
247
|
it 'should return the correct number of members when calling around_me with a page_size options' do
|
@@ -354,4 +312,40 @@ describe 'Leaderboard (reverse option)' do
|
|
354
312
|
members[0][:score].to_i.should be(1)
|
355
313
|
members[24][:member].should eql('member_25')
|
356
314
|
end
|
315
|
+
|
316
|
+
it 'should sort by rank if the :sort_by option is set to :rank' do
|
317
|
+
rank_members_in_leaderboard(25)
|
318
|
+
|
319
|
+
members = ['member_5', 'member_1', 'member_10']
|
320
|
+
ranked_members = @leaderboard.ranked_in_list(members, :sort_by => :rank)
|
321
|
+
|
322
|
+
ranked_members.size.should be(3)
|
323
|
+
|
324
|
+
ranked_members[0][:rank].should be(1)
|
325
|
+
ranked_members[0][:score].should eql(1.0)
|
326
|
+
|
327
|
+
ranked_members[1][:rank].should be(5)
|
328
|
+
ranked_members[1][:score].should eql(5.0)
|
329
|
+
|
330
|
+
ranked_members[2][:rank].should be(10)
|
331
|
+
ranked_members[2][:score].should eql(10.0)
|
332
|
+
end
|
333
|
+
|
334
|
+
it 'should sort by score if the :sort_by option is set to :score' do
|
335
|
+
rank_members_in_leaderboard(25)
|
336
|
+
|
337
|
+
members = ['member_5', 'member_1', 'member_10']
|
338
|
+
ranked_members = @leaderboard.ranked_in_list(members, :sort_by => :score)
|
339
|
+
|
340
|
+
ranked_members.size.should be(3)
|
341
|
+
|
342
|
+
ranked_members[0][:rank].should be(1)
|
343
|
+
ranked_members[0][:score].should eql(1.0)
|
344
|
+
|
345
|
+
ranked_members[1][:rank].should be(5)
|
346
|
+
ranked_members[1][:score].should eql(5.0)
|
347
|
+
|
348
|
+
ranked_members[2][:rank].should be(10)
|
349
|
+
ranked_members[2][:score].should eql(10.0)
|
350
|
+
end
|
357
351
|
end
|
data/spec/version_spec.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: leaderboard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
4
|
+
version: 3.0.0.rc1
|
5
|
+
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- David Czarnecki
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-11-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
@@ -95,16 +95,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
95
95
|
version: '0'
|
96
96
|
segments:
|
97
97
|
- 0
|
98
|
-
hash:
|
98
|
+
hash: -395088559469707987
|
99
99
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
100
|
none: false
|
101
101
|
requirements:
|
102
|
-
- - ! '
|
102
|
+
- - ! '>'
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
version:
|
105
|
-
segments:
|
106
|
-
- 0
|
107
|
-
hash: 1313694139295611168
|
104
|
+
version: 1.3.1
|
108
105
|
requirements: []
|
109
106
|
rubyforge_project: leaderboard
|
110
107
|
rubygems_version: 1.8.24
|