leaderboard 2.1.0 → 2.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.markdown +10 -0
- data/README.markdown +16 -0
- data/lib/leaderboard.rb +68 -0
- data/lib/leaderboard/version.rb +1 -1
- data/spec/leaderboard_spec.rb +45 -0
- data/spec/reverse_leaderboard_spec.rb +45 -0
- data/spec/version_spec.rb +1 -1
- metadata +4 -4
data/CHANGELOG.markdown
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## leaderboard 2.2.1 (2012-06-18)
|
4
|
+
|
5
|
+
* Fix for #17 - Leaderboard not compatible with redis 2.1.1. Redis' `zrangebyscore` and `zrevrangebyscore` methods do not return scores by default. No need to pass the option in the initial call.
|
6
|
+
|
7
|
+
## leaderboard 2.2.0 (2012-06-18)
|
8
|
+
|
9
|
+
* Added `members_from_score_range` and `members_from_score_range_in` methods. These will retrieve members from the leaderboard that fall within a given score range.
|
10
|
+
* Add `member_at` and `member_at_in` methods. These will retrieve a given member from the leaderboard at the specified position.
|
11
|
+
* `members` and `members_in` are now aliases for the `leaders` and `leaders_in` methods.
|
12
|
+
|
3
13
|
## leaderboard 2.1.0 (2012-06-11)
|
4
14
|
|
5
15
|
* Added ability to store optional member data alongside the leaderboard data.
|
data/README.markdown
CHANGED
@@ -174,6 +174,8 @@ Below is an example of retrieving the first page in the leaderboard without scor
|
|
174
174
|
=> [{: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"}]
|
175
175
|
```
|
176
176
|
|
177
|
+
You can also use the `members` and `members_in` methods as aliases for the `leaders` and `leaders_in` methods.
|
178
|
+
|
177
179
|
Add more members to your leaderboard:
|
178
180
|
|
179
181
|
```ruby
|
@@ -199,6 +201,20 @@ Get rank and score for an arbitrary list of members (e.g. friends) from the lead
|
|
199
201
|
=> [{:member=>"member_1", :rank=>56, :score=>1.0}, {:member=>"member_62", :rank=>34, :score=>62.0}, {:member=>"member_67", :rank=>29, :score=>67.0}]
|
200
202
|
```
|
201
203
|
|
204
|
+
Retrieve members from the leaderboard in a given score range:
|
205
|
+
|
206
|
+
```ruby
|
207
|
+
members = highscore_lb.members_from_score_range(4, 19)
|
208
|
+
=> [{:member=>"member_10", :rank=>47, :score=>10.0}, {:member=>"member_9", :rank=>48, :score=>9.0}, {:member=>"member_8", :rank=>49, :score=>8.0}, {:member=>"member_7", :rank=>50, :score=>7.0}, {:member=>"member_6", :rank=>51, :score=>6.0}, {:member=>"member_5", :rank=>52, :score=>5.0}, {:member=>"member_4", :rank=>53, :score=>4.0}]
|
209
|
+
```
|
210
|
+
|
211
|
+
Retrieve a single member from the leaderboard at a given position:
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
members = highscore_lb.member_at(4)
|
215
|
+
=> {:member=>"member_92", :rank=>4, :score=>92.0}
|
216
|
+
```
|
217
|
+
|
202
218
|
### Ranking multiple members in a leaderboard at once
|
203
219
|
|
204
220
|
Insert multiple data items for members and their associated scores:
|
data/lib/leaderboard.rb
CHANGED
@@ -489,6 +489,8 @@ class Leaderboard
|
|
489
489
|
leaders_in(@leaderboard_name, current_page, options)
|
490
490
|
end
|
491
491
|
|
492
|
+
alias_method :members, :leaders
|
493
|
+
|
492
494
|
# Retrieve a page of leaders from the named leaderboard.
|
493
495
|
#
|
494
496
|
# @param leaderboard_name [String] Name of the leaderboard.
|
@@ -531,6 +533,72 @@ class Leaderboard
|
|
531
533
|
return []
|
532
534
|
end
|
533
535
|
end
|
536
|
+
|
537
|
+
alias_method :members_in, :leaders_in
|
538
|
+
|
539
|
+
# Retrieve members from the leaderboard within a given score range.
|
540
|
+
#
|
541
|
+
# @param minimum_score [float] Minimum score (inclusive).
|
542
|
+
# @param maximum_score [float] Maximum score (inclusive).
|
543
|
+
# @param options [Hash] Options to be used when retrieving the data from the leaderboard.
|
544
|
+
#
|
545
|
+
# @return members from the leaderboard that fall within the given score range.
|
546
|
+
def members_from_score_range(minimum_score, maximum_score, options = {})
|
547
|
+
members_from_score_range_in(@leaderboard_name, minimum_score, maximum_score, options)
|
548
|
+
end
|
549
|
+
|
550
|
+
# Retrieve members from the named leaderboard within a given score range.
|
551
|
+
#
|
552
|
+
# @param leaderboard_name [String] Name of the leaderboard.
|
553
|
+
# @param minimum_score [float] Minimum score (inclusive).
|
554
|
+
# @param maximum_score [float] Maximum score (inclusive).
|
555
|
+
# @param options [Hash] Options to be used when retrieving the data from the leaderboard.
|
556
|
+
#
|
557
|
+
# @return members from the leaderboard that fall within the given score range.
|
558
|
+
def members_from_score_range_in(leaderboard_name, minimum_score, maximum_score, options = {})
|
559
|
+
leaderboard_options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS.dup
|
560
|
+
leaderboard_options.merge!(options)
|
561
|
+
|
562
|
+
raw_leader_data = @reverse ?
|
563
|
+
@redis_connection.zrangebyscore(leaderboard_name, minimum_score, maximum_score) :
|
564
|
+
@redis_connection.zrevrangebyscore(leaderboard_name, maximum_score, minimum_score)
|
565
|
+
|
566
|
+
if raw_leader_data
|
567
|
+
return ranked_in_list_in(leaderboard_name, raw_leader_data, leaderboard_options)
|
568
|
+
else
|
569
|
+
return []
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
573
|
+
# Retrieve a member at the specified index from the leaderboard.
|
574
|
+
#
|
575
|
+
# @param position [int] Position in leaderboard.
|
576
|
+
# @param options [Hash] Options to be used when retrieving the member from the leaderboard.
|
577
|
+
#
|
578
|
+
# @return a member from the leaderboard.
|
579
|
+
def member_at(position, options = {})
|
580
|
+
member_at_in(@leaderboard_name, position, options)
|
581
|
+
end
|
582
|
+
|
583
|
+
# Retrieve a member at the specified index from the leaderboard.
|
584
|
+
#
|
585
|
+
# @param leaderboard_name [String] Name of the leaderboard.
|
586
|
+
# @param position [int] Position in named leaderboard.
|
587
|
+
# @param options [Hash] Options to be used when retrieving the member from the named leaderboard.
|
588
|
+
#
|
589
|
+
# @return a page of leaders from the named leaderboard.
|
590
|
+
def member_at_in(leaderboard_name, position, options = {})
|
591
|
+
if position <= total_members_in(leaderboard_name)
|
592
|
+
leaderboard_options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS.dup
|
593
|
+
leaderboard_options.merge!(options)
|
594
|
+
page_size = validate_page_size(leaderboard_options[:page_size]) || @page_size
|
595
|
+
current_page = (position.to_f / page_size.to_f).ceil
|
596
|
+
offset = (position - 1) % page_size
|
597
|
+
|
598
|
+
leaders = leaders_in(leaderboard_name, current_page, options)
|
599
|
+
leaders[offset] if leaders
|
600
|
+
end
|
601
|
+
end
|
534
602
|
|
535
603
|
# Retrieve a page of leaders from the leaderboard around a given member.
|
536
604
|
#
|
data/lib/leaderboard/version.rb
CHANGED
data/spec/leaderboard_spec.rb
CHANGED
@@ -102,6 +102,20 @@ describe 'Leaderboard' do
|
|
102
102
|
leaders[-1][:score].to_i.should be(1)
|
103
103
|
end
|
104
104
|
|
105
|
+
it 'should return the correct list when calling members' do
|
106
|
+
rank_members_in_leaderboard(25)
|
107
|
+
|
108
|
+
@leaderboard.total_members.should be(25)
|
109
|
+
|
110
|
+
members = @leaderboard.members(1)
|
111
|
+
|
112
|
+
members.size.should be(25)
|
113
|
+
members[0][:member].should == 'member_25'
|
114
|
+
members[-2][:member].should == 'member_2'
|
115
|
+
members[-1][:member].should == 'member_1'
|
116
|
+
members[-1][:score].to_i.should be(1)
|
117
|
+
end
|
118
|
+
|
105
119
|
it 'should return the correct number of members when calling leaders with multiple pages' do
|
106
120
|
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)
|
107
121
|
|
@@ -126,6 +140,26 @@ describe 'Leaderboard' do
|
|
126
140
|
leaders.size.should be(1)
|
127
141
|
end
|
128
142
|
|
143
|
+
it 'should allow you to retrieve members in a given score range' do
|
144
|
+
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
|
145
|
+
|
146
|
+
members = @leaderboard.members_from_score_range(10, 15, {:with_scores => false, :with_rank => false})
|
147
|
+
|
148
|
+
member_15 = {:member => 'member_15'}
|
149
|
+
members[0].should == member_15
|
150
|
+
|
151
|
+
member_10 = {:member => 'member_10'}
|
152
|
+
members[5].should == member_10
|
153
|
+
|
154
|
+
members = @leaderboard.members_from_score_range(10, 15, {:with_scores => true, :with_rank => true, :with_member_data => true})
|
155
|
+
|
156
|
+
member_15 = {:member => 'member_15', :rank => 11, :score => 15.0, :member_data => {'member_name' => 'Leaderboard member 15'}}
|
157
|
+
members[0].should == member_15
|
158
|
+
|
159
|
+
member_10 = {:member => 'member_10', :rank => 16, :score => 10.0, :member_data => {'member_name' => 'Leaderboard member 10'}}
|
160
|
+
members[5].should == member_10
|
161
|
+
end
|
162
|
+
|
129
163
|
it 'should allow you to retrieve leaders without scores and ranks' do
|
130
164
|
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
|
131
165
|
|
@@ -210,6 +244,17 @@ describe 'Leaderboard' do
|
|
210
244
|
leaders[0].should == member_26
|
211
245
|
end
|
212
246
|
|
247
|
+
it 'should return a single member when calling member_at' do
|
248
|
+
rank_members_in_leaderboard(50)
|
249
|
+
@leaderboard.member_at(1)[:rank].should == 1
|
250
|
+
@leaderboard.member_at(1)[:score].should == 50.0
|
251
|
+
@leaderboard.member_at(26)[:rank].should == 26
|
252
|
+
@leaderboard.member_at(50)[:rank].should == 50
|
253
|
+
@leaderboard.member_at(51).should be_nil
|
254
|
+
@leaderboard.member_at(1, :with_member_data => true)[:member_data].should == {'member_name' => 'Leaderboard member 50'}
|
255
|
+
@leaderboard.member_at(1, :use_zero_index_for_rank => true)[:rank].should == 0
|
256
|
+
end
|
257
|
+
|
213
258
|
it 'should return the correct information when calling around_me' do
|
214
259
|
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)
|
215
260
|
|
@@ -33,6 +33,40 @@ describe 'Leaderboard (reverse option)' do
|
|
33
33
|
leaders[-1][:score].to_i.should be(25)
|
34
34
|
end
|
35
35
|
|
36
|
+
it 'should return the correct list when calling members' do
|
37
|
+
rank_members_in_leaderboard(25)
|
38
|
+
|
39
|
+
@leaderboard.total_members.should be(25)
|
40
|
+
|
41
|
+
members = @leaderboard.members(1)
|
42
|
+
|
43
|
+
members.size.should be(25)
|
44
|
+
members[0][:member].should == 'member_1'
|
45
|
+
members[-2][:member].should == 'member_24'
|
46
|
+
members[-1][:member].should == 'member_25'
|
47
|
+
members[-1][:score].to_i.should be(25)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should allow you to retrieve members in a given score range' do
|
51
|
+
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
|
52
|
+
|
53
|
+
members = @leaderboard.members_from_score_range(10, 15, {:with_scores => false, :with_rank => false})
|
54
|
+
|
55
|
+
member_10 = {:member => 'member_10'}
|
56
|
+
members[0].should == member_10
|
57
|
+
|
58
|
+
member_15 = {:member => 'member_15'}
|
59
|
+
members[5].should == member_15
|
60
|
+
|
61
|
+
members = @leaderboard.members_from_score_range(10, 15, {:with_scores => true, :with_rank => true, :with_member_data => true})
|
62
|
+
|
63
|
+
member_10 = {:member => 'member_10', :rank => 10, :score => 10.0, :member_data => {'member_name' => 'Leaderboard member 10'}}
|
64
|
+
members[0].should == member_10
|
65
|
+
|
66
|
+
member_15 = {:member => 'member_15', :rank => 15, :score => 15.0, :member_data => {'member_name' => 'Leaderboard member 15'}}
|
67
|
+
members[5].should == member_15
|
68
|
+
end
|
69
|
+
|
36
70
|
it 'should allow you to retrieve leaders without scores and ranks' do
|
37
71
|
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)
|
38
72
|
|
@@ -81,6 +115,17 @@ describe 'Leaderboard (reverse option)' do
|
|
81
115
|
leaders[0].should == member_1
|
82
116
|
end
|
83
117
|
|
118
|
+
it 'should return a single member when calling member_at' do
|
119
|
+
rank_members_in_leaderboard(50)
|
120
|
+
@leaderboard.member_at(1)[:rank].should == 1
|
121
|
+
@leaderboard.member_at(1)[:score].should == 1.0
|
122
|
+
@leaderboard.member_at(26)[:rank].should == 26
|
123
|
+
@leaderboard.member_at(50)[:rank].should == 50
|
124
|
+
@leaderboard.member_at(51).should be_nil
|
125
|
+
@leaderboard.member_at(1, :with_member_data => true)[:member_data].should == {'member_name' => 'Leaderboard member 1'}
|
126
|
+
@leaderboard.member_at(1, :use_zero_index_for_rank => true)[:rank].should == 0
|
127
|
+
end
|
128
|
+
|
84
129
|
it 'should return the correct information when calling around_me' do
|
85
130
|
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)
|
86
131
|
|
data/spec/version_spec.rb
CHANGED
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.1
|
4
|
+
version: 2.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-06-
|
12
|
+
date: 2012-06-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
@@ -97,7 +97,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
97
97
|
version: '0'
|
98
98
|
segments:
|
99
99
|
- 0
|
100
|
-
hash:
|
100
|
+
hash: -27523170013791394
|
101
101
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
102
|
none: false
|
103
103
|
requirements:
|
@@ -106,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
106
106
|
version: '0'
|
107
107
|
segments:
|
108
108
|
- 0
|
109
|
-
hash:
|
109
|
+
hash: -27523170013791394
|
110
110
|
requirements: []
|
111
111
|
rubyforge_project: leaderboard
|
112
112
|
rubygems_version: 1.8.23
|