Class: Leaderboard

Inherits:
Object
  • Object
show all
Defined in:
lib/leaderboard.rb

Constant Summary collapse

VERSION =
'1.0.1'.freeze
DEFAULT_PAGE_SIZE =
25
DEFAULT_REDIS_HOST =
'localhost'
DEFAULT_REDIS_PORT =
6379

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(leaderboard_name, host = DEFAULT_REDIS_HOST, port = DEFAULT_REDIS_PORT, page_size = DEFAULT_PAGE_SIZE, redis_options = {}) ⇒ Leaderboard

Returns a new instance of Leaderboard.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/leaderboard.rb', line 15

def initialize(leaderboard_name, host = DEFAULT_REDIS_HOST, port = DEFAULT_REDIS_PORT, page_size = DEFAULT_PAGE_SIZE, redis_options = {})
  @leaderboard_name = leaderboard_name
  @host = host
  @port = port
  
  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

Instance Attribute Details

#hostObject (readonly)

Returns the value of attribute host.



10
11
12
# File 'lib/leaderboard.rb', line 10

def host
  @host
end

#leaderboard_nameObject (readonly)

Returns the value of attribute leaderboard_name.



12
13
14
# File 'lib/leaderboard.rb', line 12

def leaderboard_name
  @leaderboard_name
end

#page_sizeObject

Returns the value of attribute page_size.



13
14
15
# File 'lib/leaderboard.rb', line 13

def page_size
  @page_size
end

#portObject (readonly)

Returns the value of attribute port.



11
12
13
# File 'lib/leaderboard.rb', line 11

def port
  @port
end

Instance Method Details

#add_member(member, score) ⇒ Object



35
36
37
# File 'lib/leaderboard.rb', line 35

def add_member(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) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/leaderboard.rb', line 109

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)
  
  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(raw_leader_data, with_rank, use_zero_index_for_rank)
  else
    return nil
  end
end

#change_score_for(member, delta) ⇒ Object



55
56
57
# File 'lib/leaderboard.rb', line 55

def change_score_for(member, delta)
  @redis_connection.zincrby(@leaderboard_name, delta, member)
end

#check_member?(member) ⇒ Boolean

Returns:

  • (Boolean)


71
72
73
# File 'lib/leaderboard.rb', line 71

def check_member?(member)
  !@redis_connection.zscore(@leaderboard_name, member).nil?
end

#leaders(current_page, with_scores = true, with_rank = true, use_zero_index_for_rank = false) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/leaderboard.rb', line 83

def leaders(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(raw_leader_data, with_rank, use_zero_index_for_rank)
  else
    return nil
  end
end

#rank_for(member, use_zero_index_for_rank = false) ⇒ Object



59
60
61
62
63
64
65
# File 'lib/leaderboard.rb', line 59

def rank_for(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) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/leaderboard.rb', line 127

def ranked_in_list(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
    
    ranks_for_members << data
  end
  
  ranks_for_members
end

#remove_member(member) ⇒ Object



39
40
41
# File 'lib/leaderboard.rb', line 39

def remove_member(member)
  @redis_connection.zrem(@leaderboard_name, member)
end

#remove_members_in_score_range(min_score, max_score) ⇒ Object



79
80
81
# File 'lib/leaderboard.rb', line 79

def remove_members_in_score_range(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) ⇒ Object



75
76
77
# File 'lib/leaderboard.rb', line 75

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)}    
end

#score_for(member) ⇒ Object



67
68
69
# File 'lib/leaderboard.rb', line 67

def score_for(member)
  @redis_connection.zscore(@leaderboard_name, member).to_f
end

#total_membersObject



43
44
45
# File 'lib/leaderboard.rb', line 43

def total_members
  @redis_connection.zcard(@leaderboard_name)
end

#total_members_in_score_range(min_score, max_score) ⇒ Object



51
52
53
# File 'lib/leaderboard.rb', line 51

def total_members_in_score_range(min_score, max_score)
  @redis_connection.zcount(@leaderboard_name, min_score, max_score)
end

#total_pagesObject



47
48
49
# File 'lib/leaderboard.rb', line 47

def total_pages
  (total_members / @page_size.to_f).ceil
end