<commit_before>class Course < ApplicationRecord
  belongs_to :term

  has_many :sections, dependent: :destroy, inverse_of: :course
  has_many :registrations, dependent: :destroy
  has_many :users, through: :registrations

  has_many :reg_requests, dependent: :destroy

  has_many :assignments, dependent: :restrict_with_error
  has_many :submissions, through: :assignments
  has_many :teams,       dependent: :destroy
  has_many :teamsets, dependent: :destroy

  belongs_to :lateness_config

  validates :term_id, presence: true
  validates :lateness_config, presence: true
  validates :name, length: { minimum: 2 }, uniqueness: { scope: :term_id }
  validate  :has_sections

  accepts_nested_attributes_for :sections, allow_destroy: true
  accepts_nested_attributes_for :lateness_config

  after_create :register_profs

  def has_sections
    if sections.empty?
      errors.add(:sections, "can't be empty")
    end
  end

  def section_types
    self.sections.map(&:type).uniq.sort_by{|t| Section::types[t]}.map{|t| [t, Section::types[t]]}
  end

  def sections_by_type
    self.sections.group_by(&:type)
  end

  def register_profs
    # Can't do this before create, because self.id isn't set yet
    # Can't do this using just Registration.new and RegistrationSection.new, because
    # they aren't owned by anything owned by self, so they don't get saved
    if registrations.empty?
      sections.each do |sec|
        begin
          r = Registration.find_or_create_by(user_id: sec.instructor_id, course_id: self.id)
          r.role = "professor"
          r.show_in_lists = false
          r.new_sections = [sec.id]
          r.save!
        rescue Exception => e
          errors[:base] << "Could not register #{sec.instructor.name} for course: #{e}"
        end
        begin
          rs = RegistrationSection.create!(
            registration: r,
            section: sec
          )
        rescue Exception => e
          errors[:base] << "Could not register #{sec.instructor.name} for section #{sec.id}: #{e}"
        end
      end
    end
    raise ActiveRecord::Rollback if errors[:base].count > 0
  end

  def registered_by?(user, as: nil)
    return false if user.nil?
    registration = Registration.find_by(course_id: self.id, user_id: user.id)
    return false if registration.nil?
    if as
      as == registration.role
    else
      registration.role == 'assistant' || registration.role == 'professor'
    end
  end

  def active_registrations
    registrations.where(show_in_lists: true).joins(:user).order("users.last_name", "users.first_name")
  end

  def active_teams
    self.teams.where(Team.active_query, Date.current, Date.current)
  end

  def students
    users.where("registrations.role": Registration::roles["student"])
  end

  def students_with_registrations
    students.joins("JOIN registration_sections ON registrations.id = registration_sections.registration_id")
      .joins("JOIN sections ON registration_sections.section_id = sections.id")
  end

  def users_with_drop_info(for_users = nil)
    look_for = users
    if for_users.is_a? Array
      look_for = look_for.where(id: for_users.map(&:id))
    elsif for_users.is_a? User
      look_for = look_for.where(id: for_users.id)
    elsif for_users
      look_for = look_for.where(id: for_users.pluck(:id))
    end
    look_for.select("users.*", "registrations.dropped_date as dropped_date", "registrations.id as reg_id")
  end

  def students_with_drop_info
    users_with_drop_info(students)
  end

  def professors
    users.where("registrations.role": Registration::roles["professor"])
  end

  def graders
    users.where("registrations.role": Registration::roles["grader"])
  end

  def staff
    users
      .where("registrations.role <> #{Registrations::roles["student"]}")
      .where("registrations.dropped_date is null")
  end

  def sorted_staff
    staff.select("users.*", "registrations.role as role")
      .sort_by{|s| [0 - s.role, s.sort_name]}
  end

  def first_professor
    professors.first
  end

  def assignments_sorted
    self.assignments.to_a.sort_by(&:due_date)
  end

  def all_partners
    team_users = TeamUser.where(team: teams).group_by(&:team_id)
    users_teams = teams.map do |t|
      team_users[t.id].map do |tu|
        [tu.user_id, t.id]
      end
    end.flatten(1).group_by(&:first).map{|k,v| [k,v.map(&:last)]}.to_h
    users_teams.map do |uid, tids|
      [uid, tids.map do |tid|
         team_users[tid].map{|tu| [tu.user_id, tid]}
       end.flatten(1).group_by(&:first).map{|k,v| [k,v.map(&:last)]}.to_h]
    end.to_h
  end<commit_msg>damn, typo<commit_after>class Course < ApplicationRecord
  belongs_to :term

  has_many :sections, dependent: :destroy, inverse_of: :course
  has_many :registrations, dependent: :destroy
  has_many :users, through: :registrations

  has_many :reg_requests, dependent: :destroy

  has_many :assignments, dependent: :restrict_with_error
  has_many :submissions, through: :assignments
  has_many :teams,       dependent: :destroy
  has_many :teamsets, dependent: :destroy

  belongs_to :lateness_config

  validates :term_id, presence: true
  validates :lateness_config, presence: true
  validates :name, length: { minimum: 2 }, uniqueness: { scope: :term_id }
  validate  :has_sections

  accepts_nested_attributes_for :sections, allow_destroy: true
  accepts_nested_attributes_for :lateness_config

  after_create :register_profs

  def has_sections
    if sections.empty?
      errors.add(:sections, "can't be empty")
    end
  end

  def section_types
    self.sections.map(&:type).uniq.sort_by{|t| Section::types[t]}.map{|t| [t, Section::types[t]]}
  end

  def sections_by_type
    self.sections.group_by(&:type)
  end

  def register_profs
    # Can't do this before create, because self.id isn't set yet
    # Can't do this using just Registration.new and RegistrationSection.new, because
    # they aren't owned by anything owned by self, so they don't get saved
    if registrations.empty?
      sections.each do |sec|
        begin
          r = Registration.find_or_create_by(user_id: sec.instructor_id, course_id: self.id)
          r.role = "professor"
          r.show_in_lists = false
          r.new_sections = [sec.id]
          r.save!
        rescue Exception => e
          errors[:base] << "Could not register #{sec.instructor.name} for course: #{e}"
        end
        begin
          rs = RegistrationSection.create!(
            registration: r,
            section: sec
          )
        rescue Exception => e
          errors[:base] << "Could not register #{sec.instructor.name} for section #{sec.id}: #{e}"
        end
      end
    end
    raise ActiveRecord::Rollback if errors[:base].count > 0
  end

  def registered_by?(user, as: nil)
    return false if user.nil?
    registration = Registration.find_by(course_id: self.id, user_id: user.id)
    return false if registration.nil?
    if as
      as == registration.role
    else
      registration.role == 'assistant' || registration.role == 'professor'
    end
  end

  def active_registrations
    registrations.where(show_in_lists: true).joins(:user).order("users.last_name", "users.first_name")
  end

  def active_teams
    self.teams.where(Team.active_query, Date.current, Date.current)
  end

  def students
    users.where("registrations.role": Registration::roles["student"])
  end

  def students_with_registrations
    students.joins("JOIN registration_sections ON registrations.id = registration_sections.registration_id")
      .joins("JOIN sections ON registration_sections.section_id = sections.id")
  end

  def users_with_drop_info(for_users = nil)
    look_for = users
    if for_users.is_a? Array
      look_for = look_for.where(id: for_users.map(&:id))
    elsif for_users.is_a? User
      look_for = look_for.where(id: for_users.id)
    elsif for_users
      look_for = look_for.where(id: for_users.pluck(:id))
    end
    look_for.select("users.*", "registrations.dropped_date as dropped_date", "registrations.id as reg_id")
  end

  def students_with_drop_info
    users_with_drop_info(students)
  end

  def professors
    users.where("registrations.role": Registration::roles["professor"])
  end

  def graders
    users.where("registrations.role": Registration::roles["grader"])
  end

  def staff
    users
      .where("registrations.role <> #{Registration::roles["student"]}")
      .where("registrations.dropped_date is null")
  end

  def sorted_staff
    staff.select("users.*", "registrations.role as role")
      .sort_by{|s| [0 - s.role, s.sort_name]}
  end

  def first_professor
    professors.first
  end

  def assignments_sorted
    self.assignments.to_a.sort_by(&:due_date)
  end

  def all_partners
    team_users = TeamUser.where(team: teams).group_by(&:team_id)
    users_teams = teams.map do |t|
      team_users[t.id].map do |tu|
        [tu.user_id, t.id]
      end
    end.flatten(1).group_by(&:first).map{|k,v| [k,v.map(&:last)]}.to_h
    users_teams.map do |uid, tids|
      [uid, tids.map do |tid|
         team_users[tid].map{|tu| [tu.user_id, tid]}
       end.flatten(1).group_by(&:first).map{|k,v| [k,v.map(&:last)]}.to_h]
    end.to_h
  end
{'fraction_non_alphanumeric': 0.11274830822964418, 'fraction_numerical': 0.0010914647456887142, 'mean_word_length': 3.3550380228136882, 'pattern_counts': {'":': 6, '<': 15, '<?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': '3264740', 'n_tokens_mistral': 3105, 'n_tokens_neox': 3007, 'n_words': 686}