Website : rimsha.abasa.com
backdoor
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
var
/
canvas
/
app
/
models
/
quizzes
/
Filename :
quiz_statistics.rb
back
Copy
# frozen_string_literal: true # # Copyright (C) 2013 - present Instructure, Inc. # # This file is part of Canvas. # # Canvas is free software: you can redistribute it and/or modify it under # the terms of the GNU Affero General Public License as published by the Free # Software Foundation, version 3 of the License. # # Canvas is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Affero General Public License for more # details. # # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see <http://www.gnu.org/licenses/>. # class Quizzes::QuizStatistics < ActiveRecord::Base DefaultMaxQuestions = 100 DefaultMaxSubmissions = 1000 self.table_name = :quiz_statistics belongs_to :quiz, class_name: "Quizzes::Quiz" has_one :csv_attachment, class_name: "Attachment", as: "context", dependent: :destroy has_one :progress, as: "context", dependent: :destroy scope :report_type, ->(type) { where(report_type: type) } REPORTS = %w[student_analysis item_analysis].freeze validates :report_type, inclusion: { in: REPORTS } after_initialize do self.includes_all_versions ||= false self.includes_sis_ids ||= false end delegate :context, to: :quiz # Test a given quiz if it's within the sanity limits for generating stats. # You should not generate stats for this quiz if this returns true. # # Defaults for the limits are set in the constants in this module, but you # can configure them via the Setting interface using the console, or by # directly modifying the setting records in the database (note that you will # still have to restart your Canvas instance for the settings to take effect.) def self.large_quiz?(quiz) (quiz.active_quiz_questions.size > Setting.get("quiz_statistics_max_questions", DefaultMaxQuestions).to_i) || (quiz.quiz_submissions.size > Setting.get("quiz_statistics_max_submissions", DefaultMaxSubmissions).to_i) end def report report_klass = report_type.to_s.camelize @report ||= Quizzes::QuizStatistics.const_get(report_klass).new(self) end # Generates or returns the previously generated CSV version of this report. def generate_csv self.csv_attachment ||= begin attachment = build_csv_attachment( content_type: "text/csv", filename: "quiz_#{report_type}_report.csv", display_name: t("%{quiz_title} %{quiz_type} %{report_type} Report", { quiz_title: quiz.title, quiz_type: quiz.readable_type, report_type: readable_type }) + ".csv" ) Attachments::Storage.store_for_attachment(attachment, StringIO.new(report.to_csv)) attachment.save! attachment end end # Queues a job for generating the CSV version of this report unless a job has # already been queued, or the attachment had been generated previously. def generate_csv_in_background return if csv_attachment.present? || progress.present? build_progress progress.tag = self.class.name progress.completion = 0 progress.workflow_state = "queued" progress.save! progress.process_job(self, :__process_csv_job, { strand: csv_job_strand_id }) end def __process_csv_job(_progress) generate_csv end # Whether the CSV attachment is currently being generated, or is about to be. def generating_csv? progress.present? && progress.pending? end def csv_generation_abortable? progress.present? && (progress.queued? || csv_generation_failed?) end def csv_generation_failed? progress.present? && progress.failed? end def abort_csv_generation progress.destroy reload Delayed::Job.where({ strand: csv_job_strand_id }).destroy_all end def self.csv_job_tag "Quizzes::QuizStatistics#__process_csv_job" end def csv_job_strand_id Shard.birth.activate { "quiz_statistics_#{quiz_id}_#{id}" } end def update_progress(i, n) # the report generators will always attempt to update the progress as they # do their work, but we don't always track progress (e.g, non-async) so in # that case we just ignore the updates: return if progress.nil? # TODO: smarter updates? maybe 10 updates isn't enough for quizzes with # hundreds of submissions increment = 10 percent = (i.to_f / n * 100).round if (percent / increment) > (progress.completion / increment) progress.update_completion! percent end end delegate :readable_type, to: :report set_policy do given do |user, session| quiz.grants_right?(user, session, :read_statistics) && (!includes_sis_ids || quiz.context.grants_any_right?(user, session, :read_sis, :manage_sis)) end can :read given do |user, session| quiz.grants_right?(user, session, :read_statistics) && context.grants_any_right?(user, session, *RoleOverride::GRANULAR_FILE_PERMISSIONS) end can :manage_files end end