object ProctoredStudent is
	components: uname:UserName, ifin:isFinished, ians:isAnswered, igrade:isGraded, aq:AnsweredQuestion*, ie:isEnded;
	operations: EndStudent, CreateProctoredStudent, SetAnswer, GradeQuestions;
	description:
		(* A ProctoredStudent represents a student in the proctoring and grading phases of TestTool
                   it contains zero or more answered questions (which can be GradedQuestions, which is a subset of AnsweredQuestions) *);
end;

object ProctoredTest is
	components: isInProgress, ipause:isPaused,
			Test, TimeLimit,
			ProctoredStudent*;
	operations: StartTest, PauseTest, UnpauseTest, EndTest;
	description:
		(* A ProctoredTest is a test that is in progress, or has been completed, it also contains a list of the students in a class. *);
end;

object GradedQuestion extends AnsweredQuestion
        components: percentCorrect, isGraded;
description: (*This object holds the grades for a answered question, this can be a percentage correct a problem is, and a boolean representing whether the question has been graded *);
end GradedQuestion;


operation CreateProctoredStudent
description: (* Create a student object with their username set *);
inputs: un:UserName;
outputs: ps:ProctoredStudent;
precondition: (un != nil);
postcondition: (ps != nil);
end CreateProctoredStudent;

operation EndStudent
inputs: ps:ProctoredStudent;
outputs: ps':ProctoredStudent;
precondition: (ps != nil) and (ps.ie = false);
postcondition: (ps'.ie = true);
description: (* sets the isEnded boolean, so that the student can no longer enter answers *);
end EndStudent;

operation SetAnswer
inputs: q:GradedQuestion, ps:ProctoredStudent;
outputs: ps':ProctoredStudent;
precondition: (q != nil) and (ps != nil) and (ps.ifin = true) and (ps.ians);
postcondition: (ps' != nil) and (q in ps'.aq);

description: (* Adds the answered questions to the student object *);
end SetAnswer;

operation GradeQuestions
inputs: ps:ProctoredStudent;
outputs: ps':ProctoredStudent;
precondition: (ps != nil) and ((ps.igrade) = false);
postcondition: (ps.igrade != false);
description: (* grades a student's answers *);
end GradeQuestions;

operation StartTest
inputs: psl:ProctoredStudent*;
outputs: pt:ProctoredTest;
description: (* Starts the current test for all students *);
precondition: (psl != nil);
postcondition: (pt != nil);
end StartTest;

operation UnpauseTest
description: (* Unpauses the current test for all users *);
inputs: pt:ProctoredTest;
outputs: pt':ProctoredTest;

precondition: (* The current test is not paused *)
	(pt.ipause = false);
postcondition: (* The current test is paused *)
	(pt'.ipause = true);
end PauseTest;

operation PauseTest
description: (* Pauses the current test for all users *);
inputs: pt:ProctoredTest;
outputs: pt':ProctoredTest;

precondition: (*The current test is not paused*)
	(pt.ipause = false);
postcondition: (*The current test is paused*)
	(pt'.ipause = true);
end PauseTest;

object percentCorrect is integer
description: (* The percentage correct that an answer is *);
end percentCorrect;

object isGraded is boolean
description: (* States whether an answer is graded *);
end idGraded;

object TimeLimit is integer
description: (* the time limit for a test *);
end TimeLimit;

object UserName is string
description: (* The string representation of a username *);
end UserName;

object isEnded is boolean
description: (* states whether a student's test has been ended *);
end isEnded;


object isPaused is boolean
description: (* represents whehter a test is paused or not *);
end isPaused;

object isInProgress is boolean
description: (* represents whether a test is in progress *);
end isInProgress;

object isFinished is boolean
description: (* Describes whether a test is finished *);
end isFinished;

object isAnswered is boolean
description: (* Describes whether a question has been answered *);
end isAnswered;