5.8. TestTaking

module TestTaking;
  from TestAdminister import ClassTests, TestView, CurrentQuestion, QuestionView, QuestionText, Status;
  from TestGeneration import Test, TestQuestion, PointsPossible;
  from QuestionModule import Answer, ClassName, Question, ID, Type, Difficulty, Time, CorrectAnswer,
                             Author, AverageScore, Created, Modified, LastUsed, Notes;
export StudentAnswer, AnsweredQuestion, AQStatus;

--OBJECTS
obj StudentAnswer is Answer;
obj AnsweredQuestion inherits from TestQuestion
    components: sa:StudentAnswer, aqs:AQStatus;
    description: (* A question once the student taking it has supplied an answer or once the
                    question is submitted *);
end AnsweredQuestion;
obj AQStatus is string;

--TEST TAKING OPERATIONS
op ViewTest is
    inputs: test:Test, tv:TestView;
    outputs: tv':TestView;
    post:  (* TestView displays the test which corresponds to n *)
           (forall (i:integer | i <= #(tv.qv))
             (tv.qv[i].qt in test.qs[i].text));
    description: (* The selected test name will show the test in the TestView
                 window *);
end ViewTest;

op AnswerQuestion
    inputs: t:Test, tq:TestQuestion, tv:TestView;
    outputs: t':Test;
    pre:
       (*
        * The test question to be answered is in the test
        *)
       (tq in t.qs);
    post:
       (*
        * The question is now answered
        *)
        (SetQuestion(t,tq,(tv.qv[tv.cur].answer)) = t');
    description: (*Answers a given question, converting it to an aswered question*);
end AnswerQuestion;

op DisplayNextQuestion is
    inputs: tv:TestView;
    outputs: tv':TestView;
    pre: (* not at last question *)
         tv.cur < #(tv.qv);
    post: (* TestView displays next question *)
         tv'.cur = tv.cur+1;
    description: (* The TestView will display the next question in the test *);
end DisplayNextQuestion;

op DisplayPrevQuestion is
    inputs: tv:TestView;
    outputs: tv':TestView;
    pre: (* not at first question *)
         tv.cur > 1;
    post: (* TestView displays previous question *)
         tv'.cur = tv.cur-1;
    description: (* The TestView will display the previous question in the test
                 *);
end DisplayPrevQuestion;

op DisplayFirstQuestion is
    inputs: tv:TestView;
    outputs: tv':TestView;
    pre: (* not at first question *)
         tv.cur>1;
    post: (* TestView displays first question *)
         tv'.cur=1;
    description: (* The TestView will display the first question in the test *);
end DisplayFirstQuestion;

op DisplayLastQuestion is
    inputs: tv:TestView;
    outputs: tv':TestView;
    pre:  (* not at last question *)
          tv.cur < #(tv.qv);
    post: (* TestView displays last question *)
          tv'.cur = #(tv.qv);
    description: (* The TestView will display the last question in the test*);
end DisplayLastQuestion;

op SkipToQuestion is
    inputs:  tv:TestView, question:integer;
    outputs: tv':TestView;
    pre:  (* not at question already *)
          tv.cur != question;
    post: (* TestView displays specified question *)
          tv'.cur = question;
    description: (* The TestView will display the question selected *);
end SkipToQuestion;

op SubmitTest is
    inputs: ct:ClassTests, tv:TestView;
    outputs: ct':ClassTests;
    pre:  (*  TestView status is not submitted *)
          tv.stat != "submitted";
    post: (* There exists a test in class tests such that all answers in it
          match answers in the test view *)
          exists (t:Test | t in ct'.t)
           (forall (i:integer | i <= #(tv.qv))
           (t.aq[i].sa = tv.qv[i].answer)
           
           and

           (* Every question in the test is answered *)
           (SetQuestion(t,t.qs[i],tv.qv[i].answer) in ct'.t))

           and

           (* No more test questions exist, only answered questions *)
           (forall (t in ct'.t)
              (t.qs = nil) and (t.aq != nil) and (t.gq = nil));
    description: (* SubmitTest will add an answered test to the ClassTests object *);
end SubmitTest;

function SetQuestion(t:Test,tq:TestQuestion,a:StudentAnswer)->(Test)=
(
   exists (aq in t.aq)
   (
   (*
    * All fields in TestQuestion are in AnsweredQuestion
    *)
   aq.id = tq.id and
   aq.type = tq.type and
   aq.text = tq.text and
   aq.difficulty = tq.difficulty and
   aq.time = tq.time and
   aq.ca = tq.ca and
   aq.cn = tq.cn and
   aq.topics = tq.topics and
   aq.author = tq.author and
   aq.as = tq.as and
   aq.created = tq.created and
   aq.modified = tq.modified and
   aq.lu = tq.lu and
   aq.notes = tq.notes and
   aq.qt = tq.qt and
   aq.points = tq.points and
   aq.sa = a)
);
end TestTaking;


Prev:
5.7. TestGrading

Up:
5. Formal Specifications