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;