leaderboard 2.0.2 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,8 +1,10 @@
1
1
  coverage
2
2
  rdoc
3
3
  doc
4
+ .vagrant
4
5
  .yardoc
5
6
  .bundle
6
7
  pkg
7
8
  Gemfile.lock
8
9
  test/db/*
10
+ *.rdb
@@ -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
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011 David Czarnecki
1
+ Copyright (c) 2011-2012 David Czarnecki
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -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
- Install the gem:
9
+ `gem install leaderboard`
10
+
11
+ or in your `Gemfile`
10
12
 
11
13
  ```ruby
12
- gem "leaderboard"
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
@@ -7,6 +7,7 @@ Rake::TestTask.new(:test) do |test|
7
7
  test.libs << 'lib' << 'test'
8
8
  test.pattern = 'test/**/test_*.rb'
9
9
  test.verbose = true
10
+ # test.warning = true
10
11
  end
11
12
 
12
13
  REDIS_DIR = File.expand_path(File.join("..", "test"), __FILE__)
@@ -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 use_zero_index_for_rank
210
- return @redis_connection.zrevrank(leaderboard_name, member)
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
- return @redis_connection.zrevrank(leaderboard_name, member) + 1 rescue nil
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
- transaction.zrevrank(leaderboard_name, member)
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
- raw_leader_data = @redis_connection.zrevrange(leaderboard_name, starting_offset, ending_offset, :with_scores => false)
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 = @redis_connection.zrevrank(leaderboard_name, 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 = @redis_connection.zrevrange(leaderboard_name, starting_offset, ending_offset, :with_scores => false)
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
- transaction.zrevrank(leaderboard_name, member) if leaderboard_options[:with_rank]
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
@@ -1,3 +1,3 @@
1
1
  class Leaderboard
2
- VERSION = '2.0.2'.freeze
2
+ VERSION = '2.0.3'.freeze
3
3
  end
@@ -2,8 +2,8 @@ require 'test_helper'
2
2
 
3
3
  class TestLeaderboard < Test::Unit::TestCase
4
4
  def setup
5
- @leaderboard = Leaderboard.new('name')
6
- @redis_connection = Redis.new
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.2', Leaderboard::VERSION
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.2
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-03 00:00:00.000000000 Z
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: &70115900454580 !ruby/object:Gem::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: *70115900454580
24
+ version_requirements: *2157419300
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &70115900454140 !ruby/object:Gem::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: *70115900454140
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: 822397651931818712
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: 822397651931818712
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