Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: a97e818620
Fetching contributors…

Cannot retrieve contributors at this time

149 lines (127 sloc) 5.296 kb
module Chart
def self.grade_range(events, options = {})
with_legend = options.delete(:with_legend)
tooltip = ""
tooltip << "this.series.name + '</b><br/>' + " if with_legend
tooltip << "this.x + '% (' + this.point.name + ')"
tooltip << (with_legend ? ": " : "</b><br/>")
grade_chart options do |chart|
chart.legend(true) if with_legend
chart.tooltip(formatter: "function(){ return '<b>' + #{tooltip}#{tooltip_formatter}); }")
chart.xAxis(title: 'Grade (Percentage)', tickInterval: 10, min: 0, max: 100, categories: (0..100).to_a)
chart.yAxis('# of Students')
chart.series(Data.grade_range(events))
end
end
def self.letter_grades(events, options = {})
letter_chart(options.merge({data: Data.letter_grades(events)}))
end
def self.student_grades(section, events)
letter_chart(renderTo: "graph_student_grades", title: "All Students' Current Semester Grades", data: Data.student_grades(section, events))
end
def self.assignments_by_student(events)
grade_chart renderTo: 'graph_all_assignments_by_student', title: 'All Grades By Student' do |chart|
chart.legend(enabled: true, layout: 'vertical', align: 'right', verticalAlign: 'top')
chart.tooltip(formatter: "function(){ return '<b>' + this.series.name + '</b><br/>' + this.x + ': ' + this.y + '% (' + this.point.name + ')'; }")
chart.xAxis(title: 'Assignments', categories: events.collect(&:title))
chart.yAxis(title: 'Grade (Percentage)', min: 0, max: 100)
chart.series(Data.assignments_by_student(events))
end
end
protected
def self.grade_chart(options = {})
Highcharts.new do |chart|
chart.chart(options[:renderTo])
chart.title(options[:title]) if options[:title]
yield chart
end
end
def self.letter_chart(options = {})
grade_chart options do |chart|
chart.tooltip(formatter: "function(){ return '<b>' + this.x + '</b><br/>#{tooltip_formatter}); }")
chart.xAxis(title: 'Grade', categories: ['A', 'B', 'C', 'D', 'F'])
chart.yAxis('# of Students')
chart.series(name: '# of Students', type: 'column', data: options[:data])
end
end
def self.tooltip_formatter
"' + this.y + ' Student' + (this.y == 1 ? '' : 's'"
end
module Data
extend ActionView::Helpers::NumberHelper
def self.grade_range(*events)
events.flatten!
series = Grade.for_events(events).select('score, COUNT(*) AS count, event_id').group(:event_id, :score).group_by(&:event_id).collect do |event_id, grades|
event = events.find {|e| event_id == e.id}
data = grades.collect do |grade|
{
x: format_score(grade, event),
y: grade.count,
name: "#{grade.score} / #{event.points_possible}"
}
end
{name: event.title, data: data}
end
end
def self.letter_grades(*events)
events.flatten!
grades = Grade.for_events(events).select('score, event_id').collect do |grade|
event = events.find {|e| grade.event_id == e.id}
(grade.score / event.points_possible.to_f) * 100
end
letterize(grades).values
end
def self.student_grades(section, events)
grades = Grade.for_events(events).group_by(&:student_id).collect do |_, scores|
student_events = events.select {|e| scores.collect(&:event_id).include?(e.id)}
if section.grading_system == 'point'
points_possible = student_events.sum(&:points_possible)
scores.sum(&:score) / points_possible.to_f * 100
else # weight system
total_weight = student_events.sum(&:weight)
scores.sum do |grade|
event = student_events.find {|e| e.id == grade.event_id}
(grade.score / event.points_possible.to_f) * 100 * (event.weight / total_weight.to_f)
end
end
end
letterize(grades).values
end
def self.assignments_by_student(events)
Grade.for_events(events).includes(:student).group_by(&:student_id).collect do |_, grades|
data = grades.collect do |grade|
event = events.find {|e| grade.event_id == e.id}
{
y: format_score(grade, event),
name: "#{grade.score} / #{event.points_possible}"
}
end
{name: grades.first.student.name, data: data}
end
end
protected
def self.format_score(grade, event)
number_with_precision ((grade.score / event.points_possible.to_f) * 100), precision: 2, strip_insignificant_zeros: true
end
# This take an Array of grades and maps them to the appropriate letter grade. The final result is a Hash
# of letter: count key/value pairs:
#
# {'A' => 1, 'B' => 2, 'C' => 3, 'D' => 2, 'F' => 1}
def self.letterize(grades, letter_map = nil)
letter_map ||= {
'A' => 90,
'B' => 80,
'C' => 70,
'D' => 65,
'F' => 0
}
grades = grades.group_by do |grade|
letter_map.find {|l, min| grade >= min}.first
end
letter_map.inject({}) do |scores, (letter, min)|
scores[letter] = grades[letter].try(:length) || 0
scores
end
end
end
end
Jump to Line
Something went wrong with that request. Please try again.