5.1. Quizzes (quiz.rsl)

(****
 * 
 * Module Quiz defines the objects and operations related to
 * creating a Quiz
 * for use by the CSTutor application.
 *
 *)


module Quiz;

from Page import all except TagsWeCareAbout;
from Data import ServerFilespace;
export all;



object Quiz inherits from Page
	components: qc:QuizContent and cq:CurrentQuestion and ShowQuizResults and tp:TotalPoints and author:Author;
	description: (*
		A Quiz contains all the elements to present information in a Quiz.
	*);
end Quiz;

object CurrentQuestion is QuestionNumber
	description: (*
		This is equal to the maximum number of points on the quiz.
	*);
end CurrentQuestion;

object TotalPoints is integer
	description: (*
		This is equal to the maximum number of points on the quiz.
	*);
end TotalPoints;

object Author is UserID
	description: (*
		The author of the quiz.
	*);
end Author;

object ShowQuizResults is boolean
	description: (*
		If true, students are allowed to view their scores right after they take the quiz. If false, then students do not see their scores, and consequently do not see any Helpful Links or Next-Lesson Links.
	*);
end ShowQuizResults;

operation Submit -- look at data.rsl to see where this is going
	inputs: q:Quiz, s:ServerFilespace;
	outputs: s':ServerFilespace;
	precondition: (*
		ServerFilespace is not nil.
	*)
	s != nil;
	postcondition: 
	(* there's an author folder af, with its author = the quiz's author in s.authorFolders, such that q in af.quizFolder *)
	(exists (af in s'.authorFolders) af.userID = q.Author);
	description: (*
		This operation happens when an user taking the quiz presses the submit button.
	*);
end Submit;

object QuestionNumber is integer
	description: (*
		The question's number.
	*);
end QuestionNumber;

(***********************************************************)

object QuizContent is Question*
	description: (*
		Each quiz is made up of HTMLContent (which was inherited from Page) and QuizContent. This is the content that is specific to a quiz.
	*);
end QuizContent;

object Question is
	components: qn:QuestionNumber and pv:PointValue and qt:QuestionText and qac:QuestionAnswerContent;
	description: (*
		Defines the beginning and end of each question and all of the components that belong to each question.
	*);
end Question;

object QuestionAnswerContent is QuestionNumber and Answer*
	description: (*
		Each QuestionAnswerContent belongs to one question, which QuestionNumber denotes. It is also made up of a collection of Answer objects.
	*);
end QuestionAnswerContent;

object Answer is check:Checkbox or radio:RadioButton or text:Textbox or code:CodeSegment
	description: (*
		Each question can have multiple Answer objects. A question needs an Answer objects for each checkbox, radio button, textbox, and code segment.
	*);
end Answer;

object Checkbox is boolean
	description: (*
		If true, then the checkbox is checked. If false, then it is unchecked.
	*);
end Checkbox;

object RadioButton is boolean
	description: (*
		If true, then the radio button is selected. If false, then it is unselected.
	*);
end RadioButton;

object Textbox is string
	description: (*
		The value of the textbox is stored in here.
	*);
end Textbox;

object CodeSegment is cs:CodeString and GradeThroughComparisonOfCode
	description: (*
		The CodeString is the answer for the CodeSegment, and GradeThroughComparisonOfCode has to do with how it is graded.
	*);
end CodeSegment;

object GradeThroughComparisonOfCode is boolean
	description: (*
		if it is true, then the code segment is graded through comparison of code. if it is false, then it is graded through comparison of standard output.
	*);
end GradeThroughComparisonOfCode;

object CodeString is string
	description: (*
		This is the answer to a CodeSegment.
	*);
end CodeString;

(***********************************************************)

object PointValue is integer
	description: (*
		The number of points a question is worth.
	*);
end PointValue;

object QuestionText is string*
	description: (*
		This includes all text in a question (but does not include Textbox or CodeSegment text).
	*);
end QuestionText;

object TagsWeCareAbout
	description: (*
		These are tags that need to be modeled for a particular tool's use of HTML, i.e., tags that the tool uses explicitly. These include  tags,  tags, and  tags.
	*);
end TagsWeCareAbout;

(***********************************************************)

operation InsertCheckbox is
	inputs: qac:QuestionAnswerContent and ica:IsCorrectAnswer;
	outputs: qac':QuestionAnswerContent;
	precondition: (*
		QuestionAnswerContent cannot be nil.
	*)
	(qac != nil);
	postcondition: (*
		Nothing about the Question was altered except for the checkbox was inserted in the current question. The correct answer is added to QuestionAnswerContent.
	*)
	(exists (newans:Answer | newans?check) ( newans.check = ica; ))
		and
	(forall (a':Answer) -- only the appropriate answer is altered.
	   (a' in qac') iff ((a' in qac) or (a' = newans)));

	description: (*
		Inserts a selected checkbox if IsCorrectAnswer is true. Otherwise, inserts an unselected checkbox.
	*);
end InsertCheckbox;

object IsCorrectAnswer is boolean
	description: (*
		If true, then this Answer is a correct answer. If false, then it is incorrect.
	*);
end IsCorrectAnswer;

operation InsertRadioButton is
	inputs: qac:QuestionAnswerContent and ica:IsCorrectAnswer;
	outputs: qac':QuestionAnswerContent;
	precondition: (*
		QuestionAnswerContent cannot be nil.
	*)
	(qac != nil);
	postcondition: (*
		Nothing about the Question was altered except for the radio button was inserted in the current question. The correct answer is added to QuestionAnswerContent.
	*)
	(exists (newans:Answer | newans?radio) ( newans.radio = ica; ))
		and
	(forall (a':Answer) -- only the appropriate answer is altered.
	   (a' in qac') iff ((a' in qac) or (a' = newans)));

	description: (*
		Inserts a selected radio button if IsCorrectAnswer is true. Otherwise, inserts an unselected radio button.
	*);
end InsertRadioButton;

operation InsertTextbox is
	inputs: qac:QuestionAnswerContent and input:TextboxInput;
	outputs: qac':QuestionAnswerContent;
	precondition: (*
		QuestionAnswerContent cannot be nil.
	*)
	(qac != nil);
	postcondition: (*
		Nothing about the Question was altered except for the textbox was inserted in the current question. The correct answer is added to QuestionAnswerContent.
	*)
	(exists (newans:Answer | newans?text) ( newans.text = input; ))
		and
	(forall (a':Answer) -- only the appropriate answer is altered.
	   (a' in qac') iff ((a' in qac) or (a' = newans)));
	description: (*
		Inserts a textbox with TextboxInput as the value.
	*);
end InsertTextbox;

object TextboxInput is string;
	description: (*
		This is the string value of the Textbox.
	*);
end TextboxInput;

operation InsertCodeSegment is
	inputs: qac:QuestionAnswerContent and input:TextboxInput and gtcoc:GradeThroughComparisonOfCode;
	outputs: qac':QuestionAnswerContent;
	precondition: (*
		QuestionAnswerContent cannot be nil.
	*)
	(qac != nil);
	postcondition: (*
		Nothing about the Question was altered except for the code segment was inserted in the current question. The correct answer is added to QuestionAnswerContent.
	*)
	(exists (newans:Answer | newans?code) ( newans.code.cs = input; ))
		and
	(forall (a':Answer) -- only the appropriate answer is altered.
	   (a' in qac') iff ((a' in qac) or (a' = newans)));
	description: (*
		Inserts a textbox with TextboxInput as the value.
	*);
end InsertCodeSegment;

operation InsertQuestion is
	inputs: q:Quiz, ques:Question;
	outputs: q':Quiz;
	precondition: (*
		A Quiz must be open. Only the question number and point value is defined, everything else is nil.
	*)
	(q != nil) and (ques.qt = nil) and (ques.qac = nil);
	postcondition: (*
		A new question is created, and no other question is altered.
	*)
	forall (ques':Question) (ques' in q'.qc) iff (ques' = ques) or (ques'in q.qc);
	description: (*
		A new question is started.
	*);
end InsertQuestion;

(***********************************************************)

object HelpfulLinks is HelpfulLink*
	description: (*
		These are the HelpfulLinks that are displayed next to each answer.
	*);
end HelpfulLinks;

object HelpfulLink is QuestionNumber and InternalLink
	description: (*
		These are InternalLinks which correspond to each question, as denoted by QuestionNumber.
	*);
end HelpfulLink;

operation EditHelpfulLink is
	inputs: q:Quiz and hl:HelpfulLink and il:InternalLink;
	outputs: hl':HelpfulLink;
	precondition: (*
		Students must be shown their answers.
	*)
	q.ShowQuizResults = true;
	postcondition: (*
		the HelpfulLink's internal link is changed to the new one.
	*)
	hl'.InternalLink = il;
	description: (*
		Changes a HelpfulLink's internal link.
	*);
end EditHelpfulLink;

(***********************************************************)

object NextLessonLinks is nln:NextLessonLink*
	description: (*
		These are the Next-Lesson Links that are displayed at the end of each quiz result.
	*);
end NextLessonLinks;

object NextLessonLink is pe:PointsEarned and InternalLink
	description: (*
		These are InternalLinks which correspond to each question, as denoted by QuestionNumber.
	*);
end NextLessonLink;

object PointsEarned is integer
	description: (*
		This number corresponds to how many points the student needs to get right in order to be shown the corresponding Next-Lesson Link.
	*);
end PointsEarned;

operation EditNextLessonLink is
	inputs: nln:NextLessonLink and il:InternalLink;
	outputs: nln':NextLessonLink;
	precondition: (*
		Students must be shown their answers.
	*)
	ShowQuizResults = true;
	postcondition: (*
		the NextLessonLink's internal link is changed to the new one.
	*)
	nln'.il = il;
	description: (*
		Changes a NextLessonLink's internal link.
	*);
end EditNextLessonLink;

operation PointsEarnedIsValid is
	inputs: q:Quiz and nlns:NextLessonLinks;
	outputs: nlns':NextLessonLinks;
	precondition: (*
		Students must be shown their answers.
	*)
	ShowQuizResults = true;
	postcondition: (*
		isValid is true if: all PointsEarned objects are greater than zero, but no greater than the maximum number of points on the quiz; PointsEarned objects are also be in descending order. otherwise, it is false.
	*)
	forall (i:integer | (i >= 1) and (i < #nln))
		(nln[i].pe > nln[i+1].pe) -- descending order
			and
		(nln[i].pe > 0) -- greater than 0
			and
		(nln[i].pe <= q.tp); -- less or equal to the total points on quiz
	description: (*
		Checks PointsEarned objects for validity. This happens when the user presses OK in the Next-Lesson Links dialog. If they are valid, then this is true. Otherwise, it is false.
	*);
end PointsEarnedIsValid;

end Quiz;





Prev: ... | Next: ... | Up: spec | Top: index