Way to get ranking of a score #13

Closed
jgadbois opened this Issue Jun 11, 2012 · 16 comments

3 participants

@jgadbois

Is there a way that I could pass leaderboard a number and get back the rank that score would be at?

@czarneckid
Agora Games member

Not currently. There would be a range of ranks that a given score could refer to as members in the leaderboard can have the same score.

@jgadbois

That would be fine for my purposes. I don't see how to do that in Redis, though, without manually iterating through the results in the sorted sets. This would be a very useful feature for me, because on some pages I want to show how a user's score stacks up in terms of the leaderboard. Happy to help implement if you have any good ideas on how to do so.

@jletourneau

In theory I suppose to be guaranteed a unique answer, the question could be posed not as "what rank would a score of 12345 give me" but "how many items in the leaderboard currently rank ahead of the score 12345" (the answer could be 0 if that's higher than anything currently in the leaderboard).

@jgadbois

@jletourneau yes, I am actually doing that now in my current Postgres implementation.

rank = number of scores that are greater than my score + 1

@czarneckid
Agora Games member

@jgadbois Would the percentile_for(member) method work for you here?

@jgadbois

@czarneckid no, because I'm talking about a non-high score for a user (so it won't actually be in the sorted set)

@jgadbois jgadbois closed this Jun 11, 2012
@jgadbois jgadbois reopened this Jun 11, 2012
@jgadbois

sorry accidentally closed

@czarneckid
Agora Games member

You could look at zrangebyscore or zrevrangebyscore to get the members at a score and then grab the ranks for those members or maybe just the first member.

@czarneckid
Agora Games member

Not sure if this would do what you want, but check out the leaders-from-score-range branch. In particular, 858af9a.

leaders = highscore_lb.leaders_from_score_range(4, 19)
 => [{:member=>"member_10", :rank=>47, :score=>10.0}, {:member=>"member_9", :rank=>48, :score=>9.0}, {:member=>"member_8", :rank=>49, :score=>8.0}, {:member=>"member_7", :rank=>50, :score=>7.0}, {:member=>"member_6", :rank=>51, :score=>6.0}, {:member=>"member_5", :rank=>52, :score=>5.0}, {:member=>"member_4", :rank=>53, :score=>4.0}] 
@jgadbois

That would definitely get me close. Say particular score I was looking at was 17. I could grab leaders for some range of scores around that (say 7-27), manually filter down to see who was closest to 17, and grab their rank.

There would be an issue if no members were found within a certain range because I would have no ranks to compare against.

@czarneckid
Agora Games member

The only other seemingly applicable method here is total_members_in_score_range which uses the Redis sorted set command zcount to get the total # of elements within a score range. I guess you could have custom logic which centered around a given score, opened up the range slightly until finding some # of members > 0 and then grabbing the members from the given score range.

@jgadbois

Yeah that's kind of what I was thinking. I think if you added these functions, then I could do what I wanted to by writing the custom logic you describe.

@czarneckid
Agora Games member

Well, total_members_in_score_range is already available. I'll merge the leaders-from-score-range branch in next week. I want to make sure I've noodled on that for a bit.

@jgadbois

Ok, thanks!

@jgadbois jgadbois closed this Jun 12, 2012
@jgadbois

Would you be interested in having this algorithm inside of the leaderboard gem vs in my app logic?

@czarneckid
Agora Games member

I think a good compromise here would be a wiki page demonstrating that particular use-case. I believe you should be able to edit the main page in the wiki and go over the use-case and your code in a sub-page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment