5.2. QuestionModule

(*
 * Module Question defines the objects and operations related to maintaining
 * a Question Bank, the questions that make up a Question Bank, and Question
 * Bank management.
 *)
module QuestionModule;

from QuestionBankModule import QuestionBank;
export    Question, ID, Type, QuestionText, Difficulty, Time, CorrectAnswer, ClassName, Topic, Author, AverageScore, Created, Modified, LastUsed, Notes,
        Answer, ShortAnswer, Essay, Date, Year;

object Question is
    components: id:ID, type:Type, text:QuestionText*, difficulty:Difficulty, time:Time, ca:CorrectAnswer, cn:ClassName, topics:Topic*, author:Author, as:AverageScore, created:Created, modified:Modified, lu:LastUsed, notes:Notes;
    operations: CreateQuestion;
    description: (*
    *);
end Question;

object Answer is tf:TrueFalse or mc:MultipleChoice or m:Matching or fi:FillIn or sa:ShortAnswer or e:Essay or p:Programming
    description: (* different answer types *);
end;

object TrueFalse is boolean
    description: (* answer for True/False question *);
end;

object MultipleChoice is string*, boolean*
    description: (* answer for Multiple Choice question *);
end;

object Matching is string*, Character*
    description: (* answer for Matching question *);
end;

object Character is string
    description: (* substitute for a char primative *);
end;

object FillIn is string
    description: (* answer Fill In question type *);
end;

object ShortAnswer is string*
    description: (* answer for Short Answer question *);
end;

object Essay is string*
    description: (* answer for Essay question *);
end;

object Programming is string
    description: (* answer for Programming question *);
end;

object ID is integer
    description: (* the unique identifier for a question *);
end;

object Type is string
    description: (* the type of question *);
end;

object QuestionText is string
    description: (* the question to be asked *);
end;

object Difficulty is integer
    description: (* the difficulty of the question, a range from 1 to 10 *);
end;

object Time is integer
    description: (* the expected time to answer the question in minutes *);
end;

object CorrectAnswer inherits from Answer
    description: (* the correct answer to the question *);
end;

object ClassName is string
    description: (* the name of the class that the question is intended for *);
end;

object Topic is string
    description: (* the related topic *);
end;

object Author is string
    description: (* the author of the question *);
end;

object AverageScore is number
    description: (* the average score of the students who have taken the test *);
end;

object Created is Date
    description: (* the creation date of the question *);
end;

object Modified is Date
    description: (* the last modified date of the question *);
end;

object LastUsed is Date
    description: (* the date the question was last added to a test *);
end;

object Notes is string
    description: (* notes about the question *);
end;

object Date is Day, Month, Year
    description: (* the format for date *);
end;

object Day is integer
    description: (* the day component of Date *);
end;

object Month is integer
    description: (* the month component of Date *);
end;

object Year is integer
    description: (* the year component of Date *);
end;

(* begin Joe's section *)

operation CreateQuestion
    inputs:  id:ID, tp:Type, text:QuestionText*, df:Difficulty, tm:Time, ca:CorrectAnswer, cls:ClassName, top:Topic*, auth:Author, crtd:Created, mdf:Modified, nts:Notes;
    outputs:  q:Question;
    description: (*    combines all the fields that make up a Question into a Question object *);
    precondition:
        (* Type must be valid *)
        (tp = "TrueFalse" or tp = "MultipleChoice" or tp = "Matching" or tp = "FillIn" or tp = "ShortAnswer" or tp = "Essay" or tp = "Programming") and
        (* QuestionText cannot be blank *)
        #text >= 1 and
        (* Difficulty must be chosen and must be an integer between 1 and 10, inclusive *)
        df >= 1 and df <= 10 and
        (* Time cannot be blank and must be positive *)
        tm >= 1 and
        (* CorrectAnswer must be chosen/inputted *)
        ca != nil and
        (* ClassName cannot be blank *)
        #cls >= 1;
    postcondition:
        (* A question object is properly created *)
        q.id = id and q.type = tp and q.text = text and q.difficulty = df and q.time = tm and q.ca = ca and q.cn = cls and q.topics = top and q.author = auth and q.created = crtd and q.modified = mdf and q.notes = nts;
end CreateQuestion;


operation AddQuestion
    inputs: q:Question, qb:QuestionBank;
    outputs: qb':QuestionBank;
    description: (* returns the QuestionBank (qb') with the new Question added *);
    precondition:
        (* The QuestionBank exists *)
        qb != nil and
        (* The Question exists (it was created properly) *)
        q != nil and
        (* The ID of the new Question does not refer to a question already in QuestionBank. *)
        contains(qb, q.id) = false;
    postcondition:
        (* The QuestionBank is returned with the new Question added *)
        (forall (q':Question)
            (q' in qb') iff ((q' in qb) or q' = q));
end AddQuestion;


operation EditQuestion
    inputs: qb:QuestionBank, q:Question, id:ID;
    outputs: qb':QuestionBank;
    description:  (* changes the Question in the QuestionBank with the matching ID to the new inputted Question, and returns the updated QuestionBank *);
    precondition:
        (* The QuestionBank exists *)
        qb != nil and
        (* The Question exists (it was created properly) *)
        q != nil and
        (* The ID of the new Question refers to a question already in QuestionBank, and the Type has not changed. *)
        (exists (q' in qb) ((q'.id = id) and (q'.type = q.type)));   
    postcondition:
        (* The QuestionBank (qb') now contains the edited Question *)
        q in qb'
        and
        (* The edited Question is in the QuestionBank if and only if it was previously in the QuestionBank and is not the old question,or if it is the edited Question.    *)
        (forall (q':Question) ((q' in qb') iff ((q' in qb and q'.id != id) or q' = q)));
end EditQuestion;

(*
 * Auxiliary Functions.
 *)
function contains(qb:QuestionBank, id:ID)->(boolean) = exists (q in qb.questions) (q.id = id);

(* end Joe's section *)

end QuestionModule;


Prev:
5.1. InstructorInterface

Up:
5. Formal Specifications
Next:
5.3. QuestionBank