This class makes it easier to generate a leaderboard that complies with the Standard Competition Ranking system. That is, it takes joint/tied positions into account, and adjusts the positions accordingly.
Take the following list of users and points for example:
User | Points
1 35
2 35
3 50
4 10
5 35
You might be contented with a leaderboard like this:
User | Points | Position
3 50 1
2 35 2
1 35 3
5 35 4
4 10 5
Users 2, 1 and 5 all have the same points, so what makes user 2 come second, and user 5 come fourth? That can't be right!
What you really need is this:
User | Points | Position
3 50 1
2 35 2
1 35 2
5 35 2
4 10 5
Which you can do with the code in this gist!
ranking_data = {...} # hash representation of above user/points table
leaderboard = StandardCompetitionRankings.new(ranking_data, :rank_by => :points, :sort_direction => :desc)
better_leaderboard = leaderboard.calculate
If you don't want any sorting applied because you want to roll your own or whatever, set the :sort_direction
parameter to nil
or false
.
After all that, it will append a field called position
to your dataset, which contains your now standardised rankings, and return the whole thing. :)
I'm trying to figure out the best way to extend this class a little to assign appropriate "points" based on standings.
For example, let's say I'm ranking 5 things and the positions come out as 1, 1, 3, 3, and 5. And points are assigned by position as 10, 8, 6, 4, 2.
When there's a tie for 1st, the points for 1st and 2nd should be summed and distributed among the ties. In this case, the resulting points would be:
9, 9, 5, 5, 2.
Any thoughts?