5.7. Grading (grading.rsl)
(*--- Describe the objects and operations related to grading ---*)
(* Filename - grading.rsl
Author - Sujit Polpaya
(With a lot of help from Chris Noe.)
Date - 05/24/2004
CPE 205, Dr.Fisher, Cal Poly, San Luis Obispo.
*)
(*--- Begin module Grader ---*)
module TestToolGrader;
(*--- Imports ---*)
from Test import Test, TakenTest, GradedTest, TotalPoints, File;
from Question import Question, AnsweredQuestion, GradedQuestion, AutoGrade, CorrectAnswer,
Response, Points, PointsEarned, Feedback, QuestionNumber;
from File import FileType, TakenTestType, GradedTestType;
(* There are no exports or objects in this module because this module uses the objects defined in
the other sections of the Test Tool.
*)
(* Automatically grade all the auto-gradable questions in all the available tests. *)
operation AutoGradeTests
inputs : ttests:TakenTest*;
outputs : agtests:GradedTest*;
precondition : (* All the tests in the list should be of the type: TakenTest *)
(forall (k:integer | (k >= 1) and (k < #(ttests)))
(ttests[k].file.file_type?taken_test_type));
postcondition: (* All the auto-gradable questions in all the available tests are graded.
If the response matches with the correct answer, full points are awarded,
else a zero is awarded. *)
(forall (i:integer | (i >= 1) and (i < #(ttests)))
(forall (j:integer | (j >= 1) and (j < #(ttests[i].answeredquestionlist)))
(if (ttests[i].answeredquestionlist[j].autograde = true)
then
(if(ttests[i].answeredquestionlist[j].response =
ttests[i].answeredquestionlist[j].correctanswer)
then
agtests[i].gradedquestionlist[j].pointsearned =
ttests[i].answeredquestionlist[j].points
else agtests[i].gradedquestionlist[j].pointsearned = 0))));
description : (* Automatic grading tests attempts to grade all the tests in the grading folder.
But, it grades only the auto-gradable questions in each test, namely the multiple-choice,
true or false, fill-in-the-blanks and matching. Functionality to grade a matching question
is not implemented yet. Responses are compared with the correct answer only if the question
is auto-gradable. Points are assigned if the response matches with the correct answer, which
is stored either as a character or a string. If the response does not match with the correct
answer, a zero is awarded. *);
end AutoGradeTests;
(* Display autograding summary. *)
operation DisplayAutoGradingSummary
inputs : ttests:TakenTest*;
outputs : agtests:GradedTest*, total_tests_available:integer, total_tests_graded:integer,
total_questions_in_each_test:integer;
precondition : (* None. Preconditions are already satisfied in operation AutoGradeTests *);
postcondition: (* Total tests available = # of tests in a Taken Test.
Total tests graded = # of tests in a Graded Test.
Total questions in each test = # of questions in any test.
There is no way to implement a counter to count the number of tests graded
automatically. *)
((total_tests_available = #(ttests))
and
(total_tests_graded = #(agtests))
and
(total_questions_in_each_test = #(ttests[1].answeredquestionlist)));
description : (* Output the numeric values used to display in the summary dialog box. *);
end DisplayAutoGradingSummary;
(* Manually grade an individual test by assigning points and feedback to each student response.
Feedback can be empty. *)
operation ManualGradeTest
inputs : ttest:TakenTest, pts:Points*, fdbk:Feedback*;
outputs : mgtest:GradedTest;
precondition : (* The test should be of the type: TakenTest, and the points awarded cannot
be more than the possible points for each question. *)
((ttest.file.file_type?taken_test_type)
and
(forall (k:integer | (k >= 1) and (k < #(ttest.answeredquestionlist)))
(pts[k] <= ttest.answeredquestionlist[k].points)));
postcondition: (* Assign the respective points earned and the feedback to the respective
question in the test. *)
(forall (i:integer | (i >= 1) and (i < #(ttest.answeredquestionlist)))
(mgtest.gradedquestionlist[i].pointsearned = pts[i])
and
(mgtest.gradedquestionlist[i].feedback = fdbk[i]));
description : (* Points assigned for all the short-answer and program source code type questions,
and feedback by the grader are added to produce the graded test. The grader has
to grade each question in the test manually. *);
end ManualGradeTest;
(* Manually grade an individual question in an individual test. *)
operation ManualGradeQuestion
inputs : que:AnsweredQuestion, pts:Points, fdbk:Feedback;
outputs : que':GradedQuestion;
precondition : (* Points awarded cannot be more than the possible points. *)
(pts <= que.points);
postcondition: (* The grader assigns a point to the response manually.
So, just assign the points and feedback. Feedback can be empty. *)
(que'.pointsearned = pts and que'.feedback = fdbk);
end ManualGradeQuestion;
(* Manually grade an individual questions in all the tests. *)
operation ManualGradeQuestionsInTests
inputs : ttests:TakenTest*, question_number:integer, pts:Points*, fdbk:Feedback*;
outputs : agtests:GradedTest*;
precondition : (* All the tests in the list should be of the type: TakenTest, and
Points awarded cannot be more than the possible points for the specific
question. *)
(forall (k:integer | (k >= 1) and (k < #(ttests)))
(ttests[k].file.file_type?taken_test_type))
and
(forall (k:integer | (k >= 1) and (k < #(ttests)))
(pts[k] <= ttests[k].answeredquestionlist[question_number].points));
postcondition: (* The grader assigns a point to the response manually.
So, just assign the points and feedback. Feedback can be empty. *)
(forall (i:integer | (i >= 1) and (i < #(ttests)))
(agtests[i].gradedquestionlist[question_number].pointsearned = pts[i])
and
(agtests[i].gradedquestionlist[question_number].feedback = fdbk[i]));
description : (* Grades a specific question number in all the available tests. The grader
has to input the question number, points and feedback for each question. *);
end ManualGradeQuestionsInTests;
(* EditPointsEarned can be used to add, or edit points to a question. *)
operation EditPointsEarned
inputs : que:AnsweredQuestion, pts:Points;
outputs : que':GradedQuestion;
precondition : (* Points earned cannot be more than the possible points. *)
(que'.pointsearned <= que.points);
postcondition: (* The grader assigns a point to the response manually.
Just assign the points to the points earned. *)
(que'.pointsearned = pts);
end EditPointsEarned;
(* EditFeedback can be used to add, or edit feedback to a question. *)
operation EditFeedback
inputs : que:AnsweredQuestion, fdbk:Feedback;
outputs : que':GradedQuestion;
precondition : (* The question should not be automatically gradable. *)
(que.autograde = false);
postcondition: (* The grader assigns a feedback to the response manually. *)
(que'.feedback = fdbk);
end EditFeedback;
(* Adds the points earned by each response in a test to calculate the final test score. *)
operation CalculateTotalEarnedPoints
inputs : gtest:GradedTest;
outputs : gtest':GradedTest;
precondition : (* Test has to be of the type: GradedTest *)
(gtest.file.file_type?graded_test_type);
postcondition: (* Adds up points earned for each graded question. *)
(forall (i:integer | (i >= 1) and (i < #(gtest.gradedquestionlist)))
(gtest.totalpoints = gtest.totalpoints + gtest.gradedquestionlist[i].pointsearned));
description : (* Just adds up points earned for each question. There is no way to check if the
question is already graded by the grader. This is applicable for manually graded
questions. Auto-gradable questions are already graded and points are awarded. *);
end CalculateTotalEarnedPoints;
(* Display a student test view: GUI output operation. *)
operation DisplayStudentTestView
inputs : ttest:TakenTest;
outputs : gtest:GradedTest;
precondition : (* None *);
postcondition: (* Initialize the points earned and feedback for each test question. *)
(forall (i:integer | (i >= 1) and (i < #(ttest.answeredquestionlist)))
(gtest.gradedquestionlist[i].pointsearned = 0)
and
(gtest.gradedquestionlist[i].feedback = nil));
description : (* A student test view displays all the test questions and student responses,
with the points earned for each question initialized to 0, and the feedback
initialized to nil. *);
end DisplayStudentTestView;
(* Display a question view: GUI output operation. *)
operation DisplayQuestionView
inputs : ttests:TakenTest*, question_number:integer;
outputs : gtests:GradedTest*, gque:GradedQuestion*;
precondition : (* None *);
postcondition: (* A graded question is visible only if the question index matches with the question
number input by the user. *)
(forall (i:integer | (i >= 1) and (i < #(ttests)))
(forall (j:integer | (j >= 1) and (j < #(ttests[i].answeredquestionlist)))
(gtests[i].gradedquestionlist[j] in gque) iff (question_number =
gtests[i].gradedquestionlist[j].questionnumber)
and
(gtests[i].gradedquestionlist[j].pointsearned = 0)
and
(gtests[i].gradedquestionlist[j].feedback = nil)));
description : (* A student test view displays all the test questions and student responses,
with the points earned for each question initialized to 0, and the feedback
initialized to nil. *);
end DisplayQuestionView;
end TestToolGrader;
(*--- End module Grader ---*)
Prev: generate.rsl
| Next: student.rsl
| Up: formal specification
| Top: index