6.2. Roster (roster.rsl)
(****
*
* This file defines the objs and ops related to the roster.
*
*)
object Roster is
components: groups:UserGroup* and cat:SortCat and isVisible:boolean;
end;
object UserGroup is
components: users:User* and sortby:SortBy*;
end;
object User is
components: utype:UserType and
uname:UserName and
pubdrawp:PublicDrawingPerm and
showpubp:ShowPublicDrawingsPerm and
pubnavp:PublicNavigationPerm and
chatp:ChatPerm and
hques:HasQuestion and
online:Online;
end;
object Ascending is boolean;
object SortCat is (unamecat:UserNameCat
or utypecat:UserTypeCat
or onlinecat:OnlineCat
or pubdrawcat:PublicDrawingPermCat
or showpubdrawcat:ShowPublicDrawingsPermCat
or pubnavcat:PublicNavigationPermCat
or chatcat:ChatPermCat
or questioncat:HasQuestionCat);
object SortBy is
components: cat:SortCat and asc:Ascending;
end;
object UserNameCat;
object UserTypeCat;
object OnlineCat;
object PublicDrawingPermCat;
object ShowPublicDrawingsPermCat;
object PublicNavigationPermCat;
object ChatPermCat;
object HasQuestionCat;
object UserType is
components: instructor:Instructor or
student:Student or
guest:Guest;
end;
object Instructor;
object Student;
object Guest;
object UserName is string;
object Online is boolean;
object PublicDrawingPerm is boolean;
object ShowPublicDrawingsPerm is boolean;
object PublicNavigationPerm is boolean;
object ChatPerm is boolean;
object HasQuestion is boolean;
operation setCategory is
inputs: r:Roster, c:SortCat;
outputs: r':Roster;
postcondition: (r'.cat = c);
end;
operation addSortBy is
inputs: r:Roster, g:UserGroup, s:SortBy;
outputs: r':Roster;
precondition:
exists(group in r.groups) (g = group);
postcondition:
(* all groups are the same except the one we're changing *)
forall(gs in (r.groups-g) ) (
exists(g' in r'.groups) (g' = gs)
) and #(r.groups) = #(r'.groups) and
exists(g' in r'.groups) ( (g'.sortby[1] = s) and
if(exists(sortby in g.sortby) (s.cat = sortby.cat)) then
if( g.sortby[1].cat = s.cat ) then
(g'.sortby[1].asc = not g.sortby[1].asc)
else (g'.sortby = s + (g.sortby-s))
else
(g'.sortby = s + g.sortby) and (g'.users = g.users)
);
description:
(* Takes the group that the sortby is being added to, the new sortby to be added and the roster.
If the sortby that is being added is already the first sortby, then toggle the ascending flag.
If the sortby that is being added exists elsewhere in the sortby list then move it to the first
element and leave the rest. If the new sortby isn't in the sortby list then make it the first and
shift the others sortbys over. *);
end;
operation Sort is
inputs: r:Roster;
outputs: r':Roster;
postcondition: (* Roster is grouped by cat and groups are sorted by sortby *)
(* all the users in r must be in r' and none added *)
forall( g in r.groups ) (
forall( u in g.users ) (
exists ( g' in r'.groups ) (
exists (u' in g'.users) (u' = u)
)
)
) and #(AllUsers(r.groups)) = #(AllUsers(r'.groups)) and
if(r.cat?unamecat) then (
(* all the users are in one group and sorted by name *)
(#(r'.groups) = 1) and
forall(u in AllUsers(r.groups)) (
exists(u' in r'.groups[1].users) (u' = u)
) and (#(AllUsers(r.groups)) = #(r'.groups[1].users)) and
GroupSorted(r'.groups[1])
) else if(r.cat?utypecat) then (
(#(r'.groups) = 3) and
forall(u in r'.groups[1].users) (
u.utype?instructor
) and
forall(u in r'.groups[2].users) (
u.utype?student
) and
forall(u in r'.groups[1].users) (
u.utype?guest
) and
GroupSorted(r'.groups[1]) and
GroupSorted(r'.groups[2]) and
GroupSorted(r'.groups[3])
) else (
(#(r'.groups) = 2) and
if(r.cat?onlinecat) then (
forall(u in r'.groups[1].users) (
u.online
) and
forall(u in r'.groups[2].users) (
not u.online
)
) else if(r.cat?pubdrawcat) then (
forall(u in r'.groups[1].users) (
u.pubdrawp
) and
forall(u in r'.groups[2].users) (
not u.pubdrawp
)
) else if(r.cat?showpubdrawcat) then (
forall(u in r'.groups[1].users) (
u.showpubp
) and
forall(u in r'.groups[2].users) (
not u.showpubp
)
) else if(r.cat?pubnavcat) then (
forall(u in r'.groups[1].users) (
u.pubnavp
) and
forall(u in r'.groups[2].users) (
not u.pubnavp
)
) else if(r.cat?chatcat) then (
forall(u in r'.groups[1].users) (
u.chatp
) and
forall(u in r'.groups[2].users) (
not u.chatp
)
) else if(r.cat?questioncat) then (
forall(u in r'.groups[1].users) (
u.hques
) and
forall(u in r'.groups[2].users) (
not u.hques
)
) else (false)
and
GroupSorted(r'.groups[1]) and
GroupSorted(r'.groups[2])
)
;
description:
(* Takes the cat in r and sortbys in r's UserGroups to sort the
roster accordingly. *);
end;
function GroupSorted(g:UserGroup) =
forall(i:integer | (i >= 1) and (i < #(g.users))) (
UserCompare(g.users[i], g.users[i+1], g.sortby);
);
function UserCompare(u1:User, u2:User, s:SortBy*) =
if(#s = 0) then (
true
) else if(s[1].cat?unamecat) then (
if(s[1].asc) then (
if(u1.uname > u2.uname) then (
true
) else if(u1.uname < u2.uname) then (
false
) else (
UserCompare(u1, u2, s[2:#s])
)
) else (
if(u1.uname > u2.uname) then (
false
) else if(u1.uname < u2.uname) then (
true
) else (
UserCompare(u1, u2, s[2:#s])
)
)
) else if(s[1].cat?utypecat) then (
if(s[1].asc) then (
if(u1.utype > u2.utype) then (
true
) else if(u1.utype < u2.utype) then (
false
) else (
UserCompare(u1, u2, s[2:#s])
)
) else (
if(u1.utype > u2.utype) then (
false
) else if(u1.utype < u2.utype) then (
true
) else (
UserCompare(u1, u2, s[2:#s])
)
)
) else if(s[1].cat?onlinecat) then (
if(s[1].asc) then (
if(u1.online > u2.online) then (
true
) else if(u1.online < u2.online) then (
false
) else (
UserCompare(u1, u2, s[2:#s])
)
) else (
if(u1.online > u2.online) then (
false
) else if(u1.online < u2.online) then (
true
) else (
UserCompare(u1, u2, s[2:#s])
)
)
) else if(s[1].cat?pubdrawcat) then (
if(s[1].asc) then (
if(u1.pubdrawp > u2.pubdrawp) then (
true
) else if(u1.pubdrawp < u2.pubdrawp) then (
false
) else (
UserCompare(u1, u2, s[2:#s])
)
) else (
if(u1.pubdrawp > u2.pubdrawp) then (
false
) else if(u1.pubdrawp < u2.pubdrawp) then (
true
) else (
UserCompare(u1, u2, s[2:#s])
)
)
) else if(s[1].cat?showpubdrawcat) then (
if(s[1].asc) then (
if(u1.showpubp > u2.showpubp) then (
true
) else if(u1.showpubp < u2.showpubp) then (
false
) else (
UserCompare(u1, u2, s[2:#s])
)
) else (
if(u1.showpubp > u2.showpubp) then (
false
) else if(u1.showpubp < u2.showpubp) then (
true
) else (
UserCompare(u1, u2, s[2:#s])
)
)
) else if(s[1].cat?pubnavcat) then (
if(s[1].asc) then (
if(u1.pubnavp > u2.pubnavp) then (
true
) else if(u1.pubnavp < u2.pubnavp) then (
false
) else (
UserCompare(u1, u2, s[2:#s])
)
) else (
if(u1.pubnavp > u2.pubnavp) then (
false
) else if(u1.pubnavp < u2.pubnavp) then (
true
) else (
UserCompare(u1, u2, s[2:#s])
)
)
) else if(s[1].cat?chatcat) then (
if(s[1].asc) then (
if(u1.chatp > u2.chatp) then (
true
) else if(u1.chatp < u2.chatp) then (
false
) else (
UserCompare(u1, u2, s[2:#s])
)
) else (
if(u1.chatp > u2.chatp) then (
false
) else if(u1.chatp < u2.chatp) then (
true
) else (
UserCompare(u1, u2, s[2:#s])
)
)
) else if(s[1].cat?questioncat) then (
if(s[1].asc) then (
if(u1.hques > u2.hques) then (
true
) else if(u1.hques < u2.hques) then (
false
) else (
UserCompare(u1, u2, s[2:#s])
)
) else (
if(u1.hques > u2.hques) then (
false
) else if(u1.hques < u2.hques) then (
true
) else (
UserCompare(u1, u2, s[2:#s])
)
)
) else (false);
function AllUsers(g:UserGroup*) =
if(#g = 0) then []
else g[1] + AllUsers(g[2:#g]);
operation showPublicDrawings is
inputs: u:User,
splp:ShowPublicDrawingsPerm;
outputs: u':User;
postcondition: u'.showpubp = splp;
end;
operation setPublicNavigation is
inputs: u:User,
pubnavp:PublicNavigationPerm;
outputs: u':User;
postcondition: u'.pubnavp = pubnavp;
end;
operation setPublicDrawing is
inputs: u:User,
pubdrawp:PublicDrawingPerm;
outputs: u':User;
postcondition: u'.pubdrawp = pubdrawp;
end;
operation setChatPerm is
inputs: u:User,
chatp:ChatPerm;
outputs: u':User;
postcondition: u'.chatp = chatp;
end;
operation setHasQuestion is
inputs: u:User,
hques:HasQuestion;
outputs: u':User;
postcondition: u'.hques = hques;
end;