(* * 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;