leaderboard 2.5.0 → 3.0.0.rc1
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/.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
|