(* describes the student related portion of testtool *) module Student; from Question import QuestionDB, Question, TestQuestion, AnsweredQuestion, GradedQuestion, QuestionNumber; from Test import Test, TakenTest, TestTime, Difficulty, TotalPoints, TestName; export Student, TestServer, GradesServer; (* 'students present' table in administer tools *) object StudentsPresentTable is components: studentlist:Student*; description: (* The students present table is a collection of Students. Each student takes 1 row of the table. *); end StudentsPresentTable; object Student is components: studentname:StudentName, studentid:StudentID, studentpassword:StudentPassword; description: (* A Student object represents a student. Consists of a Name, ID, and password unique to every student. *); end Student; object StudentName is string; object StudentID is string; object StudentPassword is string; operation StudentBeginsTest is inputs: spt:StudentsPresentTable, s:Student; outputs: spt':StudentsPresentTable; precondition: (* student enters the testing environment *); postcondition: (* output table consists of every student present in input table + entering student, sorted by student ID *) (spt' = spt + s) and (forall (i:integer | (i >= 1) and ( i < #(spt'.studentlist))) spt'.studentlist[i].studentid < spt'.studentlist[i+1].studentid); end StudentBeginsTest; (* administration: starting and extending test time management details *) object TimeRemaining is integer; object TimeExtension is integer; operation BeginTest is inputs: test:Test; outputs: tr:TimeRemaining; precondition: ; postcondition: (tr = test.testtime); end BeginTest; operation ExtendTime is inputs: tr:TimeRemaining, te:TimeExtension; outputs: tr':TimeRemaining; precondition: ((tr > 0) and (te > 0)); postcondition: (tr' = tr + te); end ExtendTime; (* Students log in to take test*) operation StudentLogin is inputs: s:TestServer, studentid:StudentID, studentpassword:StudentPassword; outputs: test:Test; precondition: exists (stu in s.studentlist) (stu.studentid = studentid) and (stu.studentpassword = studentpassword); postcondition: (test = s.test); description: (* Login to the server to access test. If the students' username and password exist in the server's user list, return test, otherwise nil. *); end StudentLogin; object TestServer is components: studentlist:Student*, test:Test; description: (* A test server consists of a list of authentic users and a test. Access to the server must be granted to take a test. *); end TestServer; (* Students log in to check test results *) operation StudentGradesLogin is inputs: s:GradesServer, studentid:StudentID, studentpassword:StudentPassword; outputs: tests:Test*; precondition: exists (stu in s.studentlist) (stu.studentid = studentid) and (stu.studentpassword = studentpassword); postcondition: (tests = s.tests); description: (* Login to the server to access grades. If the students' username and password exist in the server's user list, returns the graded tests associated with that student. *); end StudentGradesLogin; object GradesServer is components: studentlist:Student*, tests:Test*; description: (* The grades server consists of a list of authentic users and the graded tests accosiated with those users. Access to the server must be granted to view any graded material. *); end GradesServer; (* question navigation in seperate questions view mode *) object CurrentQuestion is integer; operation NavBeginningOfTest is inputs:; outputs: cq:CurrentQuestion; precondition:; postcondition: (cq = 1); end NavBeginningOfTest; operation NavPrev is inputs: cq:CurrentQuestion; outputs: cq':CurrentQuestion; precondition: (cq > 1); postcondition: (cq' = cq - 1); end NavPrev; operation NavNext is inputs: test:Test, cq:CurrentQuestion; outputs: cq':CurrentQuestion; precondition: (cq < #(test.testquestionlist)); postcondition: (cq' = cq - 1); end NavNext; operation NavEndOfTest is inputs: test:Test; outputs: cq:CurrentQuestion; precondition:; postcondition: (cq = #(test.testquestionlist)); end NavEndOfTest; (* student responce and test submission *)operation AnswerQuestion is inputs: tq:TestQuestion; outputs: aq:AnsweredQuestion; precondition: (* Student enters an answer *); postcondition: (* aq.response = student input *); end AnswerQuestion; operation SubmitTest is inputs: test:Test, answeredquestionlist:AnsweredQuestion*; outputs: takentest:TakenTest; precondition: (* for all AnsweredQuestion objects, question numbers must match test question numbers *) (forall (i:integer | (i >= 1) and ( i < #(answeredquestionlist))) answeredquestionlist[i].questionnumber = test.testquestionlist[i].questionnumber); postcondition: (* test names are the same, total points are the same, difficulty is the same, and every question in the TakenTest has the same question number as in the Test *) (takentest.testname = test.testname) and (takentest.totalpoints = test.totalpoints) and (takentest.difficulty = test.difficulty) and (forall (i:integer | (i >= 1) and ( i < #(test.testquestionlist))) takentest.answeredquestionlist[i].questionnumber = answeredquestionlist[i].questionnumber ); end SubmitTest; end Student;