class Leaderboard

Constants

DEFAULT_PAGE_SIZE
DEFAULT_REDIS_HOST
DEFAULT_REDIS_PORT
VERSION

Attributes

leaderboard_name[R]
page_size[RW]

Public Class Methods

new(leaderboard_name, host = DEFAULT_REDIS_HOST, port = DEFAULT_REDIS_PORT, page_size = DEFAULT_PAGE_SIZE, redis_options = {}) click to toggle source
# File lib/multi-leaderboard.rb, line 13
def initialize(leaderboard_name, host = DEFAULT_REDIS_HOST, port = DEFAULT_REDIS_PORT, page_size = DEFAULT_PAGE_SIZE, redis_options = {})
  @leaderboard_name = leaderboard_name
  
  if page_size < 1
    page_size = DEFAULT_PAGE_SIZE
  end
  
  @page_size = page_size
  
  redis_options = redis_options.dup
  redis_options[:host] ||= host
  redis_options[:port] ||= port
  
  @redis_options = redis_options
  
  @@redis_connection ||= Redis.new(@redis_options)
end
redis_connection() click to toggle source
# File lib/multi-leaderboard.rb, line 215
def redis_connection
  @@redis_connection
end
redis_connection=(redis) click to toggle source
# File lib/multi-leaderboard.rb, line 211
def redis_connection=(redis)
  @@redis_connection = redis
end

Public Instance Methods

add_member(member, score) click to toggle source
# File lib/multi-leaderboard.rb, line 31
def add_member(member, score)
  add_member_to(@leaderboard_name, member, score)
end
add_member_to(leaderboard_name, member, score) click to toggle source
# File lib/multi-leaderboard.rb, line 35
def add_member_to(leaderboard_name, member, score)
  @@redis_connection.zadd(leaderboard_name, score, member)
end
around_me(member, with_scores = true, with_rank = true, use_zero_index_for_rank = false) click to toggle source
# File lib/multi-leaderboard.rb, line 153
def around_me(member, with_scores = true, with_rank = true, use_zero_index_for_rank = false)
  around_me_in(@leaderboard_name, member, with_scores, with_rank, use_zero_index_for_rank)
end
around_me_in(leaderboard_name, member, with_scores = true, with_rank = true, use_zero_index_for_rank = false) click to toggle source
# File lib/multi-leaderboard.rb, line 157
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)
  if raw_leader_data
    massage_leader_data(leaderboard_name, raw_leader_data, with_rank, use_zero_index_for_rank)
  else
    return nil
  end
end
change_score_for(member, delta) click to toggle source
# File lib/multi-leaderboard.rb, line 71
def change_score_for(member, delta)    
  change_score_for_member_in(@leaderboard_name, member, delta)
end
change_score_for_member_in(leaderboard_name, member, delta) click to toggle source
# File lib/multi-leaderboard.rb, line 75
def change_score_for_member_in(leaderboard_name, member, delta)
  @@redis_connection.zincrby(leaderboard_name, delta, member)
end
check_member?(member) click to toggle source
# File lib/multi-leaderboard.rb, line 99
def check_member?(member)
  check_member_in?(@leaderboard_name, member)
end
check_member_in?(leaderboard_name, member) click to toggle source
# File lib/multi-leaderboard.rb, line 103
def check_member_in?(leaderboard_name, member)
   @@redis_connection.zscore(leaderboard_name, member).nil?
end
disconnect() click to toggle source

Disconnect from the redis server

# File lib/multi-leaderboard.rb, line 205
def disconnect
  @@redis_connection.client.disconnect
end
intersect_leaderboards(destination, keys, options = {:aggregate => :sum}) click to toggle source

Intersect leaderboards given by keys with this leaderboard into destination

# File lib/multi-leaderboard.rb, line 200
def intersect_leaderboards(destination, keys, options = {:aggregate => :sum})
  @@redis_connection.zinterstore(destination, keys.insert(0, @leaderboard_name), options)
end
leaders(current_page, with_scores = true, with_rank = true, use_zero_index_for_rank = false) click to toggle source
# File lib/multi-leaderboard.rb, line 123
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
leaders_in(leaderboard_name, current_page, with_scores = true, with_rank = true, use_zero_index_for_rank = false) click to toggle source
# File lib/multi-leaderboard.rb, line 127
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
    current_page = total_pages
  end
  
  index_for_redis = current_page - 1

  starting_offset = (index_for_redis * @page_size)
  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)
  if raw_leader_data
    massage_leader_data(leaderboard_name, raw_leader_data, with_rank, use_zero_index_for_rank)
  else
    return nil
  end
end
merge_leaderboards(destination, keys, options = {:aggregate => :sum}) click to toggle source

Merge leaderboards given by keys with this leaderboard into destination

# File lib/multi-leaderboard.rb, line 195
def merge_leaderboards(destination, keys, options = {:aggregate => :sum})
  @@redis_connection.zunionstore(destination, keys.insert(0, @leaderboard_name), options)
end
rank_for(member, use_zero_index_for_rank = false) click to toggle source
# File lib/multi-leaderboard.rb, line 79
def rank_for(member, use_zero_index_for_rank = false)
  rank_for_in(@leaderboard_name, member, use_zero_index_for_rank)
end
rank_for_in(leaderboard_name, member, use_zero_index_for_rank = false) click to toggle source
# File lib/multi-leaderboard.rb, line 83
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)
  else
    return @@redis_connection.zrevrank(leaderboard_name, member) + 1 rescue nil
  end
end
ranked_in_list(members, with_scores = true, use_zero_index_for_rank = false) click to toggle source
# File lib/multi-leaderboard.rb, line 175
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
ranked_in_list_in(leaderboard_name, members, with_scores = true, use_zero_index_for_rank = false) click to toggle source
# File lib/multi-leaderboard.rb, line 179
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_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
remove_member(member) click to toggle source
# File lib/multi-leaderboard.rb, line 39
def remove_member(member)
  remove_member_from(@leaderboard_name, member)
end
remove_member_from(leaderboard_name, member) click to toggle source
# File lib/multi-leaderboard.rb, line 43
def remove_member_from(leaderboard_name, member)
  @@redis_connection.zrem(leaderboard_name, member)
end
remove_members_in_score_range(min_score, max_score) click to toggle source
# File lib/multi-leaderboard.rb, line 115
def remove_members_in_score_range(min_score, max_score)
  remove_members_in_score_range_in(@leaderboard_name, min_score, max_score)
end
remove_members_in_score_range_in(leaderboard_name, min_score, max_score) click to toggle source
# File lib/multi-leaderboard.rb, line 119
def remove_members_in_score_range_in(leaderboard_name, min_score, max_score)
  @@redis_connection.zremrangebyscore(leaderboard_name, min_score, max_score)
end
score_and_rank_for(member, use_zero_index_for_rank = false) click to toggle source
# File lib/multi-leaderboard.rb, line 107
def score_and_rank_for(member, use_zero_index_for_rank = false)
  score_and_rank_for_in(@leaderboard_name, member, use_zero_index_for_rank)
end
score_and_rank_for_in(leaderboard_name, member, use_zero_index_for_rank = false) click to toggle source
# File lib/multi-leaderboard.rb, line 111
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
score_for(member) click to toggle source
# File lib/multi-leaderboard.rb, line 91
def score_for(member)
  score_for_in(@leaderboard_name, member)
end
score_for_in(leaderboard_name, member) click to toggle source
# File lib/multi-leaderboard.rb, line 95
def score_for_in(leaderboard_name, member)
  @@redis_connection.zscore(leaderboard_name, member).to_f
end
total_members() click to toggle source
# File lib/multi-leaderboard.rb, line 47
def total_members
  total_members_in(@leaderboard_name)
end
total_members_in(leaderboard_name) click to toggle source
# File lib/multi-leaderboard.rb, line 51
def total_members_in(leaderboard_name)
  @@redis_connection.zcard(leaderboard_name)
end
total_members_in_score_range(min_score, max_score) click to toggle source
# File lib/multi-leaderboard.rb, line 63
def total_members_in_score_range(min_score, max_score)
  total_members_in_score_range_in(@leaderboard_name, min_score, max_score)
end
total_members_in_score_range_in(leaderboard_name, min_score, max_score) click to toggle source
# File lib/multi-leaderboard.rb, line 67
def total_members_in_score_range_in(leaderboard_name, min_score, max_score)
  @@redis_connection.zcount(leaderboard_name, min_score, max_score)
end
total_pages() click to toggle source
# File lib/multi-leaderboard.rb, line 55
def total_pages
  total_pages_in(@leaderboard_name)
end
total_pages_in(leaderboard_name) click to toggle source
# File lib/multi-leaderboard.rb, line 59
def total_pages_in(leaderboard_name)
  (total_members_in(leaderboard_name) / @page_size.to_f).ceil
end

Private Instance Methods

massage_leader_data(leaderboard_name, leaders, with_rank, use_zero_index_for_rank) click to toggle source
# File lib/multi-leaderboard.rb, line 223
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_in(leaderboard_name, data[:member], use_zero_index_for_rank) if with_rank
      leader_data << data
      data = {}     
    end
          
    member_attribute = !member_attribute
  end
  
  leader_data
end