Class: Leaderboard

Inherits:
Object
  • Object
show all
Defined in:
lib/leaderboard.rb,
lib/leaderboard/version.rb

Constant Summary collapse

DEFAULT_PAGE_SIZE =

Default page size: 25

25
DEFAULT_OPTIONS =

Default options when creating a leaderboard. Page size is 25 and reverse is set to false, meaning various methods will return results in highest-to-lowest order.

{
  :page_size => DEFAULT_PAGE_SIZE,
  :reverse => false
}
DEFAULT_REDIS_HOST =

Default Redis host: localhost

'localhost'
DEFAULT_REDIS_PORT =

Default Redis post: 6379

6379
DEFAULT_REDIS_OPTIONS =

Default Redis options when creating a connection to Redis. The DEFAULT_REDIS_HOST and DEFAULT_REDIS_PORT will be passed.

{
  :host => DEFAULT_REDIS_HOST,
  :port => DEFAULT_REDIS_PORT
}
DEFAULT_LEADERBOARD_REQUEST_OPTIONS =

Default options when requesting data from a leaderboard. :with_scores true: Return scores along with the member names. :with_rank true: Return ranks along with the member names. :with_member_data false: Return member data along with the member names. :use_zero_index_for_rank false: If you want to 0-index ranks. :page_size nil: The default page size will be used.

{
  :with_scores => true,
  :with_rank => true,
  :with_member_data => false,
  :use_zero_index_for_rank => false,
  :page_size => nil
}
VERSION =

Leaderboard version

'2.5.0'.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(leaderboard_name, options = DEFAULT_OPTIONS, redis_options = DEFAULT_REDIS_OPTIONS) ⇒ Leaderboard

Create a new instance of a leaderboard.

Examples

leaderboard = Leaderboard.new('highscores')
leaderboard = Leaderboard.new('highscores', {:page_size => 10})

Parameters:

  • leaderboard (String)

    Name of the leaderboard.

  • options (Hash) (defaults to: DEFAULT_OPTIONS)

    Options for the leaderboard such as :page_size.

  • redis_options (Hash) (defaults to: DEFAULT_REDIS_OPTIONS)

    Options for configuring Redis.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/leaderboard.rb', line 64

def initialize(leaderboard_name, options = DEFAULT_OPTIONS, redis_options = DEFAULT_REDIS_OPTIONS)
  @leaderboard_name = leaderboard_name

  @reverse   = options[:reverse]
  @page_size = options[:page_size]
  if @page_size.nil? || @page_size < 1
    @page_size = DEFAULT_PAGE_SIZE
  end

  @redis_connection = redis_options[:redis_connection]
  unless @redis_connection.nil?
    redis_options.delete(:redis_connection)
  end

  @redis_connection = Redis.new(redis_options) if @redis_connection.nil?
end

Instance Attribute Details

#leaderboard_nameObject (readonly)

Name of the leaderboard.



44
45
46
# File 'lib/leaderboard.rb', line 44

def leaderboard_name
  @leaderboard_name
end

#page_sizeObject

Page size to be used when paging through the leaderboard.



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

def page_size
  @page_size
end

#reverseObject

Determines whether or not various leaderboard methods return their data in highest-to-lowest (:reverse false) or lowest-to-highest (:reverse true)



52
53
54
# File 'lib/leaderboard.rb', line 52

def reverse
  @reverse
end

Instance Method Details

#all_leaders(options = {}) ⇒ Object Also known as: all_members

Retrieve all leaders from the leaderboard.

Parameters:

  • options (Hash) (defaults to: {})

    Options to be used when retrieving the leaders from the leaderboard.

Returns:

  • the leaders from the leaderboard.



584
585
586
# File 'lib/leaderboard.rb', line 584

def all_leaders(options = {})
  all_leaders_from(@leaderboard_name, options)
end

#all_leaders_from(leaderboard_name, options = {}) ⇒ Object Also known as: all_members_from

Retrieves all leaders from the named leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • options (Hash) (defaults to: {})

    Options to be used when retrieving the leaders from the named leaderboard.

Returns:

  • the named leaderboard.



596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
# File 'lib/leaderboard.rb', line 596

def all_leaders_from(leaderboard_name, options = {})
  leaderboard_options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS.dup
  leaderboard_options.merge!(options)

  if @reverse
    raw_leader_data = @redis_connection.zrange(leaderboard_name, 0, -1, :with_scores => false)
  else
    raw_leader_data = @redis_connection.zrevrange(leaderboard_name, 0, -1, :with_scores => false)
  end

  if raw_leader_data
    return ranked_in_list_in(leaderboard_name, raw_leader_data, leaderboard_options)
  else
    return []
  end
end

#around_me(member, options = {}) ⇒ Object

Retrieve a page of leaders from the leaderboard around a given member.

Parameters:

  • member (String)

    Member name.

  • options (Hash) (defaults to: {})

    Options to be used when retrieving the page from the leaderboard.

Returns:

  • a page of leaders from the leaderboard around a given member.



731
732
733
# File 'lib/leaderboard.rb', line 731

def around_me(member, options = {})
  around_me_in(@leaderboard_name, member, options)
end

#around_me_in(leaderboard_name, member, options = {}) ⇒ Object

Retrieve a page of leaders from the named leaderboard around a given member.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • member (String)

    Member name.

  • options (Hash) (defaults to: {})

    Options to be used when retrieving the page from the named leaderboard.

Returns:

  • a page of leaders from the named leaderboard around a given member. Returns an empty array for a non-existent member.



742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
# File 'lib/leaderboard.rb', line 742

def around_me_in(leaderboard_name, member, options = {})
  leaderboard_options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS.dup
  leaderboard_options.merge!(options)

  reverse_rank_for_member = @reverse ?
    @redis_connection.zrank(leaderboard_name, member) :
    @redis_connection.zrevrank(leaderboard_name, member)

  return [] unless reverse_rank_for_member

  page_size = validate_page_size(leaderboard_options[:page_size]) || @page_size

  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 = @reverse ?
    @redis_connection.zrange(leaderboard_name, starting_offset, ending_offset, :with_scores => false) :
    @redis_connection.zrevrange(leaderboard_name, starting_offset, ending_offset, :with_scores => false)

  if raw_leader_data
    return ranked_in_list_in(leaderboard_name, raw_leader_data, leaderboard_options)
  else
    return []
  end
end

#change_score_for(member, delta) ⇒ Object

Change the score for a member in the leaderboard by a score delta which can be positive or negative.

Parameters:

  • member (String)

    Member name.

  • delta (float)

    Score change.



286
287
288
# File 'lib/leaderboard.rb', line 286

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

Change the score for a member in the named leaderboard by a delta which can be positive or negative.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • member (String)

    Member name.

  • delta (float)

    Score change.



295
296
297
# File 'lib/leaderboard.rb', line 295

def change_score_for_member_in(leaderboard_name, member, delta)
  @redis_connection.zincrby(leaderboard_name, delta, member)
end

#check_member?(member) ⇒ Boolean

Check to see if a member exists in the leaderboard.

Parameters:

  • member (String)

    Member name.

Returns:

  • (Boolean)

    true if the member exists in the leaderboard, false otherwise.



356
357
358
# File 'lib/leaderboard.rb', line 356

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

#check_member_in?(leaderboard_name, member) ⇒ Boolean

Check to see if a member exists in the named leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • member (String)

    Member name.

Returns:

  • (Boolean)

    true if the member exists in the named leaderboard, false otherwise.



366
367
368
# File 'lib/leaderboard.rb', line 366

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

#delete_leaderboardObject

Delete the current leaderboard.



98
99
100
# File 'lib/leaderboard.rb', line 98

def delete_leaderboard
  delete_leaderboard_named(@leaderboard_name)
end

#delete_leaderboard_named(leaderboard_name) ⇒ Object

Delete the named leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.



105
106
107
# File 'lib/leaderboard.rb', line 105

def delete_leaderboard_named(leaderboard_name)
  @redis_connection.del(leaderboard_name)
end

#disconnectObject

Disconnect the Redis connection.



93
94
95
# File 'lib/leaderboard.rb', line 93

def disconnect
  @redis_connection.client.disconnect
end

#expire_leaderboard(seconds) ⇒ Object

Expire the current leaderboard in a set number of seconds. Do not use this with leaderboards that utilize member data as there is no facility to cascade the expiration out to the keys for the member data.

Parameters:

  • seconds (int)

    Number of seconds after which the leaderboard will be expired.



489
490
491
# File 'lib/leaderboard.rb', line 489

def expire_leaderboard(seconds)
  expire_leaderboard_for(@leaderboard_name, seconds)
end

#expire_leaderboard_at(timestamp) ⇒ Object

Expire the current leaderboard at a specific UNIX timestamp. Do not use this with leaderboards that utilize member data as there is no facility to cascade the expiration out to the keys for the member data.

Parameters:

  • timestamp (int)

    UNIX timestamp at which the leaderboard will be expired.



508
509
510
# File 'lib/leaderboard.rb', line 508

def expire_leaderboard_at(timestamp)
  expire_leaderboard_at_for(@leaderboard_name, timestamp)
end

#expire_leaderboard_at_for(leaderboard_name, timestamp) ⇒ Object

Expire the given leaderboard at a specific UNIX timestamp. Do not use this with leaderboards that utilize member data as there is no facility to cascade the expiration out to the keys for the member data.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • timestamp (int)

    UNIX timestamp at which the leaderboard will be expired.



518
519
520
# File 'lib/leaderboard.rb', line 518

def expire_leaderboard_at_for(leaderboard_name, timestamp)
  @redis_connection.expireat(leaderboard_name, timestamp)
end

#expire_leaderboard_for(leaderboard_name, seconds) ⇒ Object

Expire the given leaderboard in a set number of seconds. Do not use this with leaderboards that utilize member data as there is no facility to cascade the expiration out to the keys for the member data.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • seconds (int)

    Number of seconds after which the leaderboard will be expired.



499
500
501
# File 'lib/leaderboard.rb', line 499

def expire_leaderboard_for(leaderboard_name, seconds)
  @redis_connection.expire(leaderboard_name, seconds)
end

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

Intersect leaderboards given by keys with this leaderboard into a named destination leaderboard.

Parameters:

  • destination (String)

    Destination leaderboard name.

  • keys (Array)

    Leaderboards to be merged with the current leaderboard.

  • options (Hash) (defaults to: {:aggregate => :sum})

    Options for intersecting the leaderboards.



855
856
857
# File 'lib/leaderboard.rb', line 855

def intersect_leaderboards(destination, keys, options = {:aggregate => :sum})
  @redis_connection.zinterstore(destination, keys.insert(0, @leaderboard_name), options)
end

#leaders(current_page, options = {}) ⇒ Object Also known as: members

Retrieve a page of leaders from the leaderboard.

Parameters:

  • current_page (int)

    Page to retrieve from the leaderboard.

  • options (Hash) (defaults to: {})

    Options to be used when retrieving the page from the leaderboard.

Returns:

  • a page of leaders from the leaderboard.



528
529
530
# File 'lib/leaderboard.rb', line 528

def leaders(current_page, options = {})
  leaders_in(@leaderboard_name, current_page, options)
end

#leaders_in(leaderboard_name, current_page, options = {}) ⇒ Object Also known as: members_in

Retrieve a page of leaders from the named leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • current_page (int)

    Page to retrieve from the named leaderboard.

  • options (Hash) (defaults to: {})

    Options to be used when retrieving the page from the named leaderboard.

Returns:

  • a page of leaders from the named leaderboard.



541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
# File 'lib/leaderboard.rb', line 541

def leaders_in(leaderboard_name, current_page, options = {})
  leaderboard_options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS.dup
  leaderboard_options.merge!(options)

  if current_page < 1
    current_page = 1
  end

  page_size = validate_page_size(leaderboard_options[:page_size]) || @page_size

  if current_page > total_pages_in(leaderboard_name, page_size)
    current_page = total_pages_in(leaderboard_name, page_size)
  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

  if @reverse
    raw_leader_data = @redis_connection.zrange(leaderboard_name, starting_offset, ending_offset, :with_scores => false)
  else
    raw_leader_data = @redis_connection.zrevrange(leaderboard_name, starting_offset, ending_offset, :with_scores => false)
  end

  if raw_leader_data
    return ranked_in_list_in(leaderboard_name, raw_leader_data, leaderboard_options)
  else
    return []
  end
end

#member_at(position, options = {}) ⇒ Object

Retrieve a member at the specified index from the leaderboard.

Parameters:

  • position (int)

    Position in leaderboard.

  • options (Hash) (defaults to: {})

    Options to be used when retrieving the member from the leaderboard.

Returns:

  • a member from the leaderboard.



701
702
703
# File 'lib/leaderboard.rb', line 701

def member_at(position, options = {})
  member_at_in(@leaderboard_name, position, options)
end

#member_at_in(leaderboard_name, position, options = {}) ⇒ Object

Retrieve a member at the specified index from the leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • position (int)

    Position in named leaderboard.

  • options (Hash) (defaults to: {})

    Options to be used when retrieving the member from the named leaderboard.

Returns:

  • a page of leaders from the named leaderboard.



712
713
714
715
716
717
718
719
720
721
722
723
# File 'lib/leaderboard.rb', line 712

def member_at_in(leaderboard_name, position, options = {})
  if position <= total_members_in(leaderboard_name)
    leaderboard_options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS.dup
    leaderboard_options.merge!(options)
    page_size = validate_page_size(leaderboard_options[:page_size]) || @page_size
    current_page = (position.to_f / page_size.to_f).ceil
    offset = (position - 1) % page_size

    leaders = leaders_in(leaderboard_name, current_page, options)
    leaders[offset] if leaders
  end
end

#member_data_for(member) ⇒ Object

Retrieve the optional member data for a given member in the leaderboard.

Parameters:

  • member (String)

    Member name.

Returns:

  • Hash of optional member data.



138
139
140
# File 'lib/leaderboard.rb', line 138

def member_data_for(member)
  member_data_for_in(@leaderboard_name, member)
end

#member_data_for_in(leaderboard_name, member) ⇒ Object

Retrieve the optional member data for a given member in the named leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • member (String)

    Member name.

Returns:

  • Hash of optional member data.



148
149
150
# File 'lib/leaderboard.rb', line 148

def member_data_for_in(leaderboard_name, member)
  @redis_connection.hgetall(member_data_key(leaderboard_name, member))
end

#members_from_rank_range(starting_rank, ending_rank, options = {}) ⇒ Object

Retrieve members from the leaderboard within a given rank range.

Parameters:

  • starting_rank (int)

    Starting rank (inclusive).

  • ending_rank (int)

    Ending rank (inclusive).

  • options (Hash) (defaults to: {})

    Options to be used when retrieving the data from the leaderboard.

Returns:

  • members from the leaderboard that fall within the given rank range.



656
657
658
# File 'lib/leaderboard.rb', line 656

def members_from_rank_range(starting_rank, ending_rank, options = {})
  members_from_rank_range_in(@leaderboard_name, starting_rank, ending_rank, options)
end

#members_from_rank_range_in(leaderboard_name, starting_rank, ending_rank, options = {}) ⇒ Object

Retrieve members from the named leaderboard within a given rank range.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • starting_rank (int)

    Starting rank (inclusive).

  • ending_rank (int)

    Ending rank (inclusive).

  • options (Hash) (defaults to: {})

    Options to be used when retrieving the data from the leaderboard.

Returns:

  • members from the leaderboard that fall within the given rank range.



668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
# File 'lib/leaderboard.rb', line 668

def members_from_rank_range_in(leaderboard_name, starting_rank, ending_rank, options = {})
  leaderboard_options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS.dup
  leaderboard_options.merge!(options)

  starting_rank -= 1
  if starting_rank < 0
    starting_rank = 0
  end

  ending_rank -= 1
  if ending_rank > total_members_in(leaderboard_name)
    ending_rank = total_members_in(leaderboard_name) - 1
  end

  if @reverse
    raw_leader_data = @redis_connection.zrange(leaderboard_name, starting_rank, ending_rank, :with_scores => false)
  else
    raw_leader_data = @redis_connection.zrevrange(leaderboard_name, starting_rank, ending_rank, :with_scores => false)
  end

  if raw_leader_data
    return ranked_in_list_in(leaderboard_name, raw_leader_data, leaderboard_options)
  else
    return []
  end
end

#members_from_score_range(minimum_score, maximum_score, options = {}) ⇒ Object

Retrieve members from the leaderboard within a given score range.

Parameters:

  • minimum_score (float)

    Minimum score (inclusive).

  • maximum_score (float)

    Maximum score (inclusive).

  • options (Hash) (defaults to: {})

    Options to be used when retrieving the data from the leaderboard.

Returns:

  • members from the leaderboard that fall within the given score range.



622
623
624
# File 'lib/leaderboard.rb', line 622

def members_from_score_range(minimum_score, maximum_score, options = {})
  members_from_score_range_in(@leaderboard_name, minimum_score, maximum_score, options)
end

#members_from_score_range_in(leaderboard_name, minimum_score, maximum_score, options = {}) ⇒ Object

Retrieve members from the named leaderboard within a given score range.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • minimum_score (float)

    Minimum score (inclusive).

  • maximum_score (float)

    Maximum score (inclusive).

  • options (Hash) (defaults to: {})

    Options to be used when retrieving the data from the leaderboard.

Returns:

  • members from the leaderboard that fall within the given score range.



634
635
636
637
638
639
640
641
642
643
644
645
646
647
# File 'lib/leaderboard.rb', line 634

def members_from_score_range_in(leaderboard_name, minimum_score, maximum_score, options = {})
  leaderboard_options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS.dup
  leaderboard_options.merge!(options)

  raw_leader_data = @reverse ?
    @redis_connection.zrangebyscore(leaderboard_name, minimum_score, maximum_score) :
    @redis_connection.zrevrangebyscore(leaderboard_name, maximum_score, minimum_score)

  if raw_leader_data
    return ranked_in_list_in(leaderboard_name, raw_leader_data, leaderboard_options)
  else
    return []
  end
end

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

Merge leaderboards given by keys with this leaderboard into a named destination leaderboard.

Parameters:

  • destination (String)

    Destination leaderboard name.

  • keys (Array)

    Leaderboards to be merged with the current leaderboard.

  • options (Hash) (defaults to: {:aggregate => :sum})

    Options for merging the leaderboards.



846
847
848
# File 'lib/leaderboard.rb', line 846

def merge_leaderboards(destination, keys, options = {:aggregate => :sum})
  @redis_connection.zunionstore(destination, keys.insert(0, @leaderboard_name), options)
end

#page_for(member, page_size = DEFAULT_PAGE_SIZE) ⇒ Object

Determine the page where a member falls in the leaderboard.

Parameters:

  • member (String)

    Member name.

  • page_size (int) (defaults to: DEFAULT_PAGE_SIZE)

    Page size to be used in determining page location.

Returns:

  • the page where a member falls in the leaderboard.



459
460
461
# File 'lib/leaderboard.rb', line 459

def page_for(member, page_size = DEFAULT_PAGE_SIZE)
  page_for_in(@leaderboard_name, member, page_size)
end

#page_for_in(leaderboard_name, member, page_size = DEFAULT_PAGE_SIZE) ⇒ Object

Determine the page where a member falls in the named leaderboard.

Parameters:

  • leaderboard (String)

    Name of the leaderboard.

  • member (String)

    Member name.

  • page_size (int) (defaults to: DEFAULT_PAGE_SIZE)

    Page size to be used in determining page location.

Returns:

  • the page where a member falls in the leaderboard.



470
471
472
473
474
475
476
477
478
479
480
481
482
# File 'lib/leaderboard.rb', line 470

def page_for_in(leaderboard_name, member, page_size = DEFAULT_PAGE_SIZE)
  rank_for_member = @reverse ?
    @redis_connection.zrank(leaderboard_name, member) :
    @redis_connection.zrevrank(leaderboard_name, member)

  if rank_for_member.nil?
    rank_for_member = 0
  else
    rank_for_member += 1
  end

  (rank_for_member.to_f / page_size.to_f).ceil
end

#percentile_for(member) ⇒ Object

Retrieve the percentile for a member in the leaderboard.

Parameters:

  • member (String)

    Member name.

Returns:

  • the percentile for a member in the leaderboard. Return nil for a non-existent member.



427
428
429
# File 'lib/leaderboard.rb', line 427

def percentile_for(member)
  percentile_for_in(@leaderboard_name, member)
end

#percentile_for_in(leaderboard_name, member) ⇒ Object

Retrieve the percentile for a member in the named leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • member (String)

    Member name.

Returns:

  • the percentile for a member in the named leaderboard.



437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
# File 'lib/leaderboard.rb', line 437

def percentile_for_in(leaderboard_name, member)
  return nil unless check_member_in?(leaderboard_name, member)

  responses = @redis_connection.multi do |transaction|
    transaction.zcard(leaderboard_name)
    transaction.zrevrank(leaderboard_name, member)
  end

  percentile = ((responses[0] - responses[1] - 1).to_f / responses[0].to_f * 100).ceil
  if @reverse
    100 - percentile
  else
    percentile
  end
end

#rank_for(member, use_zero_index_for_rank = false) ⇒ Object

Retrieve the rank for a member in the leaderboard.

Parameters:

  • member (String)

    Member name.

  • use_zero_index_for_rank (boolean, false) (defaults to: false)

    If the returned rank should be 0-indexed.

Returns:

  • the rank for a member in the leaderboard.



305
306
307
# File 'lib/leaderboard.rb', line 305

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

Retrieve the rank for a member in the named leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • member (String)

    Member name.

  • use_zero_index_for_rank (boolean, false) (defaults to: false)

    If the returned rank should be 0-indexed.

Returns:

  • the rank for a member in the leaderboard.



316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/leaderboard.rb', line 316

def rank_for_in(leaderboard_name, member, use_zero_index_for_rank = false)
  if @reverse
    if use_zero_index_for_rank
      return @redis_connection.zrank(leaderboard_name, member)
    else
      return @redis_connection.zrank(leaderboard_name, member) + 1 rescue nil
    end
  else
    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
end

#rank_member(member, score, member_data = nil) ⇒ Object

Rank a member in the leaderboard.

Parameters:

  • member (String)

    Member name.

  • score (float)

    Member score.

  • member_data (Hash) (defaults to: nil)

    Optional member data.



114
115
116
# File 'lib/leaderboard.rb', line 114

def rank_member(member, score, member_data = nil)
  rank_member_in(@leaderboard_name, member, score, member_data)
end

#rank_member_in(leaderboard_name, member, score, member_data) ⇒ Object

Rank a member in the named leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • member (String)

    Member name.

  • score (float)

    Member score.

  • member_data (Hash)

    Optional member data.



124
125
126
127
128
129
130
131
# File 'lib/leaderboard.rb', line 124

def rank_member_in(leaderboard_name, member, score, member_data)
  @redis_connection.multi do |transaction|
    transaction.zadd(leaderboard_name, score, member)
    if member_data
      transaction.hmset(member_data_key(leaderboard_name, member), *member_data.to_a.flatten)
    end
  end
end

#rank_members(*members_and_scores) ⇒ Object

Rank an array of members in the leaderboard.

Parameters:

  • members_and_scores (Splat or Array)

    Variable list of members and scores



187
188
189
# File 'lib/leaderboard.rb', line 187

def rank_members(*members_and_scores)
  rank_members_in(@leaderboard_name, *members_and_scores)
end

#rank_members_in(leaderboard_name, *members_and_scores) ⇒ Object

Rank an array of members in the named leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • members_and_scores (Splat or Array)

    Variable list of members and scores



195
196
197
198
199
200
201
202
203
204
205
# File 'lib/leaderboard.rb', line 195

def rank_members_in(leaderboard_name, *members_and_scores)
  if members_and_scores.is_a?(Array)
    members_and_scores.flatten!
  end

  @redis_connection.multi do |transaction|
    members_and_scores.each_slice(2) do |member_and_score|
      transaction.zadd(leaderboard_name, member_and_score[1], member_and_score[0])
    end
  end
end

#ranked_in_list(members, options = {}) ⇒ Object

Retrieve a page of leaders from the leaderboard for a given list of members.

Parameters:

  • members (Array)

    Member names.

  • options (Hash) (defaults to: {})

    Options to be used when retrieving the page from the leaderboard.

Returns:

  • a page of leaders from the leaderboard for a given list of members.



778
779
780
# File 'lib/leaderboard.rb', line 778

def ranked_in_list(members, options = {})
  ranked_in_list_in(@leaderboard_name, members, options)
end

#ranked_in_list_in(leaderboard_name, members, options = {}) ⇒ Object

Retrieve a page of leaders from the named leaderboard for a given list of members.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • members (Array)

    Member names.

  • options (Hash) (defaults to: {})

    Options to be used when retrieving the page from the named leaderboard.

Returns:

  • a page of leaders from the named leaderboard for a given list of members.



789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
# File 'lib/leaderboard.rb', line 789

def ranked_in_list_in(leaderboard_name, members, options = {})
  leaderboard_options = DEFAULT_LEADERBOARD_REQUEST_OPTIONS.dup
  leaderboard_options.merge!(options)

  ranks_for_members = []

  responses = @redis_connection.multi do |transaction|
    members.each do |member|
      if @reverse
        transaction.zrank(leaderboard_name, member) if leaderboard_options[:with_rank]
      else
        transaction.zrevrank(leaderboard_name, member) if leaderboard_options[:with_rank]
      end
      transaction.zscore(leaderboard_name, member) if leaderboard_options[:with_scores]
    end
  end

  members.each_with_index do |member, index|
    data = {}
    data[:member] = member
    if leaderboard_options[:with_scores]
      if leaderboard_options[:with_rank]
        if leaderboard_options[:use_zero_index_for_rank]
          data[:rank] = responses[index * 2]
        else
          data[:rank] = responses[index * 2] + 1 rescue nil
        end

        data[:score] = responses[index * 2 + 1].to_f
      else
        data[:score] = responses[index].to_f
      end
    else
      if leaderboard_options[:with_rank]
        if leaderboard_options[:use_zero_index_for_rank]
          data[:rank] = responses[index]
        else
          data[:rank] = responses[index] + 1 rescue nil
        end
      end
    end

    if leaderboard_options[:with_member_data]
      data[:member_data] = member_data_for_in(leaderboard_name, member)
    end

    ranks_for_members << data
  end

  ranks_for_members
end

#remove_member(member) ⇒ Object

Remove a member from the leaderboard.

Parameters:

  • member (String)

    Member name.



210
211
212
# File 'lib/leaderboard.rb', line 210

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

#remove_member_data(member) ⇒ Object

Remove the optional member data for a given member in the leaderboard.

Parameters:

  • member (String)

    Member name.



172
173
174
# File 'lib/leaderboard.rb', line 172

def remove_member_data(member)
  remove_member_data_in(@leaderboard_name, member)
end

#remove_member_data_in(leaderboard_name, member) ⇒ Object

Remove the optional member data for a given member in the named leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • member (String)

    Member name.



180
181
182
# File 'lib/leaderboard.rb', line 180

def remove_member_data_in(leaderboard_name, member)
  @redis_connection.del(member_data_key(leaderboard_name, member))
end

#remove_member_from(leaderboard_name, member) ⇒ Object

Remove a member from the named leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • member (String)

    Member name.



218
219
220
221
222
223
# File 'lib/leaderboard.rb', line 218

def remove_member_from(leaderboard_name, member)
  @redis_connection.multi do |transaction|
    transaction.zrem(leaderboard_name, member)
    transaction.del(member_data_key(leaderboard_name, member))
  end
end

#remove_members_in_score_range(min_score, max_score) ⇒ Object

Remove members from the leaderboard in a given score range.

Parameters:

  • min_score (float)

    Minimum score.

  • max_score (float)

    Maximum score.



409
410
411
# File 'lib/leaderboard.rb', line 409

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

Remove members from the named leaderboard in a given score range.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • min_score (float)

    Minimum score.

  • max_score (float)

    Maximum score.



418
419
420
# File 'lib/leaderboard.rb', line 418

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

Retrieve the score and rank for a member in the leaderboard.

Parameters:

  • member (String)

    Member name.

  • use_zero_index_for_rank (boolean, false) (defaults to: false)

    If the returned rank should be 0-indexed.

Returns:

  • the score and rank for a member in the leaderboard as a Hash.



376
377
378
# File 'lib/leaderboard.rb', line 376

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

Retrieve the score and rank for a member in the named leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • member (String)

    Member name.

  • use_zero_index_for_rank (boolean, false) (defaults to: false)

    If the returned rank should be 0-indexed.

Returns:

  • the score and rank for a member in the named leaderboard as a Hash.



387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
# File 'lib/leaderboard.rb', line 387

def score_and_rank_for_in(leaderboard_name, member, use_zero_index_for_rank = false)
  responses = @redis_connection.multi do |transaction|
    transaction.zscore(leaderboard_name, member)
    if @reverse
      transaction.zrank(leaderboard_name, member)
    else
      transaction.zrevrank(leaderboard_name, member)
    end
  end

  responses[0] = responses[0].to_f
  if !use_zero_index_for_rank
    responses[1] = responses[1] + 1 rescue nil
  end

  {:member => member, :score => responses[0], :rank => responses[1]}
end

#score_for(member) ⇒ Object

Retrieve the score for a member in the leaderboard.

Parameters:

  • member

    Member name.

Returns:

  • the score for a member in the leaderboard.



337
338
339
# File 'lib/leaderboard.rb', line 337

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

#score_for_in(leaderboard_name, member) ⇒ Object

Retrieve the score for a member in the named leaderboard.

Parameters:

  • leaderboard_name

    Name of the leaderboard.

  • member (String)

    Member name.

Returns:

  • the score for a member in the leaderboard.



347
348
349
# File 'lib/leaderboard.rb', line 347

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

#total_membersObject

Retrieve the total number of members in the leaderboard.

Returns:

  • total number of members in the leaderboard.



228
229
230
# File 'lib/leaderboard.rb', line 228

def total_members
  total_members_in(@leaderboard_name)
end

#total_members_in(leaderboard_name) ⇒ Object

Retrieve the total number of members in the named leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

Returns:

  • the total number of members in the named leaderboard.



237
238
239
# File 'lib/leaderboard.rb', line 237

def total_members_in(leaderboard_name)
  @redis_connection.zcard(leaderboard_name)
end

#total_members_in_score_range(min_score, max_score) ⇒ Object

Retrieve the total members in a given score range from the leaderboard.

Parameters:

  • min_score (float)

    Minimum score.

  • max_score (float)

    Maximum score.

Returns:

  • the total members in a given score range from the leaderboard.



267
268
269
# File 'lib/leaderboard.rb', line 267

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

Retrieve the total members in a given score range from the named leaderboard.

Parameters:

  • leaderboard_name

    Name of the leaderboard.

  • min_score (float)

    Minimum score.

  • max_score (float)

    Maximum score.

Returns:

  • the total members in a given score range from the named leaderboard.



278
279
280
# File 'lib/leaderboard.rb', line 278

def total_members_in_score_range_in(leaderboard_name, min_score, max_score)
  @redis_connection.zcount(leaderboard_name, min_score, max_score)
end

#total_pages(page_size = nil) ⇒ Object

Retrieve the total number of pages in the leaderboard.

Parameters:

  • page_size (int, nil) (defaults to: nil)

    Page size to be used when calculating the total number of pages.

Returns:

  • the total number of pages in the leaderboard.



246
247
248
# File 'lib/leaderboard.rb', line 246

def total_pages(page_size = nil)
  total_pages_in(@leaderboard_name, page_size)
end

#total_pages_in(leaderboard_name, page_size = nil) ⇒ Object

Retrieve the total number of pages in the named leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • page_size (int, nil) (defaults to: nil)

    Page size to be used when calculating the total number of pages.

Returns:

  • the total number of pages in the named leaderboard.



256
257
258
259
# File 'lib/leaderboard.rb', line 256

def total_pages_in(leaderboard_name, page_size = nil)
  page_size ||= @page_size.to_f
  (total_members_in(leaderboard_name) / page_size.to_f).ceil
end

#update_member_data(member, member_data) ⇒ Object

Update the optional member data for a given member in the leaderboard.

Parameters:

  • member (String)

    Member name.

  • member_data (Hash)

    Optional member data.



156
157
158
# File 'lib/leaderboard.rb', line 156

def update_member_data(member, member_data)
  update_member_data_in(@leaderboard_name, member, member_data)
end

#update_member_data_in(leaderboard_name, member, member_data) ⇒ Object

Update the optional member data for a given member in the named leaderboard.

Parameters:

  • leaderboard_name (String)

    Name of the leaderboard.

  • member (String)

    Member name.

  • member_data (Hash)

    Optional member data.



165
166
167
# File 'lib/leaderboard.rb', line 165

def update_member_data_in(leaderboard_name, member, member_data)
  @redis_connection.hmset(member_data_key(leaderboard_name, member), *member_data.to_a.flatten)
end