operation addItem inputs: gb:Gradebook, i:Item; outputs: gb':Gradebook; precondition: not (i in gb.items); postcondition: forall (i':Item) (i' in gb'.items) iff ((i' in gb.items) or (i' = i)); description: (* adds an item to the gradebook's hierarchy of items *); end addItem; operation editItem inputs: gb:Gradebook, old:Item, new:Item; outputs: gb':Gradebook; precondition: old in gb.items; postcondition: forall (i':Item) (i' in gb'.items) iff (((i' in gb.items) and (i' != old)) or (i' = new)); description: (* replaces an old version of an item in the gradebook's hierarchy of items with a new version of that item *); end editItem; operation deleteItem inputs: gb:Gradebook, i:Item; outputs: gb':Gradebook; precondition: i in gb.items; postcondition: forall (i':Item) (i' in gb'.items) iff ((i' in gb.items) and (i' != i)); description: (* removes an item from the gradebook's hierarchy of items *); end deleteItem; operation groupItems inputs: gb:Gradebook, cat:Item, i:Item *; outputs: gb':Gradebook; precondition: (not (cat in gb.items)) and (not (cat in i)) and (forall (i' in i) (i' in gb.items)); postcondition: (forall (i':Item) (i' in gb'.items) iff ( ((i' in gb.items) and not (i' in i)) or (i' = cat) )) and (forall (i':Item) (i' in cat.children) iff (i' in i)); description: (* removes items from the gradebook's hierarchy of items, then makes them children of a new item which is then added to the gradebook *); end groupItems; operation ungroupItem inputs: gb:Gradebook, i:Item; outputs: gb':Gradebook; precondition: (i in gb.items) and (#i.children > 0); postcondition: (forall (i':Item) (i' in gb'.items) iff (((i' in gb.items) or (i' in i.children)) and (i' != i))); description: (* takes an item with children [a category] and moves the child items to that item's parent, then removes the item *); end ungroupItem; operation collapseItem inputs: gb:Gradebook, i:Item; outputs: gb':Gradebook; precondition: i in gb.items; postcondition: forall (i':Item) (i' in gb'.items) iff (((i' in gb.items) and (i' != i)) or ( i'.name = i.name and i'.dueDate = i.dueDate and i'.gracePeriod = i.gracePeriod and i'.gracePeriodInherit = i.gracePeriodInherit and i'.latePolicy = i.latePolicy and i'.latePolicyValue = i.latePolicyValue and i'.latePolicyInherit = i.latePolicyInherit and i'.pointsPossible = i.pointsPossible and i'.pointsPossibleInherit = i.pointsPossibleInherit and i'.weight = i.weight and i'.weightPercent = i.weightPercent and i'.weightInherit = i.weightInherit and i'.gradingScheme = i.gradingScheme and i'.gradingSchemeInherit = i.gradingSchemeInherit and i'.extraCredit = i.extraCredit and i'.extraCreditFor = i.extraCreditFor and i'.extraCreditInherit = i.extraCreditInherit and i'.children = i.children and i'.selected = i.selected and i'.hidden = i.hidden and i'.collapsed = true )); description: (* takes an item and collapses it *); end collapseItem; operation expandItem inputs: gb:Gradebook, i:Item; outputs: gb':Gradebook; precondition: i in gb.items; postcondition: forall (i':Item) (i' in gb'.items) iff (((i' in gb.items) and (i' != i)) or ( i'.name = i.name and i'.dueDate = i.dueDate and i'.gracePeriod = i.gracePeriod and i'.gracePeriodInherit = i.gracePeriodInherit and i'.latePolicy = i.latePolicy and i'.latePolicyValue = i.latePolicyValue and i'.latePolicyInherit = i.latePolicyInherit and i'.pointsPossible = i.pointsPossible and i'.pointsPossibleInherit = i.pointsPossibleInherit and i'.weight = i.weight and i'.weightPercent = i.weightPercent and i'.weightInherit = i.weightInherit and i'.gradingScheme = i.gradingScheme and i'.gradingSchemeInherit = i.gradingSchemeInherit and i'.extraCredit = i.extraCredit and i'.extraCreditFor = i.extraCreditFor and i'.extraCreditInherit = i.extraCreditInherit and i'.children = i.children and i'.selected = i.selected and i'.hidden = i.hidden and i'.collapsed = false )); description: (* takes an item and expands it *); end expandItem; operation hideItem inputs: gb:Gradebook, i:Item; outputs: gb':Gradebook; precondition: i in gb.items; postcondition: forall (i':Item) (i' in gb'.items) iff (((i' in gb.items) and (i' != i)) or ( i'.name = i.name and i'.dueDate = i.dueDate and i'.gracePeriod = i.gracePeriod and i'.gracePeriodInherit = i.gracePeriodInherit and i'.latePolicy = i.latePolicy and i'.latePolicyValue = i.latePolicyValue and i'.latePolicyInherit = i.latePolicyInherit and i'.pointsPossible = i.pointsPossible and i'.pointsPossibleInherit = i.pointsPossibleInherit and i'.weight = i.weight and i'.weightPercent = i.weightPercent and i'.weightInherit = i.weightInherit and i'.gradingScheme = i.gradingScheme and i'.gradingSchemeInherit = i.gradingSchemeInherit and i'.extraCredit = i.extraCredit and i'.extraCreditFor = i.extraCreditFor and i'.extraCreditInherit = i.extraCreditInherit and i'.children = i.children and i'.selected = i.selected and i'.hidden = true and i'.collapsed = i.collapsed )); description: (* takes an item and hides it *); end hideItem; operation showItem inputs: gb:Gradebook, i:Item; outputs: gb':Gradebook; precondition: i in gb.items; postcondition: forall (i':Item) (i' in gb'.items) iff (((i' in gb.items) and (i' != i)) or ( i'.name = i.name and i'.dueDate = i.dueDate and i'.gracePeriod = i.gracePeriod and i'.gracePeriodInherit = i.gracePeriodInherit and i'.latePolicy = i.latePolicy and i'.latePolicyValue = i.latePolicyValue and i'.latePolicyInherit = i.latePolicyInherit and i'.pointsPossible = i.pointsPossible and i'.pointsPossibleInherit = i.pointsPossibleInherit and i'.weight = i.weight and i'.weightPercent = i.weightPercent and i'.weightInherit = i.weightInherit and i'.gradingScheme = i.gradingScheme and i'.gradingSchemeInherit = i.gradingSchemeInherit and i'.extraCredit = i.extraCredit and i'.extraCreditFor = i.extraCreditFor and i'.extraCreditInherit = i.extraCreditInherit and i'.children = i.children and i'.selected = i.selected and i'.hidden = false and i'.collapsed = i.collapsed )); description: (* takes an item and shows it *); end showItem; operation changeTurnInDate inputs: s:Score, d:Date; outputs: s':Score; precondition:; postcondition: s'.turnInDate = d; description: (* takes a score and changes its turn-in date *); end changeTurnInDate; operation addStudent inputs: s:Section, st:Student; outputs: s':Section; precondition: not ((st in s.students) or (exists (g:Group) ((g in s.groups) and (st in g.students)))); postcondition: forall (st':Student) (st' in s'.students) iff (((st' in s.students) or (exists (g:Group) ((g in s.groups) and (st' in g.students)))) or (st' = st)); description: (* adds a student to a specified section of a class *); end addStudent; operation editStudent inputs: s:Section, old:Student, new:Student; outputs: s':Section; precondition: ((old in s.students) or (exists (g:Group) ((g in s.groups) and (old in g.students)))); postcondition: (forall (st:Student) (st in s'.students) iff (((st in s.students) and (st != old)) or (st = new))) and (forall (g:Group | g in s'.groups) forall (st:Student) ((st in g.students) iff (((st in g.students) and (st != old)) or (st = new)))); description: (* replaces an old version of a student in a section with a new version of that student *); end editStudent; operation deleteStudent inputs: s:Section, st:Student; outputs: s':Section; precondition: ((st in s.students) or (exists (g:Group) ((g in s.groups) and (st in g.students)))); postcondition: (forall (st':Student) (st' in s'.students) iff ((st' in s.students) and (st' != st))) and (forall (g:Group | g in s'.groups) forall (st':Student) ((st' in g.students) iff ((st' in g.students) and (st' != st)))); description: (* removes a student from a section *); end deleteStudent; operation groupStudents inputs: s:Section, g:Group, st:Student *; outputs: s':Section; precondition: (not (g in s.groups)) and (forall (st' in st) (st' in s.students)); postcondition: (forall (st':Student) (st' in s'.students) iff ((st' in s.students) and not (st' in st))) and (forall (g':Group) (g' in s'.groups) iff ((g' in s.groups) or (g' = g))) and (forall (st':Student) (st' in g.students) iff (st' in st)); description: (* creates a new group, and moves students out of the section into the group *); end groupStudents; operation ungroupStudents inputs: s:Section, g:Group; outputs: s':Section; precondition: (g in s.groups); postcondition: (forall (st:Student) (st in s'.students) iff ((st in s.students) or (st in g.students))) and (forall (g':Group) (g' in s'.groups) iff ((g' in s.groups) and (g' != g))); description: (* takes a group of students, moves the students out of the group into the section, and removes the group *); end ungroupStudents; operation collapseGroup inputs: s:Section, g:Group; outputs: s':Section; precondition: (g in s.groups); postcondition: forall (g':Group) (g' in s'.groups) iff (((g' in s.groups) and (g' != g)) or ( g'.name = g.name and g'.students = g.students and g'.selected = g.selected and g'.collapsed )); description: (* takes a group and collapses it *); end collapseGroup; operation expandGroup inputs: s:Section, g:Group; outputs: s':Section; precondition: (g in s.groups); postcondition: forall (g':Group) (g' in s'.groups) iff (((g' in s.groups) and (g' != g)) or ( g'.name = g.name and g'.students = g.students and g'.selected = g.selected and not g'.collapsed )); description: (* takes a group and expands it *); end expandGroup;