Out: Monday, November 14, 2016
Due: Monday, November 28, 2016 at 600pm local time.
The goal of this problem set is to give you practice with stateful classes, and pulling and pushing information. It is also intended to give you practice with reusing code from previous problem sets.
Please restrict yourself to the language features discussed in class. You may use state. You may not use class inheritance, but you may use interface inheritance.
Otherwise, the deliverables and instructions for this problem set are the same as for Problem Set 09. As always, you must follow the design recipe, in this case the OO Design Recipe and deliverables as spelled out in Lesson 9.5 and in deliverables.html. Be sure to sync your work and fill out a Work Session Report at the end of every work session. Use the Work Session Report for PS 10.
As with ps09, you may submit your solution in multiple files. See details below.
;;; Function: ;; container-init : NonNegInt NonNegInt -> Container ;; GIVEN: the width and height of a canvas ;; RETURNS: a Container, initially empty, but which, when run, will ;; create a canvas of the given width and height and which will send events ;; to the Widgets and SWidgets that are added to it. ;;; Interfaces: ;; A Container is an object of any class that implements Container<%> (define Container<%> (interface () ; Widget -> Void ; GIVEN: A widget ; EFFECT: adds the given widget to this container add-widget ; SWidget -> Void ; GIVEN: A stateful widget ; EFFECT: adds the given swidget to this container add-stateful-widget ; PosReal -> Void ; GIVEN: a framerate, in secs/tick ; EFFECT: runs the widgets and stateful widgets in this framework ; at the given framerate. run )) ;; A Widget is an object of any class that implements Widget<%> (define Widget<%> (interface () ; -> Widget ; GIVEN: no arguments ; RETURNS: the state of this object that should follow at time t+1. after-tick ; Integer Integer -> Widget ; GIVEN: a location ; RETURNS: the state of this object that should follow the ; specified mouse event at the given location. after-button-down after-button-up after-drag after-move ; KeyEvent -> Widget ; GIVEN: a key event and a time ; RETURNS: the state of this object that should follow the ; given key event after-key-event ; Scene -> Scene ; GIVEN: a scene ; RETURNS: a scene like the given one, but with this object ; painted on it. add-to-scene )) ;; An SWidget is an object of any class that implements the SWidget<%> ;; interface. ;; A SWidget is like a Widget, but it is stable (stateful). (define SWidget<%> (interface () ; -> Void ; GIVEN: no arguments ; EFFECT: updates this widget to the state it should have ; following a tick. after-tick ; Integer Integer -> Void ; GIVEN: a location ; EFFECT: updates this widget to the state it should have ; following the specified mouse event at the given location. after-button-down after-button-up after-drag after-move ; KeyEvent -> Void ; GIVEN: a key event ; EFFECT: updates this widget to the state it should have ; following the given key event after-key-event ; Scene -> Scene ; GIVEN: a scene ; RETURNS: a scene like the given one, but with this object ; painted on it. add-to-scene ))
You are relieved to see that these interfaces are much like the ones you've been working with. Just as the salesman said, you run your widgets and swidgets by creating a Container, adding your widgets and swidgets to it, and then calling the run method on your container. You no longer need to call big-bang yourself.
Your job is to reimplement the toy from problem set 9, but using the WidgetWorks framework and stateful objects. The specifications and deliverables are exactly the same, except that:
run : PosNum -> Void GIVEN: a frame rate (in seconds/tick) EFFECT: This function creates a Container, and places a MetaToy with no toys in that Container. The function may or may not put other Widgets and SWidgets in the container, depending on the implementation. The function then runs the Container at the given frame rate using WidgetWorks.Note that this change relaxes the previous contract, since now any value is acceptable as a return value from run.
Turn in your solution as a file named "q1.rkt". Put a copy of WidgetWorks.rkt in the directory with your solution. YOU MAY NOT MODIFY WidgetWorks.rkt IN ANY WAY. WE MAY TEST YOUR SOLUTION WITH OUR OWN IMPLEMENTATION OF Container<%>.
Hint: in the Week 10 examples, each SBall took the wall as one of its init-fields, and registered itself with the wall during its initialization. The contracts in ps09 rule out an analogous "self-registration" strategy here. So you will have to make the object that creates the toys subscribe each toy to the relevant notification or notifications. Be sure you can explain your registration strategy at codewalk. If this hint is mysterious when you read it, check back when you try to implement make-throbber, etc. ADDED MON 11/21/16: Now that I look at it, I think this hint is more misleading than helpful. So you can safely ignore it. See @1044. Sorry about that. -Prof. Wand
Here's a demonstration:
Your solution should be a file named q2.rkt that provides the following two functions and one interface:
cubelets-init : -> Container GIVEN: no arguments RETURNS: a Container, initially with no blocks, which when run, will run in a 600x500 canvas and process the events in the description above. make-block : NonNegInt NonNegInt ListOfSBlock -> SBlock GIVEN: an x and y position, and a list of blocks WHERE: the list of blocks is the list of blocks already on the playground. RETURNS: a new block, at the given position, with no teammates NOTE: it is up to you as to whether you use the third argument or not. Some implementations may use the third argument; others may not. You must provide an interface named SBlock<%>. Your SBlock<%> interface should inherit from the SWidget<%> interface and add AT LEAST the following methods: get-team : -> ListOfSBlock RETURNS: the teammates of this sblock add-teammate: SBlock -> Void EFFECT: adds the given sblock to this block's team sblock-x : -> Integer sblock-y : -> Integer RETURNS: the x or y coordinates of this sblock
You may put more methods in the SBlock<%> interface if you so desire. Remember that a method must appear in the interface if and only if it is called from outside this object.
There are several places where information must be disseminated in this problem, either by pushing or pulling. Be prepared to identify these and to discuss your design decisions about each of them.
As in the problem above, you must use WidgetWorks.rkt .
Last modified: Mon Nov 21 08:52:52 Eastern Standard Time 2016