75 lines
2.7 KiB
Ruby
75 lines
2.7 KiB
Ruby
#
|
|
# Copyright (C) 2011 - 2014 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 RollupScore
|
|
attr_reader :outcome_results, :outcome, :score, :count, :title, :submitted_at
|
|
def initialize(outcome_results, opts={})
|
|
@outcome_results = outcome_results
|
|
@outcome = @outcome_results.first.learning_outcome
|
|
@count = @outcome_results.size
|
|
@calculation_method = @outcome.calculation_method || "highest"
|
|
@calculation_int = @outcome.calculation_int
|
|
@score = opts[:aggregate_score] ? get_aggregate_score : calculate_results
|
|
get_latest_result unless opts[:aggregate_score]
|
|
end
|
|
|
|
#todo - do send(@calculation_method) instead of the case to streamline this more
|
|
def calculate_results
|
|
# decaying average is default for new outcomes
|
|
case @calculation_method
|
|
when 'decaying_average'
|
|
return nil if @outcome_results.length < 2
|
|
decaying_average
|
|
when 'n_mastery'
|
|
return nil if @outcome_results.length < @calculation_int
|
|
n_mastery
|
|
when 'latest'
|
|
@outcome_results.max_by{|result| result_time(result) }.score
|
|
when 'highest'
|
|
@outcome_results.max_by{|result| result.score}.score
|
|
end
|
|
end
|
|
|
|
def n_mastery
|
|
scores = @outcome_results.map(&:score).sort.last(@calculation_int)
|
|
(scores.sum.to_f / scores.size).round(2)
|
|
end
|
|
|
|
def decaying_average
|
|
#default grading method with weight of 65 if none selected.
|
|
weight = @calculation_int || 65
|
|
scores = @outcome_results.sort_by{|result| result_time(result) }.map(&:score)
|
|
latestWeighted = scores.pop * (0.01 * weight)
|
|
olderAvgWeighted = (scores.sum / scores.length) * (0.01 * (100 - weight))
|
|
(latestWeighted + olderAvgWeighted).round(2)
|
|
end
|
|
|
|
def get_latest_result
|
|
latest_result = @outcome_results.max_by{|result| result_time(result) }
|
|
@submitted_at = latest_result.submitted_at || latest_result.assessed_at
|
|
@title = @submitted_at ? latest_result.title.split(", ")[1] : nil
|
|
end
|
|
|
|
def get_aggregate_score
|
|
scores = @outcome_results.map(&:score)
|
|
(scores.sum.to_f / scores.size).round(2)
|
|
end
|
|
|
|
def result_time(result)
|
|
(result.submitted_at || result.assessed_at).to_i
|
|
end
|
|
end |