Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leaders or members #16

Merged
merged 5 commits into from Jun 15, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.markdown
@@ -1,5 +1,11 @@
# CHANGELOG

## leaderboard 2.2.0 (in progress)

* 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.
* Add `member_at` and `member_at_in` methods. These will retrieve a given member from the leaderboard at the specified position.
* `members` and `members_in` are now aliases for the `leaders` and `leaders_in` methods.

## leaderboard 2.1.0 (2012-06-11)

* Added ability to store optional member data alongside the leaderboard data.
Expand Down
11 changes: 10 additions & 1 deletion README.markdown
Expand Up @@ -174,6 +174,8 @@ Below is an example of retrieving the first page in the leaderboard without scor
=> [{: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"}]
```

`members` and `members_in` are aliases for the `leaders` and `leaders_in` methods.

Add more members to your leaderboard:

```ruby
Expand Down Expand Up @@ -202,10 +204,17 @@ Get rank and score for an arbitrary list of members (e.g. friends) from the lead
Retrieve members from the leaderboard in a given score range:

```ruby
leaders = highscore_lb.leaders_from_score_range(4, 19)
members = highscore_lb.members_from_score_range(4, 19)
=> [{: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}]
```

Retrieve a single member from the leaderboard at a given position:

```ruby
members = highscore_lb.member_at(4)
=> {:member=>"member_92", :rank=>4, :score=>92.0}
```

### Ranking multiple members in a leaderboard at once

Insert multiple data items for members and their associated scores:
Expand Down
48 changes: 41 additions & 7 deletions lib/leaderboard.rb
Expand Up @@ -489,6 +489,8 @@ def leaders(current_page, options = {})
leaders_in(@leaderboard_name, current_page, options)
end

alias_method :members, :leaders

# Retrieve a page of leaders from the named leaderboard.
#
# @param leaderboard_name [String] Name of the leaderboard.
Expand Down Expand Up @@ -532,26 +534,28 @@ def leaders_in(leaderboard_name, current_page, options = {})
end
end

# Retrieve leaders from the leaderboard within a given score range.
alias_method :members_in, :leaders_in

# Retrieve members from the leaderboard within a given score range.
#
# @param minimum_score [float] Minimum score (inclusive).
# @param maximum_score [float] Maximum score (inclusive).
# @param options [Hash] Options to be used when retrieving the data from the leaderboard.
#
# @return leaders from the leaderboard that fall within the given score range.
def leaders_from_score_range(minimum_score, maximum_score, options = {})
leaders_from_score_range_in(@leaderboard_name, minimum_score, maximum_score, options)
# @return members from the leaderboard that fall within the given score range.
def members_from_score_range(minimum_score, maximum_score, options = {})
members_from_score_range_in(@leaderboard_name, minimum_score, maximum_score, options)
end

# Retrieve leaders from the named leaderboard within a given score range.
# Retrieve members from the named leaderboard within a given score range.
#
# @param leaderboard_name [String] Name of the leaderboard.
# @param minimum_score [float] Minimum score (inclusive).
# @param maximum_score [float] Maximum score (inclusive).
# @param options [Hash] Options to be used when retrieving the data from the leaderboard.
#
# @return leaders from the leaderboard that fall within the given score range.
def leaders_from_score_range_in(leaderboard_name, minimum_score, maximum_score, options = {})
# @return members from the leaderboard that fall within the given score range.
def members_from_score_range_in(leaderboard_name, minimum_score, maximum_score, options = {})
leaderboard_options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS.dup
leaderboard_options.merge!(options)

Expand All @@ -565,6 +569,36 @@ def leaders_from_score_range_in(leaderboard_name, minimum_score, maximum_score,
return []
end
end

# Retrieve a member at the specified index from the leaderboard.
#
# @param position [int] Position in leaderboard.
# @param options [Hash] Options to be used when retrieving the member from the leaderboard.
#
# @return a member from the leaderboard.
def member_at(position, options = {})
member_at_in(@leaderboard_name, position, options)
end

# Retrieve a member at the specified index from the leaderboard.
#
# @param leaderboard_name [String] Name of the leaderboard.
# @param position [int] Position in named leaderboard.
# @param options [Hash] Options to be used when retrieving the member from the named leaderboard.
#
# @return a page of leaders from the named leaderboard.
def member_at_in(leaderboard_name, position, options = {})
if position <= total_members_in(leaderboard_name)
leaderboard_options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS.dup
leaderboard_options.merge!(options)
page_size = validate_page_size(leaderboard_options[:page_size]) || @page_size
current_page = (position.to_f / page_size.to_f).ceil
offset = (position - 1) % page_size

leaders = leaders_in(leaderboard_name, current_page, options)
leaders[offset] if leaders
end
end

# Retrieve a page of leaders from the leaderboard around a given member.
#
Expand Down
39 changes: 32 additions & 7 deletions spec/leaderboard_spec.rb
Expand Up @@ -102,6 +102,20 @@
leaders[-1][:score].to_i.should be(1)
end

it 'should return the correct list when calling members' do
rank_members_in_leaderboard(25)

@leaderboard.total_members.should be(25)

members = @leaderboard.members(1)

members.size.should be(25)
members[0][:member].should == 'member_25'
members[-2][:member].should == 'member_2'
members[-1][:member].should == 'member_1'
members[-1][:score].to_i.should be(1)
end

it 'should return the correct number of members when calling leaders with multiple pages' do
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)

Expand All @@ -126,24 +140,24 @@
leaders.size.should be(1)
end

it 'should allow you to retrieve leaders in a given score range' do
it 'should allow you to retrieve members in a given score range' do
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)

leaders = @leaderboard.leaders_from_score_range(10, 15, {:with_scores => false, :with_rank => false})
members = @leaderboard.members_from_score_range(10, 15, {:with_scores => false, :with_rank => false})

member_15 = {:member => 'member_15'}
leaders[0].should == member_15
members[0].should == member_15

member_10 = {:member => 'member_10'}
leaders[5].should == member_10
members[5].should == member_10

leaders = @leaderboard.leaders_from_score_range(10, 15, {:with_scores => true, :with_rank => true, :with_member_data => true})
members = @leaderboard.members_from_score_range(10, 15, {:with_scores => true, :with_rank => true, :with_member_data => true})

member_15 = {:member => 'member_15', :rank => 11, :score => 15.0, :member_data => {'member_name' => 'Leaderboard member 15'}}
leaders[0].should == member_15
members[0].should == member_15

member_10 = {:member => 'member_10', :rank => 16, :score => 10.0, :member_data => {'member_name' => 'Leaderboard member 10'}}
leaders[5].should == member_10
members[5].should == member_10
end

it 'should allow you to retrieve leaders without scores and ranks' do
Expand Down Expand Up @@ -230,6 +244,17 @@
leaders[0].should == member_26
end

it 'should return a single member when calling member_at' do
rank_members_in_leaderboard(50)
@leaderboard.member_at(1)[:rank].should == 1
@leaderboard.member_at(1)[:score].should == 50.0
@leaderboard.member_at(26)[:rank].should == 26
@leaderboard.member_at(50)[:rank].should == 50
@leaderboard.member_at(51).should be_nil
@leaderboard.member_at(1, :with_member_data => true)[:member_data].should == {'member_name' => 'Leaderboard member 50'}
@leaderboard.member_at(1, :use_zero_index_for_rank => true)[:rank].should == 0
end

it 'should return the correct information when calling around_me' do
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)

Expand Down
39 changes: 32 additions & 7 deletions spec/reverse_leaderboard_spec.rb
Expand Up @@ -33,24 +33,38 @@
leaders[-1][:score].to_i.should be(25)
end

it 'should allow you to retrieve leaders in a given score range' do
it 'should return the correct list when calling members' do
rank_members_in_leaderboard(25)

@leaderboard.total_members.should be(25)

members = @leaderboard.members(1)

members.size.should be(25)
members[0][:member].should == 'member_1'
members[-2][:member].should == 'member_24'
members[-1][:member].should == 'member_25'
members[-1][:score].to_i.should be(25)
end

it 'should allow you to retrieve members in a given score range' do
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE)

leaders = @leaderboard.leaders_from_score_range(10, 15, {:with_scores => false, :with_rank => false})
members = @leaderboard.members_from_score_range(10, 15, {:with_scores => false, :with_rank => false})

member_10 = {:member => 'member_10'}
leaders[0].should == member_10
members[0].should == member_10

member_15 = {:member => 'member_15'}
leaders[5].should == member_15
members[5].should == member_15

leaders = @leaderboard.leaders_from_score_range(10, 15, {:with_scores => true, :with_rank => true, :with_member_data => true})
members = @leaderboard.members_from_score_range(10, 15, {:with_scores => true, :with_rank => true, :with_member_data => true})

member_10 = {:member => 'member_10', :rank => 10, :score => 10.0, :member_data => {'member_name' => 'Leaderboard member 10'}}
leaders[0].should == member_10
members[0].should == member_10

member_15 = {:member => 'member_15', :rank => 15, :score => 15.0, :member_data => {'member_name' => 'Leaderboard member 15'}}
leaders[5].should == member_15
members[5].should == member_15
end

it 'should allow you to retrieve leaders without scores and ranks' do
Expand Down Expand Up @@ -101,6 +115,17 @@
leaders[0].should == member_1
end

it 'should return a single member when calling member_at' do
rank_members_in_leaderboard(50)
@leaderboard.member_at(1)[:rank].should == 1
@leaderboard.member_at(1)[:score].should == 1.0
@leaderboard.member_at(26)[:rank].should == 26
@leaderboard.member_at(50)[:rank].should == 50
@leaderboard.member_at(51).should be_nil
@leaderboard.member_at(1, :with_member_data => true)[:member_data].should == {'member_name' => 'Leaderboard member 1'}
@leaderboard.member_at(1, :use_zero_index_for_rank => true)[:rank].should == 0
end

it 'should return the correct information when calling around_me' do
rank_members_in_leaderboard(Leaderboard::DEFAULT_PAGE_SIZE * 3 + 1)

Expand Down