function registerAction(gb: Gradebook, gb': Gradebook)->boolean = (gb.history.next = gb') and (gb'.history.prev = gb); function itemToString(i: Item)->string; operation Undo inputs: gb:Gradebook; outputs: gb':Gradebook; precondition: gb.history.prev != nil; postcondition: gb' = gb.history.prev; description: (* If one or more operation has been preformed on the Gradebook, remove the most recent change. Otherwise, change nothing. *); end Undo; operation Redo inputs: gb:Gradebook; outputs: gb':Gradebook; precondition: gb.history.next != nil; postcondition: gb' = gb.history.next; description: (* If one or more Undo has been preformed on the Gradebook, re-apply the most recently un-done change. Otherwise, change nothing. *); end Redo; operation Cut inputs: i:Item,clipboard:string; outputs: clipboard':string; precondition: ; postcondition: clipboard' = itemToString(i); description: (* Places the contents of the Item on the operating system's clipboard. *); end Cut; operation Copy inputs: i:Item,clipboard:string; outputs: clipboard': string; precondition: ; postcondition: clipboard' = itemToString(i); description: (* Places the contents of the Item on the operating system's clipboard. *); end Copy; operation Paste inputs: i:Item, clipboard:string; outputs: i':Item; precondition: ; postcondition: i = i' or itemToString(i') = clipboard; description: (* Places the contents of the clipboard in the specified Item. If the clipboard contents were placed there by cut, the source Item is Cleared. *); end Paste; operation Clear inputs: Item; outputs: i':Item; precondition: ; postcondition: i' = nil; description: (* Replaces the contens of the inputted Item with a blank Item. *); end Clear; operation SelectAll inputs: integer, g:Gradebook; outputs: ; precondition: ; postcondition: ((forall (sections in g.sections) forall (student in sections.students) student.selected = true) and (forall (sections in g.sections) forall (groups in sections.groups) forall (student in groups.students) student.selected = true)) or ((forall (item in g.items) item.selected = true) and (g.FinalGrade.selected = true)); description: (* Sets the "selected" variable of all Items within the specified Gradebook which match the type specified by the int to "true." *); end SelectAll; operation Find inputs: g:Gradebook, s:string, e:EasyGrader; outputs: i':Item, e':EasyGrader; precondition: ; postcondition: ((s = itemToString(i') and i' in g.items) or i' = nil) and e'.findString = s; description: (* Searches the Items within the Gradebook for an Item whose contents match the provided string. Returns the first full match. Remember string. *); end Find; operation FindNext inputs: g:Gradebook, e:EasyGrader; outputs: i':Item; precondition: e.findString != nil; postcondition: (e.findString = itemToString(i')) and (i' in g.items); description: (* Searches the Items within the Gradebook for an Item whose contents match the string provided when find was called. Returns the N+1'th match, where N = number of times findNext has been called since the find string was last set. If find string not set, does nothing. *); end FindNext; operation Replace inputs: g:Gradebook, s1:string, s2:string, i:Item; outputs: i':Item; precondition: ; postcondition: itemToString(i) = s1 and itemToString(i') = s2; description: (* Searches the Items within the Gradebook for an Item whose contents match the first string provided. When found, the second strings' contents are written over the first. *); end Replace;