Class: Leaderboard

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

Constant Summary collapse

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

Instance Attribute Summary collapse

Class Method 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.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 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

Instance Attribute Details

#leaderboard_nameObject (readonly)

Returns the value of attribute leaderboard_name.



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

def leaderboard_name
  @leaderboard_name
end

#page_sizeObject

Returns the value of attribute page_size.



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

def page_size
  @page_size
end

Class Method Details

.redis_connectionObject



215
216
217
# File 'lib/multi-leaderboard.rb', line 215

def redis_connection
  @@redis_connection
end

.redis_connection=(redis) ⇒ Object



211
212
213
# File 'lib/multi-leaderboard.rb', line 211

def redis_connection=(redis)
  @@redis_connection = redis
end

Instance Method Details

#add_member(member, score) ⇒ Object



31
32
33
# 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) ⇒ Object



35
36
37
# 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) ⇒ Object



153
154
155
# 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) ⇒ Object



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# 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) ⇒ Object



71
72
73
# 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) ⇒ Object



75
76
77
# 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) ⇒ Boolean

Returns:

  • (Boolean)


99
100
101
# File 'lib/multi-leaderboard.rb', line 99

def check_member?(member)
  check_member_in?(@leaderboard_name, member)
end

#check_member_in?(leaderboard_name, member) ⇒ Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/multi-leaderboard.rb', line 103

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

#disconnectObject

Disconnect from the redis server



205
206
207
# File 'lib/multi-leaderboard.rb', line 205

def disconnect
  @@redis_connection.client.disconnect
end

#intersect_leaderboards(destination, keys, options = {:aggregate => :sum}) ⇒ Object

Intersect leaderboards given by keys with this leaderboard into destination



200
201
202
# 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) ⇒ Object



123
124
125
# 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) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# 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}) ⇒ Object

Merge leaderboards given by keys with this leaderboard into destination



195
196
197
# 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) ⇒ Object



79
80
81
# 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) ⇒ Object



83
84
85
86
87
88
89
# 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) ⇒ Object



175
176
177
# 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) ⇒ Object



179
180
181
182
183
184
185
186
187
188
189
190
191
192
# 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) ⇒ Object



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

def remove_member(member)
  remove_member_from(@leaderboard_name, member)
end

#remove_member_from(leaderboard_name, member) ⇒ Object



43
44
45
# 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) ⇒ Object



115
116
117
# 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) ⇒ Object



119
120
121
# 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) ⇒ Object



107
108
109
# 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) ⇒ Object



111
112
113
# 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) ⇒ Object



91
92
93
# File 'lib/multi-leaderboard.rb', line 91

def score_for(member)
  score_for_in(@leaderboard_name, member)
end

#score_for_in(leaderboard_name, member) ⇒ Object



95
96
97
# File 'lib/multi-leaderboard.rb', line 95

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

#total_membersObject



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

def total_members
  total_members_in(@leaderboard_name)
end

#total_members_in(leaderboard_name) ⇒ Object



51
52
53
# 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) ⇒ Object



63
64
65
# 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) ⇒ Object



67
68
69
# 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_pagesObject



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

def total_pages
  total_pages_in(@leaderboard_name)
end

#total_pages_in(leaderboard_name) ⇒ Object



59
60
61
# File 'lib/multi-leaderboard.rb', line 59

def total_pages_in(leaderboard_name)
  (total_members_in(leaderboard_name) / @page_size.to_f).ceil
end