leaderboard 2.0.2 → 2.0.3
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/.gitignore +2 -0
- data/CHANGELOG.markdown +4 -0
- data/LICENSE.txt +1 -1
- data/README.markdown +16 -3
- data/Rakefile +1 -0
- data/lib/leaderboard.rb +46 -13
- data/lib/leaderboard/version.rb +1 -1
- data/test/test_leaderboard.rb +3 -3
- data/test/test_rev_leaderboard.rb +466 -0
- metadata +10 -8
data/.gitignore
CHANGED
data/CHANGELOG.markdown
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## leaderboard 2.0.3 (2012-02-22)
|
4
|
+
|
5
|
+
* Added `:reverse => false` to `Leaderboard::DEFAULT_OPTIONS` to support leaderboards sorted from lowest to highest score instead of highest to lowest score. (Thanks @siuying)
|
6
|
+
|
3
7
|
## leaderboard 2.0.2 (2012-02-03)
|
4
8
|
|
5
9
|
* Fix for checking to see if a member actually exists in the leaderboard for the `around_me` calls
|
data/LICENSE.txt
CHANGED
data/README.markdown
CHANGED
@@ -6,10 +6,12 @@ Builds off ideas proposed in http://blog.agoragames.com/2011/01/01/creating-high
|
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
9
|
-
|
9
|
+
`gem install leaderboard`
|
10
|
+
|
11
|
+
or in your `Gemfile`
|
10
12
|
|
11
13
|
```ruby
|
12
|
-
gem
|
14
|
+
gem 'leaderboard'
|
13
15
|
```
|
14
16
|
|
15
17
|
Make sure your redis server is running! Redis configuration is outside the scope of this README, but
|
@@ -37,6 +39,17 @@ If you need to pass in options for Redis, you can do this in the initializer:
|
|
37
39
|
=> #<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)>>
|
38
40
|
```
|
39
41
|
|
42
|
+
The `Leaderboard::DEFAULT_OPTIONS` are as follows:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
DEFAULT_OPTIONS = {
|
46
|
+
:page_size => DEFAULT_PAGE_SIZE,
|
47
|
+
:reverse => false
|
48
|
+
}
|
49
|
+
```
|
50
|
+
|
51
|
+
You would use the option, `:reverse => true`, if you wanted a leaderboard sorted from lowest to highest score.
|
52
|
+
|
40
53
|
You can pass in an existing connection to Redis using :redis_connection in the Redis options hash:
|
41
54
|
|
42
55
|
```ruby
|
@@ -240,5 +253,5 @@ The following ports have been made of the leaderboard gem.
|
|
240
253
|
|
241
254
|
## Copyright
|
242
255
|
|
243
|
-
Copyright (c) 2011 David Czarnecki. See LICENSE.txt for further details.
|
256
|
+
Copyright (c) 2011-2012 David Czarnecki. See LICENSE.txt for further details.
|
244
257
|
|
data/Rakefile
CHANGED
data/lib/leaderboard.rb
CHANGED
@@ -5,7 +5,8 @@ class Leaderboard
|
|
5
5
|
DEFAULT_PAGE_SIZE = 25
|
6
6
|
|
7
7
|
DEFAULT_OPTIONS = {
|
8
|
-
:page_size => DEFAULT_PAGE_SIZE
|
8
|
+
:page_size => DEFAULT_PAGE_SIZE,
|
9
|
+
:reverse => false
|
9
10
|
}
|
10
11
|
|
11
12
|
DEFAULT_REDIS_HOST = 'localhost'
|
@@ -43,8 +44,9 @@ class Leaderboard
|
|
43
44
|
def initialize(leaderboard_name, options = DEFAULT_OPTIONS, redis_options = DEFAULT_REDIS_OPTIONS)
|
44
45
|
@leaderboard_name = leaderboard_name
|
45
46
|
|
47
|
+
@reverse = options[:reverse]
|
46
48
|
@page_size = options[:page_size]
|
47
|
-
if @page_size < 1
|
49
|
+
if @page_size.nil? || @page_size < 1
|
48
50
|
@page_size = DEFAULT_PAGE_SIZE
|
49
51
|
end
|
50
52
|
|
@@ -206,10 +208,18 @@ class Leaderboard
|
|
206
208
|
#
|
207
209
|
# @return the rank for a member in the leaderboard.
|
208
210
|
def rank_for_in(leaderboard_name, member, use_zero_index_for_rank = false)
|
209
|
-
if
|
210
|
-
|
211
|
+
if @reverse
|
212
|
+
if use_zero_index_for_rank
|
213
|
+
return @redis_connection.zrank(leaderboard_name, member)
|
214
|
+
else
|
215
|
+
return @redis_connection.zrank(leaderboard_name, member) + 1 rescue nil
|
216
|
+
end
|
211
217
|
else
|
212
|
-
|
218
|
+
if use_zero_index_for_rank
|
219
|
+
return @redis_connection.zrevrank(leaderboard_name, member)
|
220
|
+
else
|
221
|
+
return @redis_connection.zrevrank(leaderboard_name, member) + 1 rescue nil
|
222
|
+
end
|
213
223
|
end
|
214
224
|
end
|
215
225
|
|
@@ -271,7 +281,11 @@ class Leaderboard
|
|
271
281
|
def score_and_rank_for_in(leaderboard_name, member, use_zero_index_for_rank = false)
|
272
282
|
responses = @redis_connection.multi do |transaction|
|
273
283
|
transaction.zscore(leaderboard_name, member)
|
274
|
-
|
284
|
+
if @reverse
|
285
|
+
transaction.zrank(leaderboard_name, member)
|
286
|
+
else
|
287
|
+
transaction.zrevrank(leaderboard_name, member)
|
288
|
+
end
|
275
289
|
end
|
276
290
|
|
277
291
|
responses[0] = responses[0].to_f
|
@@ -321,8 +335,13 @@ class Leaderboard
|
|
321
335
|
transaction.zcard(leaderboard_name)
|
322
336
|
transaction.zrevrank(leaderboard_name, member)
|
323
337
|
end
|
324
|
-
|
325
|
-
((responses[0] - responses[1] - 1).to_f / responses[0].to_f * 100).ceil
|
338
|
+
|
339
|
+
percentile = ((responses[0] - responses[1] - 1).to_f / responses[0].to_f * 100).ceil
|
340
|
+
if @reverse
|
341
|
+
100 - percentile
|
342
|
+
else
|
343
|
+
percentile
|
344
|
+
end
|
326
345
|
end
|
327
346
|
|
328
347
|
# Retrieve a page of leaders from the leaderboard.
|
@@ -364,8 +383,13 @@ class Leaderboard
|
|
364
383
|
end
|
365
384
|
|
366
385
|
ending_offset = (starting_offset + page_size) - 1
|
367
|
-
|
368
|
-
|
386
|
+
|
387
|
+
if @reverse
|
388
|
+
raw_leader_data = @redis_connection.zrange(leaderboard_name, starting_offset, ending_offset, :with_scores => false)
|
389
|
+
else
|
390
|
+
raw_leader_data = @redis_connection.zrevrange(leaderboard_name, starting_offset, ending_offset, :with_scores => false)
|
391
|
+
end
|
392
|
+
|
369
393
|
if raw_leader_data
|
370
394
|
return ranked_in_list_in(leaderboard_name, raw_leader_data, leaderboard_options)
|
371
395
|
else
|
@@ -394,7 +418,9 @@ class Leaderboard
|
|
394
418
|
leaderboard_options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS.dup
|
395
419
|
leaderboard_options.merge!(options)
|
396
420
|
|
397
|
-
reverse_rank_for_member = @
|
421
|
+
reverse_rank_for_member = @reverse ?
|
422
|
+
@redis_connection.zrank(leaderboard_name, member) :
|
423
|
+
@redis_connection.zrevrank(leaderboard_name, member)
|
398
424
|
|
399
425
|
return [] unless reverse_rank_for_member
|
400
426
|
|
@@ -407,7 +433,10 @@ class Leaderboard
|
|
407
433
|
|
408
434
|
ending_offset = (starting_offset + page_size) - 1
|
409
435
|
|
410
|
-
raw_leader_data = @
|
436
|
+
raw_leader_data = @reverse ?
|
437
|
+
@redis_connection.zrange(leaderboard_name, starting_offset, ending_offset, :with_scores => false) :
|
438
|
+
@redis_connection.zrevrange(leaderboard_name, starting_offset, ending_offset, :with_scores => false)
|
439
|
+
|
411
440
|
if raw_leader_data
|
412
441
|
return ranked_in_list_in(leaderboard_name, raw_leader_data, leaderboard_options)
|
413
442
|
else
|
@@ -440,7 +469,11 @@ class Leaderboard
|
|
440
469
|
|
441
470
|
responses = @redis_connection.multi do |transaction|
|
442
471
|
members.each do |member|
|
443
|
-
|
472
|
+
if @reverse
|
473
|
+
transaction.zrank(leaderboard_name, member) if leaderboard_options[:with_rank]
|
474
|
+
else
|
475
|
+
transaction.zrevrank(leaderboard_name, member) if leaderboard_options[:with_rank]
|
476
|
+
end
|
444
477
|
transaction.zscore(leaderboard_name, member) if leaderboard_options[:with_scores]
|
445
478
|
end
|
446
479
|
end
|
data/lib/leaderboard/version.rb
CHANGED
data/test/test_leaderboard.rb
CHANGED
@@ -2,8 +2,8 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class TestLeaderboard < Test::Unit::TestCase
|
4
4
|
def setup
|
5
|
-
@
|
6
|
-
@
|
5
|
+
@redis_connection = Redis.new(:host => "127.0.0.1")
|
6
|
+
@leaderboard = Leaderboard.new('name', Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS, :host => "127.0.0.1")
|
7
7
|
end
|
8
8
|
|
9
9
|
def teardown
|
@@ -13,7 +13,7 @@ class TestLeaderboard < Test::Unit::TestCase
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def test_version
|
16
|
-
assert_equal '2.0.
|
16
|
+
assert_equal '2.0.3', Leaderboard::VERSION
|
17
17
|
end
|
18
18
|
|
19
19
|
def test_initialize_with_defaults
|
@@ -0,0 +1,466 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestRevLeaderboard < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@redis_connection = Redis.new(:host => "127.0.0.1")
|
6
|
+
@leaderboard = Leaderboard.new('name', Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS.merge({:reverse => true}), :host => "127.0.0.1")
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
@redis_connection.flushdb
|
11
|
+
@leaderboard.disconnect
|
12
|
+
@redis_connection.client.disconnect
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_version
|
16
|
+
assert_equal '2.0.3', Leaderboard::VERSION
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_initialize_with_defaults
|
20
|
+
assert_equal 'name', @leaderboard.leaderboard_name
|
21
|
+
assert_equal Leaderboard::DEFAULT_PAGE_SIZE, @leaderboard.page_size
|
22
|
+
end
|
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
|
+
|
36
|
+
def test_page_size_is_default_page_size_if_set_to_invalid_value
|
37
|
+
some_leaderboard = Leaderboard.new('name', {:page_size => 0})
|
38
|
+
|
39
|
+
assert_equal Leaderboard::DEFAULT_PAGE_SIZE, some_leaderboard.page_size
|
40
|
+
some_leaderboard.disconnect
|
41
|
+
end
|
42
|
+
|
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)
|
60
|
+
|
61
|
+
assert_equal 1, @leaderboard.total_members
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_total_members_in_score_range
|
65
|
+
rank_members_in_leaderboard(5)
|
66
|
+
|
67
|
+
assert_equal 3, @leaderboard.total_members_in_score_range(2, 4)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_rank_for
|
71
|
+
rank_members_in_leaderboard(5)
|
72
|
+
|
73
|
+
assert_equal 4, @leaderboard.rank_for('member_4')
|
74
|
+
assert_equal 3, @leaderboard.rank_for('member_4', true)
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_score_for
|
78
|
+
rank_members_in_leaderboard(5)
|
79
|
+
|
80
|
+
assert_equal 4, @leaderboard.score_for('member_4')
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_total_pages
|
84
|
+
rank_members_in_leaderboard(10)
|
85
|
+
|
86
|
+
assert_equal 1, @leaderboard.total_pages
|
87
|
+
|
88
|
+
@redis_connection.flushdb
|
89
|
+
|
90
|
+
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE + 1)
|
91
|
+
|
92
|
+
assert_equal 2, @leaderboard.total_pages
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_leaders
|
96
|
+
rank_members_in_leaderboard(25)
|
97
|
+
|
98
|
+
assert_equal 25, @leaderboard.total_members
|
99
|
+
|
100
|
+
leaders = @leaderboard.leaders(1)
|
101
|
+
|
102
|
+
assert_equal 25, leaders.size
|
103
|
+
assert_equal 'member_1', leaders[0][:member]
|
104
|
+
assert_equal 'member_24', leaders[-2][:member]
|
105
|
+
assert_equal 'member_25', leaders[-1][:member]
|
106
|
+
assert_equal 25, leaders[-1][:score].to_i
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_leaders_with_multiple_pages
|
110
|
+
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)
|
111
|
+
|
112
|
+
assert_equal Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1, @leaderboard.total_members
|
113
|
+
|
114
|
+
leaders = @leaderboard.leaders(1)
|
115
|
+
assert_equal @leaderboard.page_size, leaders.size
|
116
|
+
|
117
|
+
leaders = @leaderboard.leaders(2)
|
118
|
+
assert_equal @leaderboard.page_size, leaders.size
|
119
|
+
|
120
|
+
leaders = @leaderboard.leaders(3)
|
121
|
+
assert_equal @leaderboard.page_size, leaders.size
|
122
|
+
|
123
|
+
leaders = @leaderboard.leaders(4)
|
124
|
+
assert_equal 1, leaders.size
|
125
|
+
|
126
|
+
leaders = @leaderboard.leaders(-5)
|
127
|
+
assert_equal @leaderboard.page_size, leaders.size
|
128
|
+
|
129
|
+
leaders = @leaderboard.leaders(10)
|
130
|
+
assert_equal 1, leaders.size
|
131
|
+
end
|
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_rank => false})
|
138
|
+
|
139
|
+
member_1 = {:member => 'member_1'}
|
140
|
+
assert_equal member_1, leaders[0]
|
141
|
+
|
142
|
+
member_25 = {:member => 'member_25'}
|
143
|
+
assert_equal member_25, leaders[24]
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_leaders_with_only_various_options_should_respect_other_defaults
|
147
|
+
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE + 1)
|
148
|
+
|
149
|
+
leaders = @leaderboard.leaders(1, :page_size => 1)
|
150
|
+
assert_equal 1, leaders.size
|
151
|
+
|
152
|
+
leaders = @leaderboard.leaders(1, :with_rank => false)
|
153
|
+
assert_equal Leaderboard::DEFAULT_PAGE_SIZE, leaders.size
|
154
|
+
member_1 = {:member => 'member_1', :score => 1}
|
155
|
+
member_2 = {:member => 'member_2', :score => 2}
|
156
|
+
member_3 = {:member => 'member_3', :score => 3}
|
157
|
+
assert_equal member_1, leaders[0]
|
158
|
+
assert_equal member_2, leaders[1]
|
159
|
+
assert_equal member_3, leaders[2]
|
160
|
+
|
161
|
+
leaders = @leaderboard.leaders(1, :with_scores => false)
|
162
|
+
assert_equal Leaderboard::DEFAULT_PAGE_SIZE, leaders.size
|
163
|
+
member_1 = {:member => 'member_1', :rank => 1}
|
164
|
+
member_2 = {:member => 'member_2', :rank => 2}
|
165
|
+
assert_equal member_1, leaders[0]
|
166
|
+
assert_equal member_2, leaders[1]
|
167
|
+
|
168
|
+
leaders = @leaderboard.leaders(1, :with_scores => false, :with_rank => false)
|
169
|
+
assert_equal Leaderboard::DEFAULT_PAGE_SIZE, leaders.size
|
170
|
+
member_1 = {:member => 'member_1'}
|
171
|
+
member_2 = {:member => 'member_2'}
|
172
|
+
assert_equal member_1, leaders[0]
|
173
|
+
assert_equal member_2, leaders[1]
|
174
|
+
|
175
|
+
leaders = @leaderboard.leaders(1, :with_rank => false, :page_size => 1)
|
176
|
+
assert_equal 1, leaders.size
|
177
|
+
member_1 = {:member => 'member_1', :score => 1}
|
178
|
+
assert_equal member_1, leaders[0]
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_around_me
|
182
|
+
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)
|
183
|
+
|
184
|
+
assert_equal Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1, @leaderboard.total_members
|
185
|
+
|
186
|
+
leaders_around_me = @leaderboard.around_me('member_30')
|
187
|
+
assert_equal @leaderboard.page_size / 2, leaders_around_me.size / 2
|
188
|
+
|
189
|
+
leaders_around_me = @leaderboard.around_me('member_76')
|
190
|
+
assert_equal @leaderboard.page_size / 2 + 1, leaders_around_me.size
|
191
|
+
|
192
|
+
leaders_around_me = @leaderboard.around_me('member_1')
|
193
|
+
assert_equal @leaderboard.page_size / 2, leaders_around_me.size / 2
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_ranked_in_list
|
197
|
+
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
|
198
|
+
|
199
|
+
assert_equal Leaderboard::DEFAULT_PAGE_SIZE, @leaderboard.total_members
|
200
|
+
|
201
|
+
members = ['member_1', 'member_5', 'member_10']
|
202
|
+
ranked_members = @leaderboard.ranked_in_list(members, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
|
203
|
+
|
204
|
+
assert_equal 3, ranked_members.size
|
205
|
+
|
206
|
+
assert_equal 1, ranked_members[0][:rank]
|
207
|
+
assert_equal 1, ranked_members[0][:score]
|
208
|
+
|
209
|
+
assert_equal 5, ranked_members[1][:rank]
|
210
|
+
assert_equal 5, ranked_members[1][:score]
|
211
|
+
|
212
|
+
assert_equal 10, ranked_members[2][:rank]
|
213
|
+
assert_equal 10, ranked_members[2][:score]
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_ranked_in_list_without_scores
|
217
|
+
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
|
218
|
+
|
219
|
+
assert_equal Leaderboard::DEFAULT_PAGE_SIZE, @leaderboard.total_members
|
220
|
+
|
221
|
+
members = ['member_1', 'member_5', 'member_10']
|
222
|
+
ranked_members = @leaderboard.ranked_in_list(members, {:with_scores => false, :with_rank => true, :use_zero_index_for_rank => false})
|
223
|
+
|
224
|
+
assert_equal 3, ranked_members.size
|
225
|
+
|
226
|
+
assert_equal 1, ranked_members[0][:rank]
|
227
|
+
|
228
|
+
assert_equal 5, ranked_members[1][:rank]
|
229
|
+
|
230
|
+
assert_equal 10, ranked_members[2][:rank]
|
231
|
+
end
|
232
|
+
|
233
|
+
def test_remove_member
|
234
|
+
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
|
235
|
+
|
236
|
+
assert_equal Leaderboard::DEFAULT_PAGE_SIZE, @leaderboard.total_members
|
237
|
+
|
238
|
+
@leaderboard.remove_member('member_1')
|
239
|
+
|
240
|
+
assert_equal Leaderboard::DEFAULT_PAGE_SIZE - 1, @leaderboard.total_members
|
241
|
+
assert_nil @leaderboard.rank_for('member_1')
|
242
|
+
end
|
243
|
+
|
244
|
+
def test_change_score_for
|
245
|
+
@leaderboard.rank_member('member_1', 5)
|
246
|
+
assert_equal 5, @leaderboard.score_for('member_1')
|
247
|
+
|
248
|
+
@leaderboard.change_score_for('member_1', 5)
|
249
|
+
assert_equal 10, @leaderboard.score_for('member_1')
|
250
|
+
|
251
|
+
@leaderboard.change_score_for('member_1', -5)
|
252
|
+
assert_equal 5, @leaderboard.score_for('member_1')
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_check_member
|
256
|
+
@leaderboard.rank_member('member_1', 10)
|
257
|
+
|
258
|
+
assert_equal true, @leaderboard.check_member?('member_1')
|
259
|
+
assert_equal false, @leaderboard.check_member?('member_2')
|
260
|
+
end
|
261
|
+
|
262
|
+
def test_can_change_page_size_and_have_it_reflected_in_size_of_result_set
|
263
|
+
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
|
264
|
+
|
265
|
+
@leaderboard.page_size = 5
|
266
|
+
|
267
|
+
assert_equal 5, @leaderboard.total_pages
|
268
|
+
assert_equal 5, @leaderboard.leaders(1).size
|
269
|
+
end
|
270
|
+
|
271
|
+
def test_cannot_set_page_size_to_invalid_page_size
|
272
|
+
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
|
273
|
+
|
274
|
+
@leaderboard.page_size = 0
|
275
|
+
assert_equal 1, @leaderboard.total_pages
|
276
|
+
assert_equal Leaderboard::DEFAULT_PAGE_SIZE, @leaderboard.leaders(1).size
|
277
|
+
end
|
278
|
+
|
279
|
+
def test_score_and_rank_for
|
280
|
+
rank_members_in_leaderboard
|
281
|
+
|
282
|
+
data = @leaderboard.score_and_rank_for('member_1')
|
283
|
+
assert_equal 'member_1', data[:member]
|
284
|
+
assert_equal 1, data[:score]
|
285
|
+
assert_equal 1, data[:rank]
|
286
|
+
end
|
287
|
+
|
288
|
+
def test_remove_members_in_score_range
|
289
|
+
rank_members_in_leaderboard
|
290
|
+
|
291
|
+
assert_equal 5, @leaderboard.total_members
|
292
|
+
|
293
|
+
@leaderboard.rank_member('cheater_1', 100)
|
294
|
+
@leaderboard.rank_member('cheater_2', 101)
|
295
|
+
@leaderboard.rank_member('cheater_3', 102)
|
296
|
+
|
297
|
+
assert_equal 8, @leaderboard.total_members
|
298
|
+
|
299
|
+
@leaderboard.remove_members_in_score_range(100, 102)
|
300
|
+
|
301
|
+
assert_equal 5, @leaderboard.total_members
|
302
|
+
|
303
|
+
leaders = @leaderboard.leaders(1)
|
304
|
+
leaders.each do |leader|
|
305
|
+
assert leader[:score] < 100
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def test_merge_leaderboards
|
310
|
+
foo = Leaderboard.new('foo')
|
311
|
+
bar = Leaderboard.new('bar')
|
312
|
+
|
313
|
+
foo.rank_member('foo_1', 1)
|
314
|
+
foo.rank_member('foo_2', 2)
|
315
|
+
bar.rank_member('bar_1', 3)
|
316
|
+
bar.rank_member('bar_2', 4)
|
317
|
+
bar.rank_member('bar_3', 5)
|
318
|
+
|
319
|
+
foobar_keys = foo.merge_leaderboards('foobar', ['bar'])
|
320
|
+
assert_equal 5, foobar_keys
|
321
|
+
|
322
|
+
foobar = Leaderboard.new('foobar')
|
323
|
+
assert_equal 5, foobar.total_members
|
324
|
+
|
325
|
+
first_leader_in_foobar = foobar.leaders(1).first
|
326
|
+
assert_equal 1, first_leader_in_foobar[:rank]
|
327
|
+
assert_equal 'bar_3', first_leader_in_foobar[:member]
|
328
|
+
assert_equal 5, first_leader_in_foobar[:score]
|
329
|
+
|
330
|
+
foo.disconnect
|
331
|
+
bar.disconnect
|
332
|
+
foobar.disconnect
|
333
|
+
end
|
334
|
+
|
335
|
+
def test_intersect_leaderboards
|
336
|
+
foo = Leaderboard.new('foo')
|
337
|
+
bar = Leaderboard.new('bar')
|
338
|
+
|
339
|
+
foo.rank_member('foo_1', 1)
|
340
|
+
foo.rank_member('foo_2', 2)
|
341
|
+
foo.rank_member('bar_3', 6)
|
342
|
+
bar.rank_member('bar_1', 3)
|
343
|
+
bar.rank_member('foo_1', 4)
|
344
|
+
bar.rank_member('bar_3', 5)
|
345
|
+
|
346
|
+
foobar_keys = foo.intersect_leaderboards('foobar', ['bar'], {:aggregate => :max})
|
347
|
+
assert_equal 2, foobar_keys
|
348
|
+
|
349
|
+
foobar = Leaderboard.new('foobar')
|
350
|
+
assert_equal 2, foobar.total_members
|
351
|
+
|
352
|
+
first_leader_in_foobar = foobar.leaders(1).first
|
353
|
+
assert_equal 1, first_leader_in_foobar[:rank]
|
354
|
+
assert_equal 'bar_3', first_leader_in_foobar[:member]
|
355
|
+
assert_equal 6, first_leader_in_foobar[:score]
|
356
|
+
|
357
|
+
foo.disconnect
|
358
|
+
bar.disconnect
|
359
|
+
foobar.disconnect
|
360
|
+
end
|
361
|
+
|
362
|
+
def test_massage_leader_data_respects_with_scores
|
363
|
+
rank_members_in_leaderboard(25)
|
364
|
+
|
365
|
+
assert_equal 25, @leaderboard.total_members
|
366
|
+
|
367
|
+
leaders = @leaderboard.leaders(1, {:with_scores => false, :with_rank => false})
|
368
|
+
assert_not_nil leaders[0][:member]
|
369
|
+
assert_nil leaders[0][:score]
|
370
|
+
assert_nil leaders[0][:rank]
|
371
|
+
|
372
|
+
@leaderboard.page_size = 25
|
373
|
+
leaders = @leaderboard.leaders(1, {:with_scores => false, :with_rank => false})
|
374
|
+
assert_equal 25, leaders.size
|
375
|
+
|
376
|
+
@leaderboard.page_size = Leaderboard::DEFAULT_PAGE_SIZE
|
377
|
+
leaders = @leaderboard.leaders(1, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
|
378
|
+
assert_not_nil leaders[0][:member]
|
379
|
+
assert_not_nil leaders[0][:score]
|
380
|
+
assert_not_nil leaders[0][:rank]
|
381
|
+
|
382
|
+
@leaderboard.page_size = 25
|
383
|
+
leaders = @leaderboard.leaders(1, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS)
|
384
|
+
assert_equal 25, leaders.size
|
385
|
+
end
|
386
|
+
|
387
|
+
def test_total_pages_in_with_new_page_size
|
388
|
+
rank_members_in_leaderboard(25)
|
389
|
+
|
390
|
+
assert_equal 1, @leaderboard.total_pages_in(@leaderboard.leaderboard_name)
|
391
|
+
assert_equal 5, @leaderboard.total_pages_in(@leaderboard.leaderboard_name, 5)
|
392
|
+
end
|
393
|
+
|
394
|
+
def test_leaders_call_with_new_page_size
|
395
|
+
rank_members_in_leaderboard(25)
|
396
|
+
|
397
|
+
assert_equal 5, @leaderboard.leaders(1, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS.merge({:page_size => 5})).size
|
398
|
+
assert_equal 10, @leaderboard.leaders(1, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS.merge({:page_size => 10})).size
|
399
|
+
assert_equal 10, @leaderboard.leaders(2, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS.merge({:page_size => 10})).size
|
400
|
+
assert_equal 5, @leaderboard.leaders(3, Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS.merge({:page_size => 10})).size
|
401
|
+
end
|
402
|
+
|
403
|
+
def test_around_me_call_with_new_page_size
|
404
|
+
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)
|
405
|
+
|
406
|
+
leaders_around_me = @leaderboard.around_me('member_30', Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS.merge({:page_size => 3}))
|
407
|
+
assert_equal 3, leaders_around_me.size
|
408
|
+
assert_equal 'member_31', leaders_around_me[2][:member]
|
409
|
+
assert_equal 'member_29', leaders_around_me[0][:member]
|
410
|
+
end
|
411
|
+
|
412
|
+
def test_percentile_for
|
413
|
+
rank_members_in_leaderboard(12)
|
414
|
+
|
415
|
+
assert_equal 100, @leaderboard.percentile_for('member_1')
|
416
|
+
assert_equal 91, @leaderboard.percentile_for('member_2')
|
417
|
+
assert_equal 83, @leaderboard.percentile_for('member_3')
|
418
|
+
assert_equal 75, @leaderboard.percentile_for('member_4')
|
419
|
+
assert_equal 8, @leaderboard.percentile_for('member_12')
|
420
|
+
end
|
421
|
+
|
422
|
+
def test_around_me_for_invalid_member
|
423
|
+
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)
|
424
|
+
|
425
|
+
leaders_around_me = @leaderboard.around_me('jones', Leaderboard::DEFAULT_LEADERBOARD_REQUEST_OPTIONS.merge({:page_size => 3}))
|
426
|
+
assert_equal 0, leaders_around_me.size
|
427
|
+
end
|
428
|
+
|
429
|
+
def test_score_and_rank_for_non_existent_member
|
430
|
+
score_and_rank_for_member = @leaderboard.score_and_rank_for('jones')
|
431
|
+
|
432
|
+
assert_equal 'jones', score_and_rank_for_member[:member]
|
433
|
+
assert_equal 0.0, score_and_rank_for_member[:score]
|
434
|
+
assert_nil score_and_rank_for_member[:rank]
|
435
|
+
end
|
436
|
+
|
437
|
+
def test_ranked_in_list_for_non_existent_member
|
438
|
+
rank_members_in_leaderboard
|
439
|
+
|
440
|
+
members = ['member_1', 'member_5', 'jones']
|
441
|
+
ranked_members = @leaderboard.ranked_in_list(members)
|
442
|
+
|
443
|
+
assert_equal 3, ranked_members.size
|
444
|
+
assert_nil ranked_members[2][:rank]
|
445
|
+
end
|
446
|
+
|
447
|
+
def test_percentile_for_non_existent_member
|
448
|
+
percentile = @leaderboard.percentile_for('jones')
|
449
|
+
|
450
|
+
assert_nil percentile
|
451
|
+
end
|
452
|
+
|
453
|
+
def test_change_score_for_non_existent_member
|
454
|
+
assert_equal 0.0, @leaderboard.score_for('jones')
|
455
|
+
@leaderboard.change_score_for('jones', 5)
|
456
|
+
assert_equal 5.0, @leaderboard.score_for('jones')
|
457
|
+
end
|
458
|
+
|
459
|
+
private
|
460
|
+
|
461
|
+
def rank_members_in_leaderboard(members_to_add = 5)
|
462
|
+
1.upto(members_to_add) do |index|
|
463
|
+
@leaderboard.rank_member("member_#{index}", index)
|
464
|
+
end
|
465
|
+
end
|
466
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: leaderboard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-02-
|
12
|
+
date: 2012-02-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
16
|
-
requirement: &
|
16
|
+
requirement: &2157419300 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2157419300
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &2157418880 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2157418880
|
36
36
|
description: Leaderboards backed by Redis in Ruby
|
37
37
|
email:
|
38
38
|
- dczarnecki@agoragames.com
|
@@ -55,6 +55,7 @@ files:
|
|
55
55
|
- test/test.conf
|
56
56
|
- test/test_helper.rb
|
57
57
|
- test/test_leaderboard.rb
|
58
|
+
- test/test_rev_leaderboard.rb
|
58
59
|
homepage: https://github.com/agoragames/leaderboard
|
59
60
|
licenses: []
|
60
61
|
post_install_message:
|
@@ -69,7 +70,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
69
70
|
version: '0'
|
70
71
|
segments:
|
71
72
|
- 0
|
72
|
-
hash:
|
73
|
+
hash: 2153712714897513648
|
73
74
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
75
|
none: false
|
75
76
|
requirements:
|
@@ -78,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
79
|
version: '0'
|
79
80
|
segments:
|
80
81
|
- 0
|
81
|
-
hash:
|
82
|
+
hash: 2153712714897513648
|
82
83
|
requirements: []
|
83
84
|
rubyforge_project: leaderboard
|
84
85
|
rubygems_version: 1.8.10
|
@@ -90,3 +91,4 @@ test_files:
|
|
90
91
|
- test/test.conf
|
91
92
|
- test/test_helper.rb
|
92
93
|
- test/test_leaderboard.rb
|
94
|
+
- test/test_rev_leaderboard.rb
|