module TestPackage; from Test_Preferences import all; from QuestionManagement import all; from TestGeneration import all; export all; object Test is components: qs:TestQuestion* and tl:TestLength and tt:TestTime and td:TestDifficulty and cl:Class and tkw:TestKeyword* and tpts:TestPoints and tn:TestName and ntf:NumTF and nmc:NumMC and ness:NumEssay and ncde:NumCode and nfill:NumFill; description: (* A test is composed of zero or more TestQuestions *); end Test; object TestKeyword is components: string; description: (* The keywords of a test. *); end TestKeyword; object TestName is components: string; description: (* The name of a test. *); end TestName; object TestPoints is components: integer; description: (* A integer that holds the total number of points for a test. *); end TestPoints; object TestLength is components: integer; description: (* A integer that represents the number of questions on a test. *); end TestLength; object TestTime is components: integer; description: (* A integer that represents the duration of a test. *); end TestTime; object TestDifficulty is components: integer; description: (* A integer that represents the difficulty of a test on a 1-10 scale. *); end TestDifficulty; object TestQuestion inherits from Question is components: qn:QuestionNumber and qpts:QuestionPoints; description: (* A TestQuestion has all the components of a Question, but has an extra component that specifies what number in a test it is. *); end TestQuestion; object QuestionPoints is components: integer; description: (* Points is the point value assigned to a TestQuestion for a test. *); end QuestionPoints; object QuestionNumber is components: integer; description: (* QuestNumber is the question number assigned a TestQuestion to signify the order in which it appears in a Test. *); end QuestionNumber; operation AddTestQuestion inputs: q:TestQuestion, tst:Test; outputs: tst':Test; precondition: (* * There is no question in the input Test that is the same as the input * question. *) (not (exists (q' in tst.qs) q' = q)) and (* * The input question is not empty. *) (q != nil); postcondition: (* * A Question is only in the output Test if and only if it is the new * Question to be added or it is in the input Test. *) forall (q':TestQuestion) (q' in tst'.qs) iff ((q' = q) or (q' in tst.qs)); description: (*A Question becomes a TestQuestion and is applied to the Test. *); end AddTestQuestion; operation EditTestQuestion inputs: oldQuestion:TestQuestion, newQuestion:TestQuestion, tst:Test; outputs: tst':Test; precondition: (* * There is no question in the input Test that is the same as the new * question. *) (not (exists (q' in tst.qs) (q' = newQuestion))) and (* * The old question is in the input test. *) (exists (q' in tst.qs) (q' = oldQuestion)); postcondition: (* * A Question is only in the output Test if and only if it is the new * Question to be added or is in the input Test, and it is not the old * Question. *) forall (q':TestQuestion) (newQuestion in tst'.qs) iff (((q' = newQuestion) or (q' in tst.qs)) and (q' != oldQuestion)); end EditTestQuestion; operation DeleteTestQuestion inputs: tq:TestQuestion, tst:Test; outputs: tst':Test; precondition: (* * The given TestQuestion is in Test *) tq in tst.qs; postcondition: (* * A TestQuestion is in the output Test if and only if it is not the existing * TestQuestion to be deleted and it is in the input Test. *) forall (tq':TestQuestion) (tq' in tst'.qs) iff ((tq' != tq) and (tq' in tst.qs)); description: (*A TestQuestion is selected and removed from Test. *); end DeleteTestQuestion; operation ReplaceQuestion inputs: tq:TestQuestion, tst:Test, qdb:QuestionDatabase, tp:TestPreferences; outputs: tst':Test; precondition: (* * The given TestQuestion is in test *) tq in tst.qs; postcondition: (* * A TestQuestion is in the output Test if it is not the input * TestQuestion, but it is either in the input Test or has the * same properties as the input question, but is not the input question. *) forall (tq':TestQuestion) if (tq' in tst'.qs) then ((tq' != tq) and ((tq' in tst.qs) or (forall (i:integer | i >= 1 and i <= #qdb.qs) ((tq'.qt != qdb.qs[i].qt) and (tq'.class = qdb.qs[i].class) and (tq'.author = qdb.qs[i].author) and ((tq'.time + tp.qtv.v >= qdb.qs[i].time) or (tq'.time - tp.qtv.v <= qdb.qs[i].time)) and ((tq'.diff + tp.df.v >= qdb.qs[i].diff) or (tq'.diff - tp.df.v <= qdb.qs[i].diff)) and (tq'.t = qdb.qs[i].t) and forall (j:integer | j >= 1 and j <= #tq'.keywords) tq'.keywords[j] in qdb.qs[i].keywords)))); description: (*A suitable replacement for tq is found in qdb and is then applied to Test. *); end ReplaceQuestion; end TestPackage;