From df9ce08681f336b653e0b4187ff8cfebbd28d53f Mon Sep 17 00:00:00 2001 From: Matthias Felleisen Date: Thu, 2 Oct 2008 20:21:15 +0000 Subject: [PATCH] revised world documentation svn: r11926 --- collects/teachpack/door-real.png | Bin 0 -> 4851 bytes collects/teachpack/door-sim.png | Bin 0 -> 5106 bytes .../teachpack/htdp/scribblings/world.scrbl | 343 +++++++++++++++++- collects/teachpack/world.png | Bin 0 -> 19925 bytes 4 files changed, 330 insertions(+), 13 deletions(-) create mode 100644 collects/teachpack/door-real.png create mode 100644 collects/teachpack/door-sim.png create mode 100644 collects/teachpack/world.png diff --git a/collects/teachpack/door-real.png b/collects/teachpack/door-real.png new file mode 100644 index 0000000000000000000000000000000000000000..1514131ad0aeffea24c079438aabb3d0c6832c2d GIT binary patch literal 4851 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 literal 0 HcmV?d00001 diff --git a/collects/teachpack/door-sim.png b/collects/teachpack/door-sim.png new file mode 100644 index 0000000000000000000000000000000000000000..014d4a7a9a6b82b5c470cdadbc0fe70e5c5fc860 GIT binary patch literal 5106 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 VLR-v6f^T_{uI4S&2c&h-{{ShH!E^us literal 0 HcmV?d00001 diff --git a/collects/teachpack/htdp/scribblings/world.scrbl b/collects/teachpack/htdp/scribblings/world.scrbl index 3c2842257a..f99fde8905 100644 --- a/collects/teachpack/htdp/scribblings/world.scrbl +++ b/collects/teachpack/htdp/scribblings/world.scrbl @@ -1,6 +1,8 @@ #lang scribble/doc -@(require scribble/manual "shared.ss" +@(require scribble/manual + "shared.ss" + scribble/struct (for-label scheme teachpack/htdp/image teachpack/htdp/world @@ -10,9 +12,15 @@ @emph{Note}: For a quick and educational introduction to the teachpack, see @link["http://www.ccs.neu.edu/home/matthias/HtDP/Prologue/book.html"]{How -to Design Programs, Second Edition: Prologue}. The purpose of this -documentation is to give experienced Schemers a concise overview for using -the library and for incorporating it elsewhere. +to Design Programs, Second Edition: Prologue}. As of August 2008, we also +have a series of projects available as a small booklet on +@link["http://world.cs.brown.edu/"]{How to Design Worlds}. + +The purpose of this documentation is to give experienced Schemers a concise +overview for using the library and for incorporating it elsewhere. The last +section presents a working example for an extremely simple domain and is +suited for a novice who knows how to design conditional functions for +symbols. The teachpack provides two sets of tools. The first allows students to create and display a series of animated scenes, i.e., a simulation. The @@ -20,6 +28,7 @@ second one generalizes the first by adding interactive GUI features. @declare-exporting[teachpack/htdp/world #:use-sources (teachpack/htdp/image)] +@; ----------------------------------------------------------------------------- @section[#:tag "basics"]{Basics} The teachpack assumes working knowledge of the basic image manipulation @@ -48,6 +57,7 @@ pinholes are at position @scheme[(0,0)]. @scheme[(x,y)] are comp. graph. coordinates, i.e., they count right and down from the upper-left corner.} +@; ----------------------------------------------------------------------------- @section[#:tag "simulations"]{Simple Simulations} @defproc[(run-simulation @@ -86,13 +96,28 @@ Example: @;----------------------------------------------------------------------------- @section[#:tag "interactive"]{Interactions} -An animation starts from a given ``world'' and generates new ones in response to events on the -computer. This teachpack keeps track of the ``current world'' and recognizes three kinds of events: -clock ticks; keyboard presses and releases; and mouse movements, mouse clicks, etc. Your program may -deal with such events via the @emph{installation} of @emph{handlers}. The teachpack provides for the -installation of three event handlers: @scheme[on-tick-event], @scheme[on-key-event], and -@scheme[on-mouse-event]. In addition, it provides for the installation of a @scheme[draw] handler, -which is called every time your program should visualize the current world. +An animation starts from a given ``world'' and generates new ones in + response to events on the computer. This teachpack keeps track of the + ``current world'' and recognizes three kinds of events: clock ticks; + keyboard presses and releases; and mouse movements, mouse clicks, + etc. + +Your program may deal with such events via the @emph{installation} of + @emph{handlers}. The teachpack provides for the installation of three + event handlers: @scheme[on-tick-event], @scheme[on-key-event], and + @scheme[on-mouse-event]. In addition, it provides for the installation of + a @scheme[draw] handler, which is called every time your program should + visualize the current world. + +The following picture provides an intuitive overview of the workings of + "world". + +@image["world.png"] + + The @scheme[big-bang] function installs @emph{World_0} as the initial + world; the callbacks @emph{tock}, @emph{react}, and @emph{click} transform + one world into another one; @emph{done} checks each time whether the world + is final; and @emph{draw} renders each world as a scene. @deftech{World} @scheme[any/c] @@ -191,10 +216,12 @@ Example: The following examples shows that @scheme[(run-simulation 100 100 Exercise: Add a condition for stopping the flight of the UFO when it reaches the bottom. +@; ----------------------------------------------------------------------------- @section{Scenes and Images} -For the creation of scenes from the world, use the functions from @secref["image"]. The following two -functions have turned out to be useful for the creation of scenes, too. +For the creation of scenes from the world, use the functions from +@secref["image"]. The following two functions have turned out to be useful +for the creation of scenes, too. @defproc[(nw:rectangle [width natural-number/c] [height natural-number/c] [solid-or-filled Mode] [c Color]) image?]{ @@ -209,3 +236,293 @@ functions have turned out to be useful for the creation of scenes, too. in contrast to the @scheme[add-line] function, this one cuts off those portions of the line that go beyond the boundaries of the given @scheme[s].} + +@; ----------------------------------------------------------------------------- + +@(define (table* . stuff) + ;; (list paragraph paragraph) *-> Table + (define (flow* x) (make-flow (list x))) + (make-blockquote 'blockquote + (list + (make-table (make-with-attributes 'boxed + '((cellspacing . "6"))) + ;list + (map (lambda (x) (map flow* x)) stuff) + #;(map flow* (map car stuff)) + #;(map flow* (map cadr stuff)))))) + +@; ----------------------------------------------------------------------------- +@section[#:tag "example"]{A First Example} + + +@subsection{Understanding a Door} + +Say we want to represent a door with an automatic door closer. If this kind + of door is locked, you can unlock it. While this doesn't open the door per + se, it is now possible to do so. That is, an unlocked door is closed and + pushing at the door opens it. Once you have passed through the door and + you let go, the automatic door closer takes over and closes the door + again. Of course, at this point you could lock it again. + +Here is a picture that translates our words into a graphical + representation: + +@image["door-real.png"] + +The picture displays a so-called "state machine". The three circled words + are the states that our informal description of the door identified: + locked, closed (and unlocked), and open. The arrows specify how the door + can go from one state into another. For example, when the door is open, + the automatic door closer shuts the door as time passes. This transition + is indicated by the arrow labeled "time passes." The other arrows + represent transitions in a similar manner: + +@itemize[ + +@item{"push" means a person pushes the door open (and let's go);} + +@item{"lock" refers to the act of inserting a key into the lock and turning +it to the locked position; and} + +@item{"unlock" is the opposite of "lock".} + +] + +@; ----------------------------------------------------------------------------- +@subsection{Simulations of the World} + +Simulating any dynamic behavior via a program demands two different + activities. First, we must tease out those portions of our "world" that + change over time or in reaction to actions, and we must develop a data + representation @deftech{D} for this information. Keep in mind that a good data + definition makes it easy for readers to map data to information in the + real world and vice versa. For all others aspects of the world, we use + global constants, including graphical or visual constants that are used in + conjunction with the rendering operations. + +Second, we must translate the "world" actions---the arrows in the above + diagram---into interactions with the computer that the world teachpack can + deal with. Once we have decided to use the passing of time for one aspect + and mouse movements for another, we must develop functions that map the + current state of the world---represented as data---into the next state of + the world. Since the data definition @tech{D} describes the class of data + that represents the world, these functions have the following general + contract and purpose statements: + +@(begin +#reader scribble/comment-reader +(schemeblock +;; tick : @tech{D} -> @tech{D} +;; deal with the passing of time +(define (tick w) ...) + +;; click : @tech{D} @scheme{Number} @scheme{Number} @tech{MouseEvent} -> @tech{D} +;; deal with a mouse click at (x,y) of kind @scheme{me} +;; in the current world @scheme{w} +(define (click w x y me) ...) + +;; control : @tech{D} @tech{KeyEvent} -> @tech{D} +;; deal with a key event (symbol, char) @scheme{ke} +;; in the current world @scheme{w} +(define (control w ke) ...) +)) + +That is, the contracts of the various hooks dictate what the contracts of +these functions are once we have defined how to represent the world in +data. + +A typical program does not use all three of these actions and functions but + often just one or two. Furthermore, the design of these functions provides + only the top-level, initial design goal. It often demands the design of + many auxiliary functions. + +@; ----------------------------------------------------------------------------- +@subsection{Simulating a Door: Data} + +Our first and immediate goal is to represent the world as data. In this + specific example, the world consists of our door and what changes about + the door is whether it is locked, unlocked but closed, or open. We use + three symbols to represent the three states: + +@deftech{SD} + +@(begin +#reader scribble/comment-reader +(schemeblock +;; DATA DEF. +;; The state of the door (SD) is one of: +;; -- @scheme['locked] +;; -- @scheme['closed] +;; -- @scheme['open] +)) + +Symbols are particularly well-suited here because they directly express + the state of the door. + +Now that we have a data definition, we must also decide which computer + actions and interactions should model the various actions on the door. + Our pictorial representation of the door's states and transitions, + specifically the arrow from "open" to "closed" suggests the use of a + function that simulates time. For the other three arrows, we could use + either keyboard events or mouse clicks or both. Our solution uses three + keystrokes: +@scheme{#\u} for unlocking the door, +@scheme{#\l} for locking it, and +@scheme{#\space} for pushing it open. + We can express these choices graphically by translating the above "state + machine" from the world of information into the world of data: + +@image["door-sim.png"] + +@; ----------------------------------------------------------------------------- +@subsection{Simulating a Door: Functions} + +Our analysis and data definition leaves us with three functions to design: + +@itemize[ + +@item{@scheme{automatic-closer}, which closes the time during one tick;} + +@item{@scheme{door-actions}, which manipulates the time in response to +pressing a key; and} + +@item{@scheme{render}, which translates the current state of the door into +a visible scene.} + +] + +Let's start with @scheme{automatic-closer}. We know its contract and it is +easy to refine the purpose statement, too: + +@(begin +#reader scribble/comment-reader +(schemeblock +;; automatic-closer : SD -> SD +;; closes an open door over the period of one tick +(define (automatic-closer state-of-door) ...) +)) + + Making up examples is trivial when the world can only be in one of three + states: + +@table*[ + @list[@t{ given state } @t{ desired state }] + @list[@t{ 'locked } @t{ 'locked }] + @list[@t{ 'closed } @t{ 'closed }] + @list[@t{ 'open } @t{ 'closed }] +] + +@(begin +#reader scribble/comment-reader +(schemeblock +;; automatic-closer : SD -> SD +;; closes an open door over the period of one tick + +(check-expect (automatic-closer 'locked) 'locked) +(check-expect (automatic-closer 'closed) 'closed) +(check-expect (automatic-closer 'open) 'closed) + +(define (automatic-closer state-of-door) ...) +)) + + The template step demands a conditional with three clauses: + +@(begin +#reader scribble/comment-reader +(schemeblock +(define (automatic-closer state-of-door) + (cond + [(symbol=? 'locked state-of-door) ...] + [(symbol=? 'closed state-of-door) ...] + [(symbol=? 'open state-of-door) ...])) +)) + + The examples basically dictate what the outcomes of the three cases must + be: + +@(begin +#reader scribble/comment-reader +(schemeblock +(define (automatic-closer state-of-door) + (cond + [(symbol=? 'locked state-of-door) 'locked] + [(symbol=? 'closed state-of-door) 'closed] + [(symbol=? 'open state-of-door) 'closed])) +)) + + Don't forget to run the example-tests. + +For the remaining three arrows of the diagram, we design a function that + reacts to the three chosen keyboard events. As mentioned, functions that + deal with keyboard events consume both a world and a keyevent: + +@(begin +#reader scribble/comment-reader +(schemeblock +;; door-actions : SD Keyevent -> SD +;; key events simulate actions on the door +(define (door-actions s k) ...) +)) + +@table*[ + @list[@t{ given state } @t{ given keyevent } @t{ desired state }] + +@list[ @t{ 'locked } @t{ #\u } @t{ 'closed}] +@list[ @t{ 'closed } @t{ #\l } @t{ 'locked} ] +@list[ @t{ 'closed } @t{ #\space} @t{ 'open } ] +@list[ @t{ 'open } @t{ --- } @t{ 'open } ]] + + The examples combine what the above picture shows and the choices we made + about mapping actions to keyboard events. + +From here, it is straightforward to turn this into a complete design: + +@schemeblock[ +(define (door-actions s k) + (cond + [(and (symbol=? 'locked s) (key=? #\u k)) 'closed] + [(and (symbol=? 'closed s) (key=? #\l k)) 'locked] + [(and (symbol=? 'closed s) (key=? #\space k)) 'open] + [else s])) + +(check-expect (door-actions 'locked #\u) 'closed) +(check-expect (door-actions 'closed #\l) 'locked) +(check-expect (door-actions 'closed #\space) 'open) +(check-expect (door-actions 'open 'any) 'open) +(check-expect (door-actions 'closed 'any) 'closed) +] + +Last but not least we need a function that renders the current state of the +world as a scene. For simplicity, let's just use a large enough text for +this purpose: + +@(begin +#reader scribble/comment-reader +(schemeblock +;; render : @tech{SD} -> @scheme{Scene} +;; translate the current state of the door into a large text +(define (render s) + (text (symbol->string s) 40 'red)) + +(check-expecy (render 'closed) (text "closed" 40 'red)) +)) + The function @scheme{symbol->string} translates a symbol into a string, + which is needed because @scheme{text} can deal only with the latter, not + the former. A look into the language documentation revealed that this + conversion function exists, and so we use it. + +Once everything is properly designed, it is time to @emph{run} the +program. In the case of the world teachpack, this means we must specify +which function takes care of tick events, key events, and redraws: + +@(begin +#reader scribble/comment-reader +(schemeblock +(big-bang 100 100 1 'locked) +(on-tick-event automatic-closer) +(on-key-event door-actions) +(on-redraw render) +)) + +Now it's time for you to collect the pieces and run them in DrScheme to see +whether it all works. diff --git a/collects/teachpack/world.png b/collects/teachpack/world.png new file mode 100644 index 0000000000000000000000000000000000000000..82dd678265d584fc645a40f2b9201fab3e50adb5 GIT binary patch literal 19925 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 A1^@s6 literal 0 HcmV?d00001