class ComputeAnalysisDataJob < ApplicationJob
  queue_as :default

  def perform
    @period = 3.months.ago
    @period_days = 90

    @jobs = Jobstat::Job.where("submit_time > ?", @period)
    @logins = @jobs.pluck(:login).uniq
    @projects = @logins.map { |login|
      member = Core::Member.find_by(login: login)
      member.blank? ? nil : member.project }.uniq

    @projects.delete(nil)

    perform_quantity_analysis
    perform_utilization_analysis
  end

  private
  def perform_quantity_analysis
    # Logins
    grouped_jobs = @jobs.group(:login).count
    sorted_jobs = grouped_jobs.sort_by(&:last)

    total = sorted_jobs.size
    q20 = sorted_jobs[(0.2 * total).round][1].to_f / @period_days
    q40 = sorted_jobs[(0.4 * total).round][1].to_f / @period_days
    q60 = sorted_jobs[(0.6 * total).round][1].to_f / @period_days
    q80 = sorted_jobs[(0.8 * total).round][1].to_f / @period_days

    AnalysisDatum.find_or_create_by(reference: "logins", analysis_type: "quantity").update(q20: q20, q40: q40, q60: q60, q80: q80)

    # Projects
    grouped_jobs = @jobs.group_by { |job|
      member = Core::Member.find_by(login: job.login)
      member.blank? ? nil : member.project
    }

    grouped_jobs.delete(nil)

    sorted_jobs = grouped_jobs.sort_by { |project, jobs| jobs.length }

    total = sorted_jobs.size
    q20 = sorted_jobs[(0.2 * total).round][1].length.to_f / @period_days
    q40 = sorted_jobs[(0.4 * total).round][1].length.to_f / @period_days
    q60 = sorted_jobs[(0.6 * total).round][1].length.to_f / @period_days
    q80 = sorted_jobs[(0.8 * total).round][1].length.to_f / @period_days

    AnalysisDatum.find_or_create_by(reference: "projects", analysis_type: "quantity").update(q20: q20, q40: q40, q60: q60, q80: q80)
  end

  def perform_utilization_analysis
    # Logins
    grouped_jobs = @jobs.group_by { |job| job.login }
    util = grouped_jobs.map { |k,v| v.map {|job| job.get_cpuh}.reduce(:+) }
    util = util.sort

    total = util.size
    q20 = util[(0.2 * total).round] / @period_days
    q40 = util[(0.4 * total).round] / @period_days
    q60 = util[(0.6 * total).round] / @period_days
    q80 = util[(0.8 * total).round] / @period_days

    AnalysisDatum.find_or_create_by(reference: "logins", analysis_type: "utilization").update(q20: q20, q40: q40, q60: q60, q80: q80)

    # Projects
    grouped_jobs = @jobs.group_by { |job|
      member = Core::Member.find_by(login: job.login)
      member.blank? ? nil : member.project
    }

    grouped_jobs.delete(nil)

    util = grouped_jobs.map { |k,v| v.map { |job| job.get_cpuh }.reduce(:+) }.sort

    total = util.size
    q20 = util[(0.2 * total).round] / @period_days
    q40 = util[(0.4 * total).round] / @period_days
    q60 = util[(0.6 * total).round] / @period_days
    q80 = util[(0.8 * total).round] / @period_days

    AnalysisDatum.find_or_create_by(reference: "projects", analysis_type: "utilization").update(q20: q20, q40: q40, q60: q60, q80: q80)
  end
end
