<commit_before>class Assignment < ActiveRecord::Base
  require 'ftools'
  include DynamicReviewMapping

  belongs_to :course
  belongs_to :wiki_type
  # wiki_type needs to be removed. When an assignment is created, it needs to
  # be created as an instance of a subclass of the Assignment (model) class;
  # then Rails will "automatically" set the type field to the value that
  # designates an assignment of the appropriate type.
  has_many :participants, :class_name => 'AssignmentParticipant', :foreign_key => 'parent_id'
  has_many :participant_review_mappings, :class_name => 'ParticipantReviewResponseMap', :through => :participants, :source => :review_mappings
  has_many :users, :through => :participants
  has_many :due_dates
  has_many :teams, :class_name => 'AssignmentTeam', :foreign_key => 'parent_id'
  has_many :team_review_mappings, :class_name => 'TeamReviewResponseMap', :through => :teams, :source => :review_mappings
  has_many :invitations, :class_name => 'Invitation', :foreign_key => 'assignment_id'
  has_many :assignment_questionnaires, :class_name => 'AssignmentQuestionnaires', :foreign_key => 'assignment_id'
  has_many :questionnaires, :through => :assignment_questionnaires
  belongs_to  :instructor, :class_name => 'User', :foreign_key => 'instructor_id'    
  has_many :sign_up_topics, :foreign_key => 'assignment_id', :dependent => :destroy  

  validates_presence_of :name
  validates_uniqueness_of :scope => [:directory_path, :instructor_id]

  COMPLETE = "Complete"

  #  Review Strategy information.
  RS_INSTRUCTOR_SELECTED = 'Instructor-Selected'
  RS_STUDENT_SELECTED    = 'Student-Selected'
  RS_AUTO_SELECTED       = 'Auto-Selected'
  REVIEW_STRATEGIES = [RS_INSTRUCTOR_SELECTED, RS_STUDENT_SELECTED, RS_AUTO_SELECTED]

  DEFAULT_MAX_REVIEWERS = 3

  # Returns a set of topics that can be reviewed.
  # We choose the topics if one of its submissions has received the fewest reviews so far
  def candidate_topics_to_review
    return nil if sign_up_topics.empty?   # This is not a topic assignment
    
    contributor_set = Array.new(contributors)
    
    # Reject contributors that have not selected a topic, or have no submissions
    contributor_set.reject! { |contributor| contributor.topic.nil? or !contributor.has_submissions? }
    
    # Filter the contributors with the least number of reviews
    # (using the fact that each contributor is associated with a topic)
    contributor = contributor_set.min_by { |contributor| contributor.review_mappings.count }
    min_reviews = contributor.review_mappings.count
    contributor_set.reject! { |contributor| contributor.review_mappings.count > min_reviews + review_topic_threshold }
    
    candidate_topics = Set.new
    contributor_set.each { |contributor| candidate_topics.add(contributor.topic) }
    
    candidate_topics<commit_msg>Reject topics whose deadline has already passed<commit_after>class Assignment < ActiveRecord::Base
  require 'ftools'
  include DynamicReviewMapping

  belongs_to :course
  belongs_to :wiki_type
  # wiki_type needs to be removed. When an assignment is created, it needs to
  # be created as an instance of a subclass of the Assignment (model) class;
  # then Rails will "automatically" set the type field to the value that
  # designates an assignment of the appropriate type.
  has_many :participants, :class_name => 'AssignmentParticipant', :foreign_key => 'parent_id'
  has_many :participant_review_mappings, :class_name => 'ParticipantReviewResponseMap', :through => :participants, :source => :review_mappings
  has_many :users, :through => :participants
  has_many :due_dates
  has_many :teams, :class_name => 'AssignmentTeam', :foreign_key => 'parent_id'
  has_many :team_review_mappings, :class_name => 'TeamReviewResponseMap', :through => :teams, :source => :review_mappings
  has_many :invitations, :class_name => 'Invitation', :foreign_key => 'assignment_id'
  has_many :assignment_questionnaires, :class_name => 'AssignmentQuestionnaires', :foreign_key => 'assignment_id'
  has_many :questionnaires, :through => :assignment_questionnaires
  belongs_to  :instructor, :class_name => 'User', :foreign_key => 'instructor_id'    
  has_many :sign_up_topics, :foreign_key => 'assignment_id', :dependent => :destroy  

  validates_presence_of :name
  validates_uniqueness_of :scope => [:directory_path, :instructor_id]

  COMPLETE = "Complete"

  #  Review Strategy information.
  RS_INSTRUCTOR_SELECTED = 'Instructor-Selected'
  RS_STUDENT_SELECTED    = 'Student-Selected'
  RS_AUTO_SELECTED       = 'Auto-Selected'
  REVIEW_STRATEGIES = [RS_INSTRUCTOR_SELECTED, RS_STUDENT_SELECTED, RS_AUTO_SELECTED]

  DEFAULT_MAX_REVIEWERS = 3

  # Returns a set of topics that can be reviewed.
  # We choose the topics if one of its submissions has received the fewest reviews so far
  def candidate_topics_to_review
    return nil if sign_up_topics.empty?   # This is not a topic assignment
    
    contributor_set = Array.new(contributors)
    
    # Reject contributors that have not selected a topic, or have no submissions
    contributor_set.reject! { |contributor| contributor.topic.nil? or !contributor.has_submissions? }
    
    # Reject contributions of topics whose deadline is passed
    contributor_set.reject! { |contributor| contributor.assignment.get_current_stage(contributor.topic.id) == "Complete" or
                                            contributor.assignment.get_current_stage(contributor.topic.id) == "submission" }
    
    # Filter the contributors with the least number of reviews
    # (using the fact that each contributor is associated with a topic)
    contributor = contributor_set.min_by { |contributor| contributor.review_mappings.count }
    min_reviews = contributor.review_mappings.count
    contributor_set.reject! { |contributor| contributor.review_mappings.count > min_reviews + review_topic_threshold }
    
    candidate_topics = Set.new
    contributor_set.each { |contributor| candidate_topics.add(contributor.topic) }
    
    candidate_topics
{'fraction_non_alphanumeric': 0.08347162296714239, 'fraction_numerical': 0.00033189512114171923, 'mean_word_length': 4.823188405797102, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1647022', 'n_tokens_mistral': 1854, 'n_tokens_neox': 1805, 'n_words': 488}