<commit_before>class Participant < ActiveRecord::Base
  include Auditable
  include Concealable
  include PersonalInfo
  include Searchable
  include SetOperations
  include Matchable
  strip_attributes collapse_spaces: true
  enum gender: [:male, :female]
  has_many :connections, dependent: :destroy
  has_many :followers, through: :connections, source: :user
  has_many :efforts
  belongs_to :claimant, class_name: 'User', foreign_key: 'user_id'

  attr_accessor :suggested_match

  scope :with_age_and_effort_count, -> { select(SQL[:age_and_effort_count]).joins(:efforts => :event).group(:id) }
  scope :ordered_by_name, -> { order(:last_name, :first_name) }

  SQL = {age_and_effort_count: 'participants.*, COUNT(efforts.id) as effort_count, ROUND(AVG((extract(epoch from(current_date - events.start_time))/60/60/24/365.25) + efforts.age)) as participant_age',
         ages_from_events: '((extract(epoch from(current_date - events.start_time))/60/60/24/365.25) + efforts.age)'}

  validates_presence_of :first_name, :last_name, :gender
  validates :email, allow_blank: true, length: {maximum: 105},
            uniqueness: {case_sensitive: false},
            format: {with: VALID_EMAIL_REGEX}

  def self.search(param)
    return none if param.blank? || (param.length < 3)
    flexible_search(param)
  end

  def self.age_matches(age_param)
    return none unless age_param.is_a?(Numeric)
    threshold = 2 # Allow for some inaccuracy in reporting, rounding errors, etc.
    age_hash = approximate_ages_today.merge(exact_ages_today)
                   .reject { |_, age| (age - age_param).abs > threshold }
    self.where(id: age_hash.keys)
  end<commit_msg>Fix bug in Participant::with_age_and_effort_count.<commit_after>class Participant < ActiveRecord::Base
  include Auditable
  include Concealable
  include PersonalInfo
  include Searchable
  include SetOperations
  include Matchable
  strip_attributes collapse_spaces: true
  enum gender: [:male, :female]
  has_many :connections, dependent: :destroy
  has_many :followers, through: :connections, source: :user
  has_many :efforts
  belongs_to :claimant, class_name: 'User', foreign_key: 'user_id'

  attr_accessor :suggested_match

  scope :with_age_and_effort_count, -> { select(SQL[:age_and_effort_count]).joins(:efforts => :event).group('participants.id') }
  scope :ordered_by_name, -> { order(:last_name, :first_name) }

  SQL = {age_and_effort_count: 'participants.*, COUNT(efforts.id) as effort_count, ROUND(AVG((extract(epoch from(current_date - events.start_time))/60/60/24/365.25) + efforts.age)) as participant_age',
         ages_from_events: '((extract(epoch from(current_date - events.start_time))/60/60/24/365.25) + efforts.age)'}

  validates_presence_of :first_name, :last_name, :gender
  validates :email, allow_blank: true, length: {maximum: 105},
            uniqueness: {case_sensitive: false},
            format: {with: VALID_EMAIL_REGEX}

  def self.search(param)
    return none if param.blank? || (param.length < 3)
    flexible_search(param)
  end

  def self.age_matches(age_param)
    return none unless age_param.is_a?(Numeric)
    threshold = 2 # Allow for some inaccuracy in reporting, rounding errors, etc.
    age_hash = approximate_ages_today.merge(exact_ages_today)
                   .reject { |_, age| (age - age_param).abs > threshold }
    self.where(id: age_hash.keys)
  end
{'fraction_non_alphanumeric': 0.11328009464655428, 'fraction_numerical': 0.015971606033717833, 'mean_word_length': 4.526143790849673, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, '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': '740068', 'n_tokens_mistral': 1174, 'n_tokens_neox': 1102, 'n_words': 244}