lib/leaderboard.rb in leaderboard-1.0.1 vs lib/leaderboard.rb in leaderboard-1.0.2
- old
+ new
@@ -1,9 +1,9 @@
require 'redis'
class Leaderboard
- VERSION = '1.0.1'.freeze
+ VERSION = '1.0.2'.freeze
DEFAULT_PAGE_SIZE = 25
DEFAULT_REDIS_HOST = 'localhost'
DEFAULT_REDIS_PORT = 6379
@@ -31,58 +31,106 @@
@redis_connection = Redis.new(@redis_options)
end
def add_member(member, score)
- @redis_connection.zadd(@leaderboard_name, score, member)
+ add_member_to(@leaderboard_name, member, score)
end
+
+ def add_member_to(leaderboard_name, member, score)
+ @redis_connection.zadd(leaderboard_name, score, member)
+ end
def remove_member(member)
- @redis_connection.zrem(@leaderboard_name, member)
+ remove_member_from(@leaderboard_name, member)
end
+ def remove_member_from(leaderboard_name, member)
+ @redis_connection.zrem(leaderboard_name, member)
+ end
+
def total_members
- @redis_connection.zcard(@leaderboard_name)
+ total_members_in(@leaderboard_name)
end
+ def total_members_in(leaderboard_name)
+ @redis_connection.zcard(leaderboard_name)
+ end
+
def total_pages
- (total_members / @page_size.to_f).ceil
+ total_pages_in(@leaderboard_name)
end
+ def total_pages_in(leaderboard_name)
+ (total_members_in(leaderboard_name) / @page_size.to_f).ceil
+ end
+
def total_members_in_score_range(min_score, max_score)
- @redis_connection.zcount(@leaderboard_name, min_score, max_score)
+ total_members_in_score_range_in(@leaderboard_name, min_score, max_score)
end
- def change_score_for(member, delta)
- @redis_connection.zincrby(@leaderboard_name, delta, member)
+ def total_members_in_score_range_in(leaderboard_name, min_score, max_score)
+ @redis_connection.zcount(leaderboard_name, min_score, max_score)
end
- def rank_for(member, use_zero_index_for_rank = false)
+ def change_score_for(member, delta)
+ change_score_for_member_in(@leaderboard_name, member, delta)
+ end
+
+ def change_score_for_member_in(leaderboard_name, member, delta)
+ @redis_connection.zincrby(leaderboard_name, delta, member)
+ end
+
+ def rank_for(member, use_zero_index_for_rank = false)
+ rank_for_in(@leaderboard_name, member, use_zero_index_for_rank)
+ end
+
+ def rank_for_in(leaderboard_name, member, use_zero_index_for_rank = false)
if use_zero_index_for_rank
- return @redis_connection.zrevrank(@leaderboard_name, member)
+ return @redis_connection.zrevrank(leaderboard_name, member)
else
- return @redis_connection.zrevrank(@leaderboard_name, member) + 1 rescue nil
+ return @redis_connection.zrevrank(leaderboard_name, member) + 1 rescue nil
end
end
def score_for(member)
- @redis_connection.zscore(@leaderboard_name, member).to_f
+ score_for_in(@leaderboard_name, member)
end
+ def score_for_in(leaderboard_name, member)
+ @redis_connection.zscore(leaderboard_name, member).to_f
+ end
+
def check_member?(member)
- !@redis_connection.zscore(@leaderboard_name, member).nil?
+ check_member_in?(@leaderboard_name, member)
end
+ def check_member_in?(leaderboard_name, member)
+ !@redis_connection.zscore(leaderboard_name, member).nil?
+ end
+
def score_and_rank_for(member, use_zero_index_for_rank = false)
- {:member => member, :score => score_for(member), :rank => rank_for(member, use_zero_index_for_rank)}
+ score_and_rank_for_in(@leaderboard_name, member, use_zero_index_for_rank)
end
+
+ def score_and_rank_for_in(leaderboard_name, member, use_zero_index_for_rank = false)
+ {:member => member, :score => score_for_in(leaderboard_name, member), :rank => rank_for_in(leaderboard_name, member, use_zero_index_for_rank)}
+ end
def remove_members_in_score_range(min_score, max_score)
- @redis_connection.zremrangebyscore(@leaderboard_name, min_score, max_score)
+ remove_members_in_score_range_in(@leaderboard_name, min_score, max_score)
end
+ def remove_members_in_score_range_in(leaderboard_name, min_score, max_score)
+ @redis_connection.zremrangebyscore(leaderboard_name, min_score, max_score)
+ end
+
def leaders(current_page, with_scores = true, with_rank = true, use_zero_index_for_rank = false)
+ leaders_in(@leaderboard_name, current_page, with_scores, with_rank, use_zero_index_for_rank)
+ end
+
+ def leaders_in(leaderboard_name, current_page, with_scores = true, with_rank = true, use_zero_index_for_rank = false)
if current_page < 1
current_page = 1
end
if current_page > total_pages
@@ -96,63 +144,81 @@
starting_offset = 0
end
ending_offset = (starting_offset + @page_size) - 1
- raw_leader_data = @redis_connection.zrevrange(@leaderboard_name, starting_offset, ending_offset, :with_scores => with_scores)
+ raw_leader_data = @redis_connection.zrevrange(leaderboard_name, starting_offset, ending_offset, :with_scores => with_scores)
if raw_leader_data
- massage_leader_data(raw_leader_data, with_rank, use_zero_index_for_rank)
+ massage_leader_data(leaderboard_name, raw_leader_data, with_rank, use_zero_index_for_rank)
else
return nil
end
end
def around_me(member, with_scores = true, with_rank = true, use_zero_index_for_rank = false)
- reverse_rank_for_member = @redis_connection.zrevrank(@leaderboard_name, member)
+ around_me_in(@leaderboard_name, member, with_scores, with_rank, use_zero_index_for_rank)
+ end
+
+ def around_me_in(leaderboard_name, member, with_scores = true, with_rank = true, use_zero_index_for_rank = false)
+ reverse_rank_for_member = @redis_connection.zrevrank(leaderboard_name, member)
starting_offset = reverse_rank_for_member - (@page_size / 2)
if starting_offset < 0
starting_offset = 0
end
ending_offset = (starting_offset + @page_size) - 1
- raw_leader_data = @redis_connection.zrevrange(@leaderboard_name, starting_offset, ending_offset, :with_scores => with_scores)
+ raw_leader_data = @redis_connection.zrevrange(leaderboard_name, starting_offset, ending_offset, :with_scores => with_scores)
if raw_leader_data
- massage_leader_data(raw_leader_data, with_rank, use_zero_index_for_rank)
+ massage_leader_data(leaderboard_name, raw_leader_data, with_rank, use_zero_index_for_rank)
else
return nil
end
end
def ranked_in_list(members, with_scores = true, use_zero_index_for_rank = false)
+ ranked_in_list_in(@leaderboard_name, members, with_scores, use_zero_index_for_rank)
+ end
+
+ def ranked_in_list_in(leaderboard_name, members, with_scores = true, use_zero_index_for_rank = false)
ranks_for_members = []
members.each do |member|
data = {}
data[:member] = member
- data[:rank] = rank_for(member, use_zero_index_for_rank)
- data[:score] = score_for(member) if with_scores
+ data[:rank] = rank_for_in(leaderboard_name, member, use_zero_index_for_rank)
+ data[:score] = score_for_in(leaderboard_name, member) if with_scores
ranks_for_members << data
end
ranks_for_members
end
+ # Merge leaderboards given by keys with this leaderboard into destination
+ def merge_leaderboards(destination, keys, options = {:aggregate => :sum})
+ @redis_connection.zunionstore(destination, keys.insert(0, @leaderboard_name), options)
+ end
+
+ # Intersect leaderboards given by keys with this leaderboard into destination
+ def intersect_leaderboards(destination, keys, options = {:aggregate => :sum})
+ @redis_connection.zinterstore(destination, keys.insert(0, @leaderboard_name), options)
+ end
+
private
- def massage_leader_data(leaders, with_rank, use_zero_index_for_rank)
+ def massage_leader_data(leaderboard_name, leaders, with_rank, use_zero_index_for_rank)
member_attribute = true
leader_data = []
data = {}
leaders.each do |leader_data_item|
if member_attribute
data[:member] = leader_data_item
else
data[:score] = leader_data_item.to_f
- data[:rank] = rank_for(data[:member], use_zero_index_for_rank) if with_rank
+ data[:rank] = rank_for_in(leaderboard_name, data[:member], use_zero_index_for_rank) if with_rank
leader_data << data
data = {}
end
member_attribute = !member_attribute
\ No newline at end of file