Class: Grade

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/grade.rb

Constant Summary collapse

FIRST_GRADE_ROW =
2
FIRST_GRADE_COL =
4

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.export_grade_book_to_spreadsheet(course, file_path) ⇒ Object

To export the grades in spreadheet for offline grading.


160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'app/models/grade.rb', line 160

def self.export_grade_book_to_spreadsheet(course, file_path)
  Spreadsheet.client_encoding = 'UTF-8'
  grade_book = Spreadsheet::Workbook.new
  grade_sheet = grade_book.create_worksheet
  grade_sheet.name = "#{course.short_name}"

  # print course id and assignment id
  grade_sheet[0, 0] = course.id
  course.assignments.each_with_index do |assignment, i|
    grade_sheet[0, FIRST_GRADE_COL+i] = assignment.id
  end
  assignment_count = course.assignments.count
  grade_sheet[0, FIRST_GRADE_COL+assignment_count] = -1
  grade_sheet.row(0).hidden = true

  # print details
  grade_sheet[1, 1] = "First Name"
  grade_sheet[1, 2] = "Last Name"
  grade_sheet[1, 3] = "Team Name"

  grade_sheet.column(0).hidden=true
  course.assignments.each_with_index do |assignment, j|
    grade_sheet[1, FIRST_GRADE_COL+j] = assignment.name
  end
  grade_sheet[1, FIRST_GRADE_COL+assignment_count] = "Final Grade"

  # print students' names and grades
  students = course.registered_students_or_on_teams.sort do |x, y|
    r = (self.find_student_team(course.id, x.id).try(:name) || "")<=> (self.find_student_team(course.id, y.id).try(:name) || "")
    r = x.first_name <=> y.first_name if r == 0
    r = x.last_name <=> y.last_name if r == 0
    r
  end
  students.each_with_index do |student, i|
    grade_sheet[FIRST_GRADE_ROW+i, 0] = student.id
    grade_sheet[FIRST_GRADE_ROW+i, 1] = student.first_name
    grade_sheet[FIRST_GRADE_ROW+i, 2] = student.last_name
    grade_sheet[FIRST_GRADE_ROW+i, 3] = self.find_student_team(course.id, student.id).try(:name)
    course.assignments.each_with_index do |assignment, j|
      score=Grade.get_grade(course.id, assignment.id, student.id).try(:score) || ""
      if !course.grading_rule.validate_letter_grade(score)
        unless score.blank?
          score=score.to_f
        end

      end
      grade_sheet[FIRST_GRADE_ROW+i, FIRST_GRADE_COL+j] = score
    end
    grade_sheet[FIRST_GRADE_ROW+i, FIRST_GRADE_COL+assignment_count] = Grade.get_final_grade(course.id, student.id)
  end
  grade_book.write(file_path)
end

.get_final_grade(course_id, student_id) ⇒ Object

To get the final grade of the student for a particular course.


68
69
70
71
72
73
74
75
# File 'app/models/grade.rb', line 68

def self.get_final_grade(course_id, student_id)
  grade = Grade.where(course_id: course_id).where(student_id: student_id).where(:assignment_id => -1).first
  if grade.nil? || !grade.is_student_visible?
    ""
  else
    Grade.decrypt_score(grade.score, grade.course_id, grade.student_id)
  end
end

.get_grade(course_id, assignment_id, student_id) ⇒ Object

To fetch the entry with matching course, assignment and student.


63
64
65
# File 'app/models/grade.rb', line 63

def self.get_grade(course_id, assignment_id, student_id)
  grade = Grade.where(course_id: course_id).where(student_id: student_id).where(:assignment_id => assignment_id).first
end

.get_grades_for_student_per_course(course, student) ⇒ Object

To fetch the grade of student.


49
50
51
52
53
54
55
56
57
58
59
60
# File 'app/models/grade.rb', line 49

def self.get_grades_for_student_per_course (course, student)
  grades = {}
  Grade.where(course_id: course.id).where(student_id: student.id).each do |grade|
    if grade.assignment_id < 0
      grade.score = Grade.decrypt_score(grade.score, grade.course_id, grade.student_id)
      grades["final"] = grade
    else
      grades[grade.assignment.id] = grade
    end
  end
  grades
end

.give_grade(course_id, assignment_id, student_id, score, is_student_visible = nil, last_graded_by = nil) ⇒ Object

To returns a specific grade for one assignment of given course_id, student_id and assignment_id. This function is

useful for controller to test whether the score is exists or not.

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'app/models/grade.rb', line 79

def self.give_grade(course_id, assignment_id, student_id, score, is_student_visible = nil, last_graded_by = nil)
  if assignment_id > 0
    if Assignment.find(assignment_id).nil?
      return false
    end
  end

  grading_result = false
  student = User.find(student_id)
  course = Course.find(course_id)
  if course.registered_students_or_on_teams.include?(student)
    grade = Grade.get_grade(course_id, assignment_id, student_id)
    if grade.nil?
      grade = Grade.new({:course_id => course_id, :assignment_id => assignment_id, :student_id => student_id,
                         :score => score, :is_student_visible => is_student_visible, :last_graded_by => last_graded_by})
    end

    if course.grading_rule.validate_score(score)
      grade.score = score.upcase
      unless is_student_visible.nil?
        grade.is_student_visible = is_student_visible
      end
      unless last_graded_by.nil?
        if grade.last_graded_by.nil?
          grade.last_graded_by = last_graded_by
        end
      end
      grading_result = grade.save
    else
      grading_result = false
    end
  end
  grading_result
end

.give_grades(grades, last_graded_by = nil) ⇒ Object

To assign grades for to multiple students.


115
116
117
118
119
120
# File 'app/models/grade.rb', line 115

def self.give_grades(grades, last_graded_by = nil)
  grades.each do |grade_entry|
    # FIXME: error handling for update failure
    self.give_grade(grade_entry[:course_id], grade_entry[:assignment_id], grade_entry[:student_id], grade_entry[:score], grade_entry[:is_student_visible], last_graded_by)
  end
end

.import_grade_book_from_spreadsheet(file_path, current_course_id) ⇒ Object

To import the grades into the gradebook from spreadsheet.


147
148
149
150
151
152
153
154
155
156
157
# File 'app/models/grade.rb', line 147

def self.import_grade_book_from_spreadsheet(file_path, current_course_id)
  Spreadsheet.client_encoding = 'UTF-8'
  grade_book = Spreadsheet.open(file_path)
  grade_sheet = grade_book.worksheet(0)
  if validate_sheet(grade_sheet, current_course_id)
    import_scores(grade_sheet)
    return true
  else
    return false
  end
end

.mail_drafted_grade(course_id, hostname, faculty_email = nil) ⇒ Object

To notify students about the grade that were drafted by professor till now.


123
124
125
126
127
128
129
130
131
132
# File 'app/models/grade.rb', line 123

def self.mail_drafted_grade(course_id, hostname, faculty_email=nil)
  draft_grades = Grade.find_all_by_is_student_visible_and_course_id(false, course_id)
  draft_grades.each do |grade|
    grade.is_student_visible = true
    grade.save
    unless (grade.score.blank?)
      grade.send_feedback_to_student(hostname, faculty_email)
    end
  end
end

.mail_final_grade(course_id, hostname, faculty_email = nil) ⇒ Object

To send the final grade mail to students


135
136
137
138
139
140
141
142
143
144
# File 'app/models/grade.rb', line 135

def self.mail_final_grade(course_id, hostname, faculty_email=nil)
  final_grades = Grade.find_all_by_course_id_and_assignment_id(course_id, -1)
  final_grades.each do |grade|
    unless (grade.score.blank?)
      grade.is_student_visible = true
      grade.save
      grade.send_feedback_to_student(hostname, faculty_email)
    end
  end
end

Instance Method Details

#decrypt_scoreObject

To decrpyt the score if it is a final grade.


42
43
44
45
46
# File 'app/models/grade.rb', line 42

def decrypt_score
  if self.assignment_id < 0
    self.score = Grade.decrypt_score(self.score, self.course_id, self.student_id)
  end
end

#format_scoreObject

To format and encrypt the score in correct format before saving into the database.


34
35
36
37
38
39
# File 'app/models/grade.rb', line 34

def format_score
  self.score = GradingRule.format_score(self.course.id, self.score)
  if self.assignment_id < 0
    self.score = Grade.encrypt_score(self.score, self.course_id, self.student_id)
  end
end

#make_feedback_for_final_gradeObject

To make the email body for the final grade awarded by the professor


230
231
232
233
# File 'app/models/grade.rb', line 230

def make_feedback_for_final_grade
  feedback = "Final grade has been assigned for "
  feedback += self.course.name + "\n"
end

#make_feedback_for_one_assignmentObject

To make the email body for the assignment graded by professor


214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'app/models/grade.rb', line 214

def make_feedback_for_one_assignment
  feedback = "Grade has been submitted for "
  if !self.assignment.task_number.nil? and self.assignment.task_number != "" and !self.assignment.name.nil? and self.assignment.name !=""
    feedback += "#{self.assignment.name} (#{self.assignment.task_number}) of "
  end
  feedback +=self.course.name
  feedback += "\nGrade earned for this "
  feedback += self.course.nomenclature_assignment_or_deliverable
  feedback += " is: "
  feedback += self.score.to_s
  feedback += " / "
  feedback += self.assignment.formatted_maximum_score
  feedback += "\n"
end

#send_feedback_to_student(hostname, faculty_email = nil) ⇒ Object

To send the feedback to the student.


236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'app/models/grade.rb', line 236

def send_feedback_to_student(hostname, faculty_email=nil)
  if assignment_id > 0
    feedback = make_feedback_for_one_assignment
  else
    feedback = make_feedback_for_final_grade
  end
  url = hostname + "/courses/#{self.course.id}/student_grades"
  options = {:to => self.student.email,
             :cc => faculty_email,
             :subject => "Grade for " + self.course.name,
             :message => feedback,
             :url_label => "Click here to view grade",
             :url => url
  }

  GenericMailer.email(options).deliver
end