canvas-lms/app/models/quiz_statistics.rb

116 lines
3.2 KiB
Ruby

#
# Copyright (C) 2013 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 QuizStatistics < ActiveRecord::Base
set_table_name :quiz_statistics
attr_accessible :includes_all_versions, :anonymous, :report_type
belongs_to :quiz
has_one :csv_attachment, :class_name => "Attachment", :as => 'context',
:dependent => :destroy
has_one :progress, :as => 'context', :dependent => :destroy
scope :report_type, lambda { |type| where(:report_type => type) }
REPORTS = %w[student_analysis item_analysis].freeze
validates_inclusion_of :report_type, :in => REPORTS
def report
@report ||= begin
report_class = case report_type.to_s
when 'item_analysis' then QuizStatistics::ItemAnalysis
when 'student_analysis' then QuizStatistics::StudentAnalysis
end
report_class.new(self)
end
end
def generate_csv
display_name = t(:statistics_filename, "%{quiz_title} %{quiz_type} %{report_type} Report",
:quiz_title => quiz.title,
:quiz_type => quiz.readable_type,
:report_type => readable_type
) + ".csv"
build_csv_attachment(:filename => "quiz_#{report_type}_report.csv",
:display_name => display_name,
:uploaded_data => StringIO.new(report.to_csv)
).tap { |a|
a.content_type = 'text/csv'
a.save!
complete_progress
}
end
def generate_csv_in_background
return if csv_attachment
start_progress
strand_id = Shard.birth.activate { quiz_id }
send_later_enqueue_args :generate_csv, :strand => "quiz_statistics_#{strand_id}"
end
def start_progress
return if progress
build_progress(:tag => self.class.name, :completion => 0)
progress.start
end
def update_progress(i, n)
# 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
def complete_progress
progress.complete
progress.save!
end
def readable_type
case report_type
when 'item_analysis' then t('types.item_analysis', 'Item Analysis')
when 'student_analysis' then t('types.student_analysis', 'Student Analysis')
end
end
set_policy do
given { |user, session| quiz.grants_right?(user, session, :read_statistics) }
can :read
end
class QuizStatistics::Report
extend Forwardable
def_delegators :quiz_statistics, :quiz, :includes_all_versions?, :anonymous?, :start_progress, :update_progress
attr_reader :quiz_statistics
def initialize(quiz_statistics)
@quiz_statistics = quiz_statistics
end
end
end