igrigorik/vimgolf

View on GitHub
app/services/submissions_per_user.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
98%
require_relative '../repositories/repository_challenge'
require_relative './solution'

class SubmissionsPerUser

  def initialize(current_user, challenge_id, player)
    # @current_user is the logged in user, while @player is the user about
    # which this per-challenge page is being shown.
    #
    # Note that this is different from Submission, in which @player refers
    # to the current logged in user.
    @current_user = current_user
    @challenge_id = challenge_id
    @player = player
  end
  attr_reader :challenge_id
  attr_reader :player

  def each
    each_unfiltered do |s|
      if visible_score && s.score >= visible_score
        yield s
      end
    end
  end

  def each_unfiltered
    # Adjust entries from the query. The position in the ranking from the first
    # entry is correct, but the other entries are not actually in the ranking
    # (only the best answer for each user is.)
    #
    # So, instead, we adjust it to show after which entry in the ranking it would
    # have been, had the user not had a better entry than that one.
    #
    # To differentiate it visually, we display it as #>n instead of #n. For
    # example, #>15 instead of #15 if your entry would come right after the one
    # in position 15.
    #
    # `each_unfiltered` is used to list all scores of the user (where the
    # Leaderboard normally is), while `each` is used to display the solutions
    # that should be visible, assuming the logged in user has an entry with
    # score low enough to allow displaying them.
    adjust = 0
    submissions.each do |s|
      position = s['position'] - adjust
      if adjust > 0
        position = ">#{position}"
      end
      yield Solution.new(s, users, position)
      adjust += 1
    end
  end

  def empty?
    submissions.none?
  end

  def users
    @users ||= {player.id => player}
  end

  def submissions
    @submissions ||= Challenge.find_by_urlkey(@challenge_id).player_entries(player.id)
  end

  def visible_score
    return @visible_score if defined?(@visible_score)

    if !@current_user
      @visible_score = nil
    elsif @current_user.admin? || creator?
      @visible_score = 0
    else
      # Player's score for this challenge, or nil if player hasn't
      # made any submissions for this one.
      @visible_score = RepositoryChallenge.best_player_score(@challenge_id, @current_user.id)
    end
  end

  def user_id
    @user_id ||= Challenge.find_by_urlkey(@challenge_id).user_id
  end

  def highlight_owner?
    false
  end

  def creator?
    user_id == @current_user.id
  end

  def player_can_edit?(_)
    false
  end
  alias :player_can_delete? :player_can_edit?

  def count_uniq_users
    RepositoryChallenge.count_uniq_users(@challenge_id)
  end

  def count_remaining
    result = 0
    each_unfiltered do |s|
      if !(visible_score && s.score >= visible_score)
        result += 1
      end
    end
    result
  end

end