5.4. Tutorial browser (tutorial-browser.rsl)
module Student;
from Admin import Accounts;
from Login import LoginCookie;
from Data import all;
from Page import all;
from tutorial import all;
export all;
(*****************************************************************************)
object TutorialBrowser is
components:
browseTab:BrowseTab and
searchTab:SearchTab and
historyTab:HistoryTab;
description: (*
Highest-level model of the Tutorials window in the Student interface.
Consists of three tabs used in tutorial location.
*);
end TutorialBrowser;
(*****************************************************************************)
object BrowseTab is
components:
departmentGroups:DepartmentGroup*;
description: (*
The main Tutorials tab, this contains all tutorials in the database,
arranged by department.
*);
end BrowseTab;
object DepartmentGroup is
components:
departmentName:DepartmentName and
courseGroups:CourseGroup*;
description: (*
Further subdivides the tutorials in a department by course.
*);
end DepartmentGroup;
object CourseGroup is
components:
courseNumber:CourseNumber and
authorGroups:AuthorGroup*;
description: (*
The CourseGroup is used to group tutorials by author. It consists of a
CourseNumber and a collection of AuthorGroups.
*);
end Course;
object AuthorGroup is
components:
authorID:UserID and
tutorialGroups:TutorialGroup* and
tutorials:TutorialRecord*;
description: (*
The AuthorGroup contains all tutorials for a particular class written by
the same author. It consists of an authorID and a collection of
TutorialGroups and TutorialRecords.
*);
end AuthorGroup;
object TutorialGroup is
components:
tutorialGroups:TutorialGroup* and
tutorials:TutorialRecord*;
description: (*
A TutorialGroup is used to subdivide tutorials written by a particular
author into additional categories. It is analogous to a file folder,
consiting of a collection of TutorialGroups and TutorialRecords.
*);
end TutorialGroup;
(*****************************************************************************)
object SearchTab is
components:
searchName:SearchString and
searchKeywords:SearchString and
searchDepartmentName:SearchString and
searchCourseNumber:SearchInteger and
searchAuthorFirstName:SearchString and
searchAuthorLastName:SearchString;
description: (*
This Tutorials tab allows the user to search for tutorials by specifying
certain search parameters.
*);
end SearchTab;
object SearchString is string
description: (*
A generic string used for a parameter in the tutorial search operation.
*);
end SearchString;
object SearchInteger is integer
description: (*
A generic integer used for a parameter in the tutorial search operation.
*);
end SearchInteger;
operation FindTutorial is
inputs:
cookie:LoginCookie and
accounts:Accounts and
tutorialDB:TutorialDB and
pageDB:PageDB and
searchName:SearchString and
searchKeywords:SearchString and
searchDepartmentName:SearchString and
searchCourseNumber:SearchInteger and
searchAuthorFirstName:SearchString and
searchAuthorLastName:SearchString;
outputs:
matchingTutorials:TutorialRecord*;
precondition: cookie.isConnected;
postcondition:
(* Skip a parameter if it is not supplied, otherwise assert that the
parameter matches the corresponding aspect of the file *)
forall (tutorialRecord in matchingTutorials) (
(searchName = nil or StringContains(tutorialRecord.tutorial.title, searchName)) and
(searchKeywords = nil or TutorialContains(tutorialRecord, searchKeywords)) and
(searchDepartmentName = nil or StringContains(tutorialRecord.class.departmentName, searchDepartmentName)) and
(searchCourseNumber = nil or tutorialRecord.class.courseNumber = searchCourseNumber) and
(searchAuthorFirstName = nil or GetFirstName(accounts, tutorialRecord.authorID) = searchAuthorFirstName) and
(searchAuthorLastName = nil or GetLastName(accounts, tutorialRecord.authorID) = searchAuthorLastName)
);
description: (*
Given some identifying properties for tutorials, FindTutorial retrieves
zero or more tutorials that match the specified parameters. Any parameter
that is left blank will be ignored.
*);
end FindTutorial;
(* Returns true if s2 is a substring of s1, false otherwise *)
function StringContains(s1:string, s2:string)->boolean =
(exists (x:integer | (x >= 1) and (x + #s2 <= #s1) ) s1[x : (x + #s2)] = s2);
(* Returns true if any of the pages in the tutorial contains all of the space-
separated keywords, false otherwise *)
function TutorialContains(t:TutorialRecord, k:string)->boolean =
...;
(* Returns the first name of the user in Accounts with the specified UserID, or
nil if no such user exists *)
function GetFirstName(a:Accounts, uid:UserID)->string =
...;
(* Returns the last name of the user in Accounts with the specified UserID, or
nil if no such user exists *)
function GetLastName(a:Accounts, uid:UserID)->string =
...;
(*****************************************************************************)
object HistoryTab is
components:
favoriteTutorials:FavoriteTutorials and
tutorialsInProgress:TutorialsInProgress and
completedTutorials:CompletedTutorials;
description: (*
This Tutorials tab allows the user to browse their tutorial history,
including completed, incomplete, and bookmarked tutorials.
*);
end HistoryTab;
object FavoriteTutorials is
components:
tutorialIDs:TutorialID*;
description: (*
This subfolder of the History tab holds all tutorials that the user has
bookmarked as 'Favorites'.
*);
end FavoriteTutorials;
operation AddFavorite is
inputs:
cookie:LoginCookie and
ft:FavoriteTutorials and
newID:TutorialID;
outputs:
ft':FavoriteTutorials;
precondition:
cookie.isConnected and
cookie.isAuthenticated and
(not exists (tID in ft.tutorialIDs) tID = newID);
postcondition:
forall (tID':TutorialID) (tID' in ft') iff ((tID' = newID) or (tID' in ft));
description: (*
Adds a tutorial to the Favorites folder if it is not already there.
*);
end AddFavorite;
operation RemoveFavorite is
inputs:
cookie:LoginCookie and
ft:FavoriteTutorials and
pageID:PageID;
outputs:
ft':FavoriteTutorials;
precondition:
cookie.isConnected and
cookie.isAuthenticated and
pageID in ft;
postcondition:
forall (pID':PageID) (pID' in ft') iff ((pID' != pageID) or (pID' in ft));
description: (*
Removes a tutorial from the Favorites folder.
*);
end RemoveFavorite;
object TutorialsInProgress is
components:
pageIDs:PageID*;
description: (*
This subfolder of the History tab holds all tutorials that the user has
begun but has not navigated to completion.
*);
end TutorialsInProgress;
object CompletedTutorials is
components:
pageIDs:PageID*;
description: (*
This subfolder of the History tab holds all tutorials that the user has
fully completed.
*);
end CompletedTutorials;
operation CompleteTutorial is
inputs:
cookie:LoginCookie and
tip:TutorialsInProgress and
ct:CompletedTutorials and
pID:PageID;
outputs:
tip':TutorialsInProgress and
ct':CompletedTutorials;
precondition:
cookie.isConnected and
cookie.isAuthenticated;
postcondition:
(forall (pID':PageID) (pID' in tip') iff ((pID' != pID) or (pID' in tip))) and
(forall (pID':PageID) (pID' in ct' ) iff ((pID' = pID) or (pID' in ct )));
description: (*
Moves a tutorial from the Tutorials In Progress list to the Completed Tutorials list.
Precondition has been left open because it is not necessary for a tutorial to be on
the Tutorials In Progress list when completed, even though this should always be the
case.
*);
end CompleteTutorial;
(*****************************************************************************)
end Student;
Prev: Tutorials
| Next: Tutorial viewer
| Up: spec
| Top: index