(*
* Module QuestionBank defines the objects and operations related
to maintaining
* a Question Bank and Question Bank management.
*)
module QuestionBankModule;
from QuestionModule import Question, ID, Type, QuestionText,
Difficulty, Time, CorrectAnswer, ClassName, Topic, Author,
AverageScore, Created, Modified, LastUsed, Notes, Answer;
export QuestionBank, LocalQuestionBank,
SharedQuestionBank,
QuestionBankSettings,
LocalQuestionBankSettings, SharedQuestionBankSettings,
LocalBankProfile, BankName,
BankLocation,
SharedBankProfile, BankUserList,
BankAdministrator, BankUR, Username, Password;
object QuestionBank is
components: questions:Question*;
operations: AddQuestion, EditQuestion,
DeleteQuestions, FilterQuestions;
description: (*
*);
end QuestionBank;
object LocalQuestionBank inherits from QuestionBank
operations: UploadQuestion;
description: (*
*);
end LocalQuestionBank;
object SharedQuestionBank inherits from QuestionBank
components: BankUserList;
operations: DownloadQuestion;
description: (*
*);
end SharedQuestionBank;
(*---------------------- begin Kate's section -----------------------*)
operation DeleteQuestions is
inputs: id: ID*, a: Author*, qb: QuestionBank;
outputs: qb' : QuestionBank;
description: (* This operation delets questions from
the QuestionBank. It return a QuestionBank without the deleted
questions in it *);
precondition:
(forall (idx in id)
(forall (authx
in a)
(forall (q:
Question)
exists (q in
qb )((q.id = idx) and (q.author = authx) ) )));
postcondition:
(*The unwanted quesitons are
deleted from the QuestionBank*)
(forall (q': Question)
(forall (authx in a)
(forall (idx in id)
(q' in qb')
iff ((idx != q'.id) and (authx != q'.author) and (q' in qb)))));
end DeleteQuestions;
operation UploadQuestions is
inputs: id: ID*, a: Author*, lqb: LocalQuestionBank,
sqb: SharedQuestionBank;
outputs: sqb' :
SharedQuestionBank;
description: (*This operation uploads questions from
the local QuestionBank to the shared QuestionBank; after
the operation,
the shared question bank will now contain the new questions*);
precondition:
(forall (q: Question)
(forall (authx in a)
(forall (idx in id)
exists (q in lqb) ((q.id = idx)
and (q.author = authx)))));
postcondition:
(*The desired questions are
uploaded from the shared QuestionBank to the local QuestionBank*)
(forall (q' : Question)
(forall (authx in a)
(forall (idx in id)
(q' in
sqb'.questions) iff ((q' in sqb.questions) or ((idx =q'.id) and (authx
= q'.author) and (q' in lqb.questions))))));
end UploadQuestions;
operation DownloadQuestions is
inputs: id: ID*, a: Author*, lqb: LocalQuestionBank,
sqb: SharedQuestionBank;
outputs: lqb': LocalQuestionBank;
description: (*This operation downloads questions
from the shared QuestionBank to the local QuestionBank, after
this operation
is performed the local question bank will contain the new questions*);
precondition:
(forall (q: Question)
(forall (authx in a)
(forall (idx in id)
exists (q in
sqb.questions) ((q.id = idx) and (q.author = authx)))));
postcondition:
(*The desired questions are
downloaded from the local QuestionBank to the shared QuestionBank*)
(forall (q' : Question)
(forall (authx in a)
(forall (idx in id)
(q' in
lqb'.questions) iff ((q' in lqb.questions) or ((idx =q'.id) and (authx
= q'.author) and (q' in sqb.questions))))));
end DownloadQuestions;
operation FilterQuestions is
inputs: qb: QuestionBank, f: Filter;
outputs: ql : QuestionList;
description: (* Displays questions with certain
selected attributes, while hiding others*);
precondition:
qb != nil;
postcondition:
(*Undesired questions are hidden,
while the desired questions are displayed*)
(forall(q: Question)
exists (q in qb.questions)
(q.cn in
f.class) or
(q.author in
f.author) or
(q.type in
f.type) or
((*f.keyword
in q.notes*) (f.keyword in q.topics)));
end FilterQuestions;
operation ShowDetails is
inputs: q: Question;
outputs: dp: DetailPanel;
description: (*Clicking on the question row fills in
the ShowDetails *);
precondition:
(forall(qb: QuestionBank)
(q in qb));
postcondition:
(*The DetailPanel is filled in
with the attributes of the selected question*)
(dp.answer = q.ca) and
(dp.class = q.cn) and
(dp.topics = q.topics) and
(dp.author = q.author) and
(dp.as = q.as) and
(dp.created = q.created) and
(dp.modified = q.modified) and
(dp.lu = q.lu) and
(dp.notes = q.notes);
end ShowDetails;
operation SortedByTypeAscending is
inputs: ql:QuestionList;
outputs: ql':QuestionList;
description: (* Sorts the list of questions by their
type field *);
precondition:
#ql > 0;
postcondition:
(forall (q:Question) ((q in ql)
iff (q in ql'))) and
(forall (i:integer | i >= 1
and i < #ql)
(ql'[i].type
< ql'[i + 1].type));
end SortedByTypeAscending;
operation SortedByDifficultyAscending is
inputs: ql:QuestionList;
outputs: ql':QuestionList;
description: (* Sorts the list of questions by their
difficulty field *);
precondition:
#ql > 0;
postcondition:
(forall (q:Question) ((q in ql)
iff (q in ql'))) and
(forall (i:integer | i >= 1
and i < #ql)
(ql'[i].difficulty < ql'[i + 1].difficulty));
end SortedByDifficultyAscending;
operation SortedByTimeAscending is
inputs: ql:QuestionList;
outputs: ql':QuestionList;
description: (* Sorts the list of questions by their
time field *);
precondition:
#ql > 0;
postcondition:
(forall (q:Question) ((q in ql)
iff (q in ql'))) and
(forall (i:integer | i >= 1
and i < #ql)
(ql'[i].time
< ql'[i + 1].time));
end SortedByTimeAscending;
operation SortedByQuestionAscending is
inputs: ql:QuestionList;
outputs: ql':QuestionList;
description: (* Sorts the list of questions by their
question text field *);
precondition:
#ql > 0;
postcondition:
(forall (q:Question) ((q in ql)
iff (q in ql'))) and
(forall (i:integer | i >= 1
and i < #ql)
(ql'[i].text
< ql'[i + 1].text));
end SortedByQuestionAscending;
object DetailPanel is answer:Answer, class:ClassName, topics:Topic*,
author:Author, as:AverageScore, created:Created, modified:Modified,
lu:LastUsed, notes:Notes
description: (*The Detail Panel lists more detailed
question attributes*);
end;
object Filter is type:TypeFilter, class:ClassFilter,
author:AuthorFilter, keyword:KeywordFilter
description: (* Each filter type allows the user to
display or hide questions
posessing that
property*);
end;
object TypeFilter is Type*
description: (* TypeFilter allows the user to hide
or display questions based on
what answer
type is assosiated with the question*);
end;
object ClassFilter is ClassName*
description: (* ClassFilter allows the user to hide
or display questions based on
what class
name is assosiated with the question*);
end;
object AuthorFilter is Author*
description: (* AuthorFilter allows the user to hide
or display questions based on
the author of
the question*);
end;
object KeywordFilter is string
description: (* KeywordFilter allows the user to
hide or display questions based on
what words are
contained in the question text filed, the notes field,
and the answer
field*);
end;
object QuestionList is Question*
description: (* This is the list of questions that
is displayed in the table of the question bank view.
This way, you can filter and sort
the questions without affecting the underlying Question Bank,
since those only affect how they
are shown to the user. *);
end;
(*--------------------------- end Kate's section
-----------------------*)
(*--------------------------- begin Adam's section
---------------------*)
object QuestionBankSettings is Lqbs:LocalQuestionBankSettings,
Sqbs:SharedQuestionBankSettings;
object LocalQuestionBankSettings is
components: Lbp:LocalBankProfile*;
operations: AddLocalQB, EditLocalQB,
DeleteSharedQB, MoveUp, MoveDown;
end LocalQuestionBankSettings;
object LocalBankProfile is bn:BankName, bl:BankLocation,
lqb:LocalQuestionBank;
object SharedQuestionBankSettings is
components: sbp:SharedBankProfile*;
operations: AddSharedQB, EditSharedQB,
DeleteSharedQB, MoveUp, MoveDown;
end SharedQuestionBankSettings;
object SharedBankProfile is bn:BankName, bl:BankLocation,
bul:BankUserList, un:Username, pw:Password, sqb:SharedQuestionBank;
object BankUserList is
components: bur:BankUR*, ba:BankAdministrator;
operations: AddUser, DeleteUser, SwitchAdmin;
end BankUserList;
object BankUR is un:Username, pw:Password;
object Username is string;
object ConfirmPassword is string;
object Password is string;
object BankName is string;
object BankLocation is string;
object BankAdministrator is string;
operation CreateLocal is
inputs: Lqbs:LocalQuestionBankSettings, BankName,
BankLocation;
outputs: Lqbs':LocalQuestionBankSettings;
end CreateLocal;
operation AddSharedQB is
inputs: Sqbs: SharedQuestionBankSettings,
sbp:SharedBankProfile;
outputs: Sqbs':SharedQuestionBankSettings;
precondition:
(* BankName, BankLocation,
Username, and Password are non-empty *)
#(sbp.bn) >= 1 and
#(sbp.bl) >= 1 and
#(sbp.un) >= 1 and
#(sbp.pw) >= 1;
postcondition:
(* Question Bank is added to the
Shared Question Bank list *)
sbp in Sqbs';
end AddSharedQB;
operation AddLocalQB is
inputs: Lqbs:LocalQuestionBankSettings,
lbp:LocalBankProfile;
outputs: Lqbs':LocalQuestionBankSettings;
precondition:
(* BankName, BankLocation are
non-empty *)
#(lbp.bn) >= 1 and
#(lbp.bl) >= 1;
postcondition:
(* Question Bank is added to the
Local Question Bank list *)
lbp in Lqbs';
end AddLOcalQB;
operation EditSharedQB is
inputs: Sqbs:SharedQuestionBankSettings,
sbp:SharedBankProfile;
outputs: Sqbs':SharedQuestionBankSettings;
precondition:
(* BankName, BankLocation,
Username, and Password are non-empty *)
#(sbp.bn) >= 1 and
#(sbp.bl) >= 1 and
#(sbp.un) >= 1 and
#(sbp.pw) >= 1;
postcondition:
(* Question Bank is updated in
the Shared Question Bank list *)
sbp in Sqbs';
end EditSharedQB;
operation EditLocalQB is
inputs: Lqbs:LocalQuestionBankSettings,
lbp:LocalBankProfile;
outputs: Lqbs':LocalQuestionBankSettings;
precondition:
(* BankName, BankLocation are
non-empty *)
#(lbp.bn) >= 1 and
#(lbp.bl) >= 1;
postcondition:
(* Question Bank is updated in
the Shared Question Bank list *)
lbp in Lqbs';
end EditLocalQB;
operation DeleteLocalQB is
inputs: Lqbs:LocalQuestionBankSettings,
Lbp:LocalBankProfile;
outputs: Lqbs':LocalQuestionBankSettings;
precondition:
(* Question Bank must exist in
Question Bank Settings *)
Lbp != nil and
Lbp in Lqbs;
postcondition:
(* Question Bank is deleted from
Local Question Bank list *)
not(Lbp in Lqbs');
end DeleteLocalQB;
operation DeleteSharedQB is
inputs: Sqbs:SharedQuestionBankSettings,
Sbp:SharedBankProfile;
outputs: Sqbs':SharedQuestionBankSettings;
precondition:
(* Question Bank must exist in
Question Bank Settings *)
Sbp != nil and
Sbp in Sqbs;
postcondition:
(* Question Bank is deleted from
Shared Question Bank list *)
not(Sbp in Sqbs');
end DeleteSharedQB;
operation AddUser is
inputs: bul:BankUserList, un:Username,
pw:Password, cpw:ConfirmPassword;
outputs: bul':BankUserList;
precondition:
(* Username cannot exist in bank
users list and password and confirm password must match *)
(not (exists (bur:BankUR) (bur in
bul.bur) and (bur.un = un))) and
(#pw >= 1 and #cpw >=1 and
pw = cpw);
postcondition:
(* BankUR has been added to bank
user list *)
forall(bur:BankUR)
(bur in bul'.bur) iff (bur in
bul.bur) or ((bur.un) = un and (bur.pw) = pw);
end AddUser;
operation DeleteUser is
inputs: bul:BankUserList, un:Username;
outputs: bul':BankUserList;
precondition:
(* User must exist in Bank Users
List *)
(un != nil) and (exists(r in
bul.bur) (r.un = un));
postcondition:
(* User record with matching user
name no longer exists in the bank user list *)
forall(bur:BankUR)
(bur in bul'.bur) iff ((bur in
bul.bur) and (bur.un != un));
end DeleteUser;
operation SwitchAdmin is
inputs: Bul:BankUserList, bur:BankUR;
outputs: Bul':BankUserList;
precondition:
(* User record needs to be in
user list *)
(* (exists(r in Bul)) r.un =
bur.un *);
postcondition:
(* User is now the administrator
*)
forall(ur:UserRecord)
(ur in
Bul'.bur) iff (ur in Bul.bur)
and
(Bul'.ba = bur.un);
end SwitchAdmin;
operation FileDirectory is
inputs: qb:QuestionBank, ln:BankLocation;
outputs: ln':BankLocation;
precondition:
(* Question Bank must exist in
folder *);
postcondition:
(* Location is the path of the
Question Bank *);
end FileDirectory;
operation MoveUp is
inputs: sbp:SharedBankProfile,
Sqbs:SharedQuestionBankSettings;
outputs: Sqbs':SharedQuestionBankSettings;
precondition:
(* selected profile exists *)
(exists (sbp' in Sqbs) (sbp.bn =
sbp'.bn)) and
Sqbs[1] != sbp;
postcondition:
(* Question Bank moves up on
Question Bank list *)
forall
(profile:SharedBankProfile) ((profile in Sqbs) iff (profile in Sqbs'));
end Moveup;
(*----------------------------- end Adam's section
--------------------------*)
end QuestionBankModule;
Prev: 5.2. Question |
Up: 5. Formal Specifications |
Next: 5.4. StudentInterface |