Skip to content

Commit

Permalink
More pipelining as per Ruby leaderboard library, agoragames/leaderboa…
Browse files Browse the repository at this point in the history
  • Loading branch information
David Czarnecki committed Sep 16, 2016
1 parent e88666b commit 7cfbc72
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 32 deletions.
53 changes: 33 additions & 20 deletions leaderboard/competition_ranking_leaderboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def ranked_in_list_in(self, leaderboard_name, members, **options):
@return a page of leaders from the named leaderboard for a given list of members.
'''
ranks_for_members = []
scores = []

pipeline = self.redis_connection.pipeline()

Expand All @@ -102,28 +103,15 @@ def ranked_in_list_in(self, leaderboard_name, members, **options):

data[self.SCORE_KEY] = score

if self.order == self.ASC:
try:
data[self.RANK_KEY] = self.redis_connection.zcount(
leaderboard_name, '-inf', "(%s" % str(float(data[self.SCORE_KEY])))
except:
data[self.RANK_KEY] = None
else:
try:
data[self.RANK_KEY] = self.redis_connection.zcount(
leaderboard_name, "(%s" % str(float(data[self.SCORE_KEY])), '+inf')
except:
data[self.RANK_KEY] = None
if data[self.RANK_KEY] is not None:
data[self.RANK_KEY] += 1
ranks_for_members.append(data)
scores.append(data[self.SCORE_KEY])

if ('with_member_data' in options) and (True == options['with_member_data']):
data[
self.MEMBER_DATA_KEY] = self.member_data_for_in(
leaderboard_name,
member)
for index, rank in enumerate(self.__rankings_for_members_having_scores_in(leaderboard_name, members, scores)):
ranks_for_members[index][self.RANK_KEY] = rank

ranks_for_members.append(data)
if ('with_member_data' in options) and (True == options['with_member_data']):
for index, member_data in enumerate(self.members_data_for_in(leaderboard_name, members)):
ranks_for_members[index][self.MEMBER_DATA_KEY] = member_data

if 'sort_by' in options:
if self.RANK_KEY == options['sort_by']:
Expand All @@ -138,3 +126,28 @@ def ranked_in_list_in(self, leaderboard_name, members, **options):
self.SCORE_KEY])

return ranks_for_members

def __up_rank(self, rank):
if rank is not None:
return rank + 1
else:
return None

def __rankings_for_members_having_scores_in(self, leaderboard_name, members, scores):
pipeline = self.redis_connection.pipeline()

for index, member in enumerate(members):
if self.order == self.ASC:
try:
pipeline.zcount(leaderboard_name, '-inf', "(%s" % str(float(scores[index])))
except:
None
else:
try:
pipeline.zcount(leaderboard_name, "(%s" % str(float(scores[index])), '+inf')
except:
None

responses = pipeline.execute()

return [self.__up_rank(response) for response in responses]
10 changes: 4 additions & 6 deletions leaderboard/leaderboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -1051,14 +1051,12 @@ def ranked_in_list_in(self, leaderboard_name, members, **options):
score = float(score)
data[self.SCORE_KEY] = score

if ('with_member_data' in options) and (True == options['with_member_data']):
data[
self.MEMBER_DATA_KEY] = self.member_data_for_in(
leaderboard_name,
member)

ranks_for_members.append(data)

if ('with_member_data' in options) and (True == options['with_member_data']):
for index, member_data in enumerate(self.members_data_for_in(leaderboard_name, members)):
ranks_for_members[index][self.MEMBER_DATA_KEY] = member_data

if 'sort_by' in options:
if self.RANK_KEY == options['sort_by']:
ranks_for_members = sorted(
Expand Down
10 changes: 4 additions & 6 deletions leaderboard/tie_ranking_leaderboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,14 +271,12 @@ def ranked_in_list_in(self, leaderboard_name, members, **options):
if not options.get('include_missing', True):
continue

if ('with_member_data' in options) and (True == options['with_member_data']):
data[
self.MEMBER_DATA_KEY] = self.member_data_for_in(
leaderboard_name,
member)

ranks_for_members.append(data)

if ('with_member_data' in options) and (True == options['with_member_data']):
for index, member_data in enumerate(self.members_data_for_in(leaderboard_name, members)):
ranks_for_members[index][self.MEMBER_DATA_KEY] = member_data

if 'sort_by' in options:
if self.RANK_KEY == options['sort_by']:
ranks_for_members = sorted(
Expand Down
19 changes: 19 additions & 0 deletions test/leaderboard/competition_ranking_leaderboard_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@ def test_leaders(self):
leaders[3]['rank'].should.equal(3)
leaders[4]['rank'].should.equal(5)

def test_leaders_with_optional_member_data(self):
self.leaderboard.rank_member('member_1', 50)
self.leaderboard.rank_member('member_2', 50)
self.leaderboard.rank_member('member_3', 30)
self.leaderboard.rank_member('member_4', 30)
self.leaderboard.rank_member('member_5', 10, 'member_5')

leaders = self.leaderboard.leaders(1, with_member_data=True)
leaders[0]['rank'].should.equal(1)
leaders[0]['member_data'].should.equal(None)
leaders[1]['rank'].should.equal(1)
leaders[1]['member_data'].should.equal(None)
leaders[2]['rank'].should.equal(3)
leaders[2]['member_data'].should.equal(None)
leaders[3]['rank'].should.equal(3)
leaders[3]['member_data'].should.equal(None)
leaders[4]['rank'].should.equal(5)
leaders[4]['member_data'].should.equal('member_5')

def test_correct_rankings_for_leaders_with_different_page_sizes(self):
self.leaderboard.rank_member('member_1', 50)
self.leaderboard.rank_member('member_2', 50)
Expand Down

0 comments on commit 7cfbc72

Please sign in to comment.