class TieRankingLeaderboard
Constants
- DEFAULT_OPTIONS
Default options when creating a leaderboard. Page size is 25 and reverse is set to false, meaning various methods will return results in highest-to-lowest order.
Public Class Methods
Create a new instance of a leaderboard.
@param leaderboard [String] Name of the leaderboard. @param options [Hash] Options for the leaderboard such as :page_size
. @param redis_options [Hash] Options for configuring Redis.
Examples
leaderboard = Leaderboard.new('highscores') leaderboard = Leaderboard.new('highscores', {:page_size => 10})
Leaderboard::new
# File lib/tie_ranking_leaderboard.rb, line 28 def initialize(leaderboard_name, options = DEFAULT_OPTIONS, redis_options = DEFAULT_REDIS_OPTIONS) super leaderboard_options = DEFAULT_OPTIONS.dup leaderboard_options.merge!(options) @ties_namespace = leaderboard_options[:ties_namespace] end
Public Instance Methods
Change the score for a member in the named leaderboard by a delta which can be positive or negative.
@param leaderboard_name [String] Name of the leaderboard. @param member [String] Member name. @param delta [float] Score change. @param member_data [String] Optional member data.
# File lib/tie_ranking_leaderboard.rb, line 54 def change_score_for_member_in(leaderboard_name, member, delta, member_data = nil) previous_score = score_for(member) new_score = (previous_score || 0) + delta total_members_at_previous_score = @redis_connection.zrevrangebyscore(leaderboard_name, previous_score, previous_score) @redis_connection.multi do |transaction| transaction.zadd(leaderboard_name, new_score, member) transaction.zadd(ties_leaderboard_key(leaderboard_name), new_score, new_score.to_f.to_s) transaction.hset(member_data_key(leaderboard_name), member, member_data) if member_data end if total_members_at_previous_score.length == 1 @redis_connection.zrem(ties_leaderboard_key(leaderboard_name), previous_score.to_f.to_s) end end
Delete the named leaderboard.
@param leaderboard_name [String] Name of the leaderboard.
# File lib/tie_ranking_leaderboard.rb, line 40 def delete_leaderboard_named(leaderboard_name) @redis_connection.multi do |transaction| transaction.del(leaderboard_name) transaction.del(member_data_key(leaderboard_name)) transaction.del(ties_leaderboard_key(leaderboard_name)) end end
Expire the given leaderboard at a specific UNIX timestamp. Do not use this with leaderboards that utilize member data as there is no facility to cascade the expiration out to the keys for the member data.
@param leaderboard_name [String] Name of the leaderboard. @param timestamp [int] UNIX timestamp at which the leaderboard will be expired.
# File lib/tie_ranking_leaderboard.rb, line 203 def expire_leaderboard_at_for(leaderboard_name, timestamp) @redis_connection.multi do |transaction| transaction.expireat(leaderboard_name, timestamp) transaction.expireat(ties_leaderboard_key(leaderboard_name), timestamp) transaction.expireat(member_data_key(leaderboard_name), timestamp) end end
Expire the given leaderboard in a set number of seconds. Do not use this with leaderboards that utilize member data as there is no facility to cascade the expiration out to the keys for the member data.
@param leaderboard_name [String] Name of the leaderboard. @param seconds [int] Number of seconds after which the leaderboard will be expired.
# File lib/tie_ranking_leaderboard.rb, line 189 def expire_leaderboard_for(leaderboard_name, seconds) @redis_connection.multi do |transaction| transaction.expire(leaderboard_name, seconds) transaction.expire(ties_leaderboard_key(leaderboard_name), seconds) transaction.expire(member_data_key(leaderboard_name), seconds) end end
Retrieve the rank for a member in the named leaderboard.
@param leaderboard_name [String] Name of the leaderboard. @param member [String] Member name.
@return the rank for a member in the leaderboard.
# File lib/tie_ranking_leaderboard.rb, line 138 def rank_for_in(leaderboard_name, member) member_score = score_for_in(leaderboard_name, member) if @reverse return @redis_connection.zrank(ties_leaderboard_key(leaderboard_name), member_score.to_f.to_s) + 1 rescue nil else return @redis_connection.zrevrank(ties_leaderboard_key(leaderboard_name), member_score.to_f.to_s) + 1 rescue nil end end
Rank a member across multiple leaderboards.
@param leaderboards [Array] Leaderboard
names. @param member [String] Member name. @param score [float] Member score. @param member_data [String] Optional member data.
# File lib/tie_ranking_leaderboard.rb, line 97 def rank_member_across(leaderboards, member, score, member_data = nil) leaderboards.each do |leaderboard_name| rank_member_in(leaderboard_name, member, score, member_data) end end
Rank a member in the named leaderboard.
@param leaderboard_name [String] Name of the leaderboard. @param member [String] Member name. @param score [float] Member score. @param member_data [String] Optional member data.
# File lib/tie_ranking_leaderboard.rb, line 77 def rank_member_in(leaderboard_name, member, score, member_data = nil) member_score = @redis_connection.zscore(leaderboard_name, member) || nil can_delete_score = member_score && members_from_score_range_in(leaderboard_name, member_score, member_score).length == 1 && member_score != score @redis_connection.multi do |transaction| transaction.zadd(leaderboard_name, score, member) transaction.zadd(ties_leaderboard_key(leaderboard_name), score, score.to_f.to_s) transaction.zrem(ties_leaderboard_key(leaderboard_name), member_score.to_f.to_s) if can_delete_score transaction.hset(member_data_key(leaderboard_name), member, member_data) if member_data end end
Rank an array of members in the named leaderboard.
@param leaderboard_name [String] Name of the leaderboard. @param members_and_scores [Splat or Array] Variable list of members and scores
# File lib/tie_ranking_leaderboard.rb, line 107 def rank_members_in(leaderboard_name, *members_and_scores) if members_and_scores.is_a?(Array) members_and_scores.flatten! end members_and_scores.each_slice(2) do |member_and_score| rank_member_in(leaderboard_name, member_and_score[0], member_and_score[1]) end end
Retrieve a page of leaders from the named leaderboard for a given list of members.
@param leaderboard_name [String] Name of the leaderboard. @param members [Array] Member names. @param options [Hash] Options to be used when retrieving the page from the named leaderboard.
@return a page of leaders from the named leaderboard for a given list of members.
# File lib/tie_ranking_leaderboard.rb, line 218 def ranked_in_list_in(leaderboard_name, members, options = {}) leaderboard_options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS.dup leaderboard_options.merge!(options) ranks_for_members = [] responses = @redis_connection.multi do |transaction| members.each do |member| if @reverse transaction.zrank(leaderboard_name, member) else transaction.zrevrank(leaderboard_name, member) end transaction.zscore(leaderboard_name, member) end end unless leaderboard_options[:members_only] members.each_with_index do |member, index| data = {} data[@member_key] = member unless leaderboard_options[:members_only] data[@score_key] = responses[index * 2 + 1].to_f if responses[index * 2 + 1] if @reverse data[@rank_key] = @redis_connection.zrank(ties_leaderboard_key(leaderboard_name), data[@score_key].to_s) + 1 rescue nil else data[@rank_key] = @redis_connection.zrevrank(ties_leaderboard_key(leaderboard_name), data[@score_key].to_s) + 1 rescue nil end if data[@rank_key] == nil next unless leaderboard_options[:include_missing] end end ranks_for_members << data end if leaderboard_options[:with_member_data] included_members = ranks_for_members.collect { |member| member[@member_key] } members_data_for_in(leaderboard_name, included_members).each_with_index do |member_data, index| ranks_for_members[index][@member_data_key] = member_data end end case leaderboard_options[:sort_by] when :rank ranks_for_members = ranks_for_members.sort_by { |member| member[@rank_key] } when :score ranks_for_members = ranks_for_members.sort_by { |member| member[@score_key] } end ranks_for_members end
Remove a member from the named leaderboard.
@param leaderboard_name [String] Name of the leaderboard. @param member [String] Member name.
# File lib/tie_ranking_leaderboard.rb, line 121 def remove_member_from(leaderboard_name, member) member_score = @redis_connection.zscore(leaderboard_name, member) || nil can_delete_score = member_score && members_from_score_range_in(leaderboard_name, member_score, member_score).length == 1 @redis_connection.multi do |transaction| transaction.zrem(leaderboard_name, member) transaction.zrem(ties_leaderboard_key(leaderboard_name), member_score.to_f.to_s) if can_delete_score transaction.hdel(member_data_key(leaderboard_name), member) end end
Remove members from the named leaderboard in a given score range.
@param leaderboard_name [String] Name of the leaderboard. @param min_score [float] Minimum score. @param max_score [float] Maximum score.
# File lib/tie_ranking_leaderboard.rb, line 176 def remove_members_in_score_range_in(leaderboard_name, min_score, max_score) @redis_connection.multi do |transaction| transaction.zremrangebyscore(leaderboard_name, min_score, max_score) transaction.zremrangebyscore(ties_leaderboard_key(leaderboard_name), min_score, max_score) end end
Retrieve the score and rank for a member in the named leaderboard.
@param leaderboard_name [String]Name of the leaderboard. @param member [String] Member name.
@return the score and rank for a member in the named leaderboard as a Hash.
# File lib/tie_ranking_leaderboard.rb, line 153 def score_and_rank_for_in(leaderboard_name, member) member_score = @redis_connection.zscore(leaderboard_name, member) responses = @redis_connection.multi do |transaction| transaction.zscore(leaderboard_name, member) if @reverse transaction.zrank(ties_leaderboard_key(leaderboard_name), member_score.to_f.to_s) else transaction.zrevrank(ties_leaderboard_key(leaderboard_name), member_score.to_f.to_s) end end responses[0] = responses[0].to_f if responses[0] responses[1] = responses[1] + 1 rescue nil {@member_key => member, @score_key => responses[0], @rank_key => responses[1]} end
Protected Instance Methods
Key for ties leaderboard.
@param leaderboard_name [String] Name of the leaderboard.
@return a key in the form of leaderboard_name:ties_namespace
# File lib/tie_ranking_leaderboard.rb, line 279 def ties_leaderboard_key(leaderboard_name) "#{leaderboard_name}:#{@ties_namespace}" end