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 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