The Blog
Meta Leaderboards
Traditionally, leaderboards rank players using one criteria, e.g. XP, kills, etc. What if you wanted to retrieve information from a leaderboard that combined more than one criteria? I’m going to show you how to do that.
To be honest, I don’t necessarily have a definite use case for this functionality, but I thought it might be useful. So, here goes nothing.
Let’s say you’ve got a game and its multiplayer mode can be played across 5 maps. We’ll also simplify things and say that we’re only ranking players on each map on XP gained when finishing the map. If you want to generate a leaderboard of players ranked by XP who have played in any of the maps, you would need to perform a merge of each of the leaderboards for the 5 maps. If you want to generate a leaderboard of players ranked by XP who have played in each of the maps, you would need to perform an intersection of each of the leaderboards for the 5 maps.
This functionality is now present in the Ruby leaderboard gem released today.
You can use the merge_leaderboards(…) call to merge the current leaderboard with any other leaderboards into a new leaderboard.
ruby-1.8.7-p302 > map_1_xp_lb = Leaderboard.new('map_1_xp') => #<Leaderboard:0x1018d96e8 @leaderboard_name="map_1_xp", @page_size=25, @port=6379, @redis_connection=#<Redis client v2.1.1 connected to redis://localhost:6379/0 (Redis v2.0.3)>, @host="localhost", @redis_options={:host=>"localhost", :port=>6379}> ruby-1.8.7-p302 > map_2_xp_lb = Leaderboard.new('map_2_xp') => #<Leaderboard:0x1018d3568 @leaderboard_name="map_2_xp", @page_size=25, @port=6379, @redis_connection=#<Redis client v2.1.1 connected to redis://localhost:6379/0 (Redis v2.0.3)>, @host="localhost", @redis_options={:host=>"localhost", :port=>6379}> ruby-1.8.7-p302 > map_3_xp_lb = Leaderboard.new('map_3_xp') => #<Leaderboard:0x1018cd460 @leaderboard_name="map_3_xp", @page_size=25, @port=6379, @redis_connection=#<Redis client v2.1.1 connected to redis://localhost:6379/0 (Redis v2.0.3)>, @host="localhost", @redis_options={:host=>"localhost", :port=>6379}> ruby-1.8.7-p302 > map_4_xp_lb = Leaderboard.new('map_4_xp') => #<Leaderboard:0x1018c7358 @leaderboard_name="map_4_xp", @page_size=25, @port=6379, @redis_connection=#<Redis client v2.1.1 connected to redis://localhost:6379/0 (Redis v2.0.3)>, @host="localhost", @redis_options={:host=>"localhost", :port=>6379}> ruby-1.8.7-p302 > map_5_xp_lb = Leaderboard.new('map_5_xp') => #<Leaderboard:0x1018c1250 @leaderboard_name="map_5_xp", @page_size=25, @port=6379, @redis_connection=#<Redis client v2.1.1 connected to redis://localhost:6379/0 (Redis v2.0.3)>, @host="localhost", @redis_options={:host=>"localhost", :port=>6379}> ruby-1.8.7-p302 > map_1_xp_lb.add_member('member_1', 10) => true ruby-1.8.7-p302 > map_2_xp_lb.add_member('member_2', 7) => true ruby-1.8.7-p302 > map_3_xp_lb.add_member('member_3', 7) => true ruby-1.8.7-p302 > map_4_xp_lb.add_member('member_4', 22) => true ruby-1.8.7-p302 > map_5_xp_lb.add_member('member_5', 3) => true ruby-1.8.7-p302 > map_1_xp_lb.merge_leaderboards('all_maps_xp_lb', ['map_2_xp', 'map_3_xp', 'map_4_xp', 'map_5_xp']) => 5 ruby-1.8.7-p302 > all_maps_xp_lb = Leaderboard.new('all_maps_xp_lb') => #<Leaderboard:0x101883040 @leaderboard_name="all_maps_xp_lb", @page_size=25, @port=6379, @redis_connection=#<Redis client v2.1.1 connected to redis://localhost:6379/0 (Redis v2.0.3)>, @host="localhost", @redis_options={:host=>"localhost", :port=>6379}> ruby-1.8.7-p302 > all_maps_xp_lb.total_members => 5 ruby-1.8.7-p302 > all_maps_xp_lb.leaders(1) => [{:rank=>1, :member=>"member_4", :score=>22.0}, {:rank=>2, :member=>"member_1", :score=>10.0}, {:rank=>3, :member=>"member_3", :score=>7.0}, {:rank=>4, :member=>"member_2", :score=>7.0}, {:rank=>5, :member=>"member_5", :score=>3.0}]
You can use the intersect_leaderboards(…) call to intersect the current leaderboard with any other leaderboards into a new leaderboard.
ruby-1.8.7-p302 > map_1_xp_lb = Leaderboard.new('map_1_xp') => #<Leaderboard:0x1018d96e8 @leaderboard_name="map_1_xp", @page_size=25, @port=6379, @redis_connection=#<Redis client v2.1.1 connected to redis://localhost:6379/0 (Redis v2.0.3)>, @host="localhost", @redis_options={:host=>"localhost", :port=>6379}> ruby-1.8.7-p302 > map_2_xp_lb = Leaderboard.new('map_2_xp') => #<Leaderboard:0x1018d34f0 @leaderboard_name="map_2_xp", @page_size=25, @port=6379, @redis_connection=#<Redis client v2.1.1 connected to redis://localhost:6379/0 (Redis v2.0.3)>, @host="localhost", @redis_options={:host=>"localhost", :port=>6379}> ruby-1.8.7-p302 > map_3_xp_lb = Leaderboard.new('map_3_xp') => #<Leaderboard:0x1018cd370 @leaderboard_name="map_3_xp", @page_size=25, @port=6379, @redis_connection=#<Redis client v2.1.1 connected to redis://localhost:6379/0 (Redis v2.0.3)>, @host="localhost", @redis_options={:host=>"localhost", :port=>6379}> ruby-1.8.7-p302 > map_4_xp_lb = Leaderboard.new('map_4_xp') => #<Leaderboard:0x1018c71f0 @leaderboard_name="map_4_xp", @page_size=25, @port=6379, @redis_connection=#<Redis client v2.1.1 connected to redis://localhost:6379/0 (Redis v2.0.3)>, @host="localhost", @redis_options={:host=>"localhost", :port=>6379}> ruby-1.8.7-p302 > map_5_xp_lb = Leaderboard.new('map_5_xp') => #<Leaderboard:0x1018c1070 @leaderboard_name="map_5_xp", @page_size=25, @port=6379, @redis_connection=#<Redis client v2.1.1 connected to redis://localhost:6379/0 (Redis v2.0.3)>, @host="localhost", @redis_options={:host=>"localhost", :port=>6379}> ruby-1.8.7-p302 > map_1_xp_lb.add_member('member_1', 10) => false ruby-1.8.7-p302 > map_1_xp_lb.add_member('member_2', 19) => true ruby-1.8.7-p302 > map_2_xp_lb.add_member('member_2', 7) => false ruby-1.8.7-p302 > map_3_xp_lb.add_member('member_3', 7) => false ruby-1.8.7-p302 > map_3_xp_lb.add_member('member_4', 17) => true ruby-1.8.7-p302 > map_4_xp_lb.add_member('member_4', 22) => false ruby-1.8.7-p302 > map_4_xp_lb.add_member('member_5', 2) => true ruby-1.8.7-p302 > map_5_xp_lb.add_member('member_5', 3) => false ruby-1.8.7-p302 > map_5_xp_lb.add_member('member_1', 13) => true ruby-1.8.7-p302 > map_1_xp_lb.merge_leaderboards('intersect_maps_xp_lb', ['map_2_xp', 'map_3_xp', 'map_4_xp', 'map_5_xp']) => 5 ruby-1.8.7-p302 > intersect_maps_xp_lb = Leaderboard.new('intersect_maps_xp_lb') => #<Leaderboard:0x10188a890 @leaderboard_name="intersect_maps_xp_lb", @page_size=25, @port=6379, @redis_connection=#<Redis client v2.1.1 connected to redis://localhost:6379/0 (Redis v2.0.3)>, @host="localhost", @redis_options={:host=>"localhost", :port=>6379}> ruby-1.8.7-p302 > intersect_maps_xp_lb.total_members => 5 ruby-1.8.7-p302 > intersect_maps_xp_lb.leaders(1) => [{:rank=>1, :member=>"member_4", :score=>39.0}, {:rank=>2, :member=>"member_2", :score=>26.0}, {:rank=>3, :member=>"member_1", :score=>23.0}, {:rank=>4, :member=>"member_3", :score=>7.0}, {:rank=>5, :member=>"member_5", :score=>5.0}]
Hopefully you’ll find this functionality useful.
You can find more hilarity over on my Twitter account, CzarneckiD.






