<commit_before>require 'searchkick'
class User < ActiveRecord::Base
  searchkick text_start: [:username]
  include Authority::UserAbilities
  include CroppableAvatar
  include Authority::Abilities
  self.authorizer_name = 'UserAuthorizer'

  after_create :registration_badges
  after_create :send_signup_email

  before_update :send_email_if_username_was_changed
  before_update :send_email_if_email_was_changed

  has_many :predictions, inverse_of: :user, :dependent => :destroy
  has_many :challenges, inverse_of: :user, :dependent => :destroy
  has_many :badges, :dependent => :destroy
  has_many :voted_predictions, through: :challenges, class_name: "Prediction", source: 'prediction'
  has_many :apple_device_tokens, :dependent => :destroy
  has_many :android_device_tokens, :dependent => :destroy
  has_many :comments, :dependent => :destroy
  has_many :activities, :dependent => :destroy
  has_many :memberships
  has_many :groups, through: :memberships
  has_many :invitations
  has_many :referrals
  has_many :social_accounts
  has_many :user_events

  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :token_authenticatable, :omniauthable,
         :authentication_keys => [:login]

  validates_presence_of   :username
  validates_uniqueness_of :username, :case_sensitive => false
  validates_format_of     :username, :with => /\A[a-zA-Z0-9_]{1,15}\z/

  attr_accessor :login

  def self.username_length
    return 15
  end

  def self.find_first_by_auth_conditions(warden_conditions)
    conditions = warden_conditions.dup
    if login = conditions.delete(:login)
      where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
    else
      where(conditions).first
    end
  end

  def won
    r = self.challenges.select { |c| c.is_finished == true and c.is_right == true}
    r.length
  end

  def lost
    r = self.challenges.select { |c| c.is_finished == true and c.is_right == false}
    r.length
  end

  def winning_percentage
    if self.won > 0
      (self.won.to_f / (self.won + self.lost) * 100.0).round(2)
    else
      0.00
    end
  end

  def update_streak(won)
    if won
      self.streak = (self.streak > 0) ? self.streak+1 : +1
    else
      self.streak = (self.streak < 0) ? self.streak-1 : -1
    end
  end

  def registration_badges
    case self.id
      when 1..500
        self.badges.create(:name => 'gold_founding')
      when 501..5000
        self.badges.create(:name => 'silver_founding')
    end
  end

  def prediction_create_badges
    case self.predictions.size
      when 1
        self.badges.create(:name => '1_prediction')
      when 10
        self.badges.create(:name => '10_predictions')
    end
  end

  def challenge_create_badges
    case self.challenges.where(is_own: false).count
      when 1
        self.badges.create(:name => '1_challenge')
    end
  end

  def outcome_badges
    # 10 correct predictions badge
    correct_predictions = self.predictions.where(outcome: true).count
    correct_badge = self.badges.where(name: '10_correct_predictions').first

    if correct_badge
      if correct_predictions < 10
        correct_badge.delete
      end
    else
      if correct_predictions > 9
        self.badges.create(name: '10_correct_predictions')
      end
    end

    # 10 incorrect predictions badge
    incorrect_predictions = self.predictions.where(outcome: false).count
    incorrect_badge = self.badges.where(name: '10_incorrect_predictions').first
    if incorrect_badge
      if incorrect_predictions < 10
        incorrect_badge.delete
      end
    else
      if incorrect_predictions > 9
        self.badges.create(name: '10_incorrect_predictions')
      end
    end
  end

  def pick(prediction, agree)
    self.challenges.build({
      prediction: prediction,
      agree: agree
    })
  end

  def alerts_count
    self.activities.unseen.count
  end

  def send_signup_email
    SignupMailer.signup(self).deliver
  end

  def send_email_if_username_was_changed
    if self.username_changed?
      UserMailer.username_was_changed(self).deliver
    end
  end

  def send_email_if_email_was_changed
    if self.email_changed?
      UserMailer.email_was_changed(self).deliver
    end
  end

  def search_data
    {
      username: username,
      points: points
    }
  end

  def streak_as_text<commit_msg>Adding guestmode support to users<commit_after>require 'searchkick'
class User < ActiveRecord::Base
  searchkick text_start: [:username]
  include Authority::UserAbilities
  include CroppableAvatar
  include Authority::Abilities
  self.authorizer_name = 'UserAuthorizer'

  after_create :registration_badges
  after_create :send_signup_email

  before_update :send_email_if_username_was_changed
  before_update :send_email_if_email_was_changed

  has_many :predictions, inverse_of: :user, :dependent => :destroy
  has_many :challenges, inverse_of: :user, :dependent => :destroy
  has_many :badges, :dependent => :destroy
  has_many :voted_predictions, through: :challenges, class_name: "Prediction", source: 'prediction'
  has_many :apple_device_tokens, :dependent => :destroy
  has_many :android_device_tokens, :dependent => :destroy
  has_many :comments, :dependent => :destroy
  has_many :activities, :dependent => :destroy
  has_many :memberships
  has_many :groups, through: :memberships
  has_many :invitations
  has_many :referrals
  has_many :social_accounts
  has_many :user_events

  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :token_authenticatable, :omniauthable,
         :authentication_keys => [:login]

  validates_presence_of   :username
  validates_uniqueness_of :username, :case_sensitive => false
  validates_format_of     :username, :with => /\A[a-zA-Z0-9_]{1,15}\z/

  attr_accessor :login

  def self.username_length
    return 15
  end

  def self.find_first_by_auth_conditions(warden_conditions)
    conditions = warden_conditions.dup
    if login = conditions.delete(:login)
      where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
    else
      where(conditions).first
    end
  end

  def won
    r = self.challenges.select { |c| c.is_finished == true and c.is_right == true}
    r.length
  end

  def lost
    r = self.challenges.select { |c| c.is_finished == true and c.is_right == false}
    r.length
  end

  def winning_percentage
    if self.won > 0
      (self.won.to_f / (self.won + self.lost) * 100.0).round(2)
    else
      0.00
    end
  end

  def update_streak(won)
    if won
      self.streak = (self.streak > 0) ? self.streak+1 : +1
    else
      self.streak = (self.streak < 0) ? self.streak-1 : -1
    end
  end

  def registration_badges
    case self.id
      when 1..500
        self.badges.create(:name => 'gold_founding')
      when 501..5000
        self.badges.create(:name => 'silver_founding')
    end
  end

  def prediction_create_badges
    case self.predictions.size
      when 1
        self.badges.create(:name => '1_prediction')
      when 10
        self.badges.create(:name => '10_predictions')
    end
  end

  def challenge_create_badges
    case self.challenges.where(is_own: false).count
      when 1
        self.badges.create(:name => '1_challenge')
    end
  end

  def outcome_badges
    # 10 correct predictions badge
    correct_predictions = self.predictions.where(outcome: true).count
    correct_badge = self.badges.where(name: '10_correct_predictions').first

    if correct_badge
      if correct_predictions < 10
        correct_badge.delete
      end
    else
      if correct_predictions > 9
        self.badges.create(name: '10_correct_predictions')
      end
    end

    # 10 incorrect predictions badge
    incorrect_predictions = self.predictions.where(outcome: false).count
    incorrect_badge = self.badges.where(name: '10_incorrect_predictions').first
    if incorrect_badge
      if incorrect_predictions < 10
        incorrect_badge.delete
      end
    else
      if incorrect_predictions > 9
        self.badges.create(name: '10_incorrect_predictions')
      end
    end
  end

  def pick(prediction, agree)
    self.challenges.build({
      prediction: prediction,
      agree: agree
    })
  end

  def alerts_count
    self.activities.unseen.count
  end

  def send_signup_email
    if self.email
      SignupMailer.signup(self).deliver
    end
  end

  def send_email_if_username_was_changed
    if self.username_changed?
      UserMailer.username_was_changed(self).deliver
    end
  end

  def send_email_if_email_was_changed
    if self.email_changed?
      UserMailer.email_was_changed(self).deliver
    end
  end

  def search_data
    {
      username: username,
      points: points
    }
  end

  def streak_as_text
{'fraction_non_alphanumeric': 0.08925457715780297, 'fraction_numerical': 0.012859633827375762, 'mean_word_length': 3.30239099859353, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '463894', 'n_tokens_mistral': 3134, 'n_tokens_neox': 2950, 'n_words': 654}