;=====
; CS 111 - Week 3 Lecture 2 - 2026-09-10
;
; In-class examples, cleaned up after class!
;
; last modified: 2026-09-10

;-----
; will be using some functions from the 2htdp/image module:

(require 2htdp/image)

;-----
; AND will now ALSO be using a function, big-bang,
;     from the 2htdp/universe module!

(require 2htdp/universe)

;=====
; a new type: the scene type
; *   provided by 2htdp/image
; *   the scene data type is an interesting type in that
;     it is a SUBTYPE of the image data type
;
;     like a background! but you can put things in it!
;     transparent, and it won't let contents overlap its edges;

;=====
; when you learn of a data type,
; you need to know WHAT you can do with it
;
; for scene, 2htdp/image provides TWO starter functions:
; *   empty-scene
; *   place-image

;=====
; when you have a new data type, you need a way to
;     create INSTANCES of that data type;
; 2htdp/image provides the function empty-scene for
;     creating a new empty scene instance

;=====
; signature: empty-scene: number number -> scene
; purpose: expects a desired width and height of a
;    scene in pixels, and returns an empty scene of that
;    width and height

(empty-scene 400 200)

;=====
; if, within a .rkt file, I want a standard width and height
;    for a bunch of scenes,
;    named constants for the width and height would be nice!

(define WIDTH 400)
(define HEIGHT 200)

(empty-scene WIDTH HEIGHT)

;=====
; how can I have a scene with something in it?
; *   2htdp/image provides a function place-image to
;     add an image to a scene and result in a new scene

;=====
; signature: place-image: image number number scene -> scene
; purpose: expects an image to add to a scene, the desired
;     x and y coordinates where you'd like to place that image,
;     and the scene to add the image to, and returns a new scene
;     with that given image centered at those coordinates in the
;     given scene (and trimmed if needed to the scene's size
;     if needed)

;=====
; BUT: IMPORTANT ASIDE: what is the scene data type's
;     COORDINATE system? Where is x=0, y=0 in a scene?
;
; it is based on old computer monitors, where the image
;     on a screen is drawn from top-to-bottom, left-to-right;

;-----
; that is, here is a scene's coordinate system:
;
; (0,0)    1    2    3  x
;     -----|----|----|-->
;     |
;     |
;   1 -
;     |
;     |
;   2 -
;     |
;     |
;   3 -
;     |
;   y v
;
;     SO (0, 0) is the top-left...!
;         larger x values are further RIGHT,
;         larger y values are further DOWN...!!!!!)

;-----
; and if I might want a scene to serve as a default backdrop
;     scene for placing an image into for several or more
;     place-image expressions, a named constant for THAT could
;     be useful, also!
; (note: it is perfectly fine to use previously-defined named
;     constants in defining other named constants)

(define BACKDROP (empty-scene WIDTH HEIGHT))

;-----
; so, this expression results in a scene of a 30-pixel-radius
;     purple circle centered at
;     50 pixels from the left,
;     50 pixels down,
;     in a scene that's WEIGHT pixels wide, HEIGHT pixels high

(place-image (circle 30 "solid" "purple")
             50  50
             BACKDROP)

;-----
; so, this expression results in a scene of a 45x45 pixel
;     green square centered at
;     300 pixels from the left,
;     25 pixels down,
;     in a scene that's WEIGHT pixels wide, HEIGHT pixels high

(place-image (square 45 "solid" "green")
             300  25
             BACKDROP)

;-----
; so, this expression results in a scene of a 40-pixel-radius
;     pink circle centered at
;     WIDTH pixels from the left,
;     HEIGHT pixels down,
;     in a scene that's WEIGHT pixels wide, HEIGHT pixels high
;
; (when you run this, note how the part of the circle "outside"
;     the scene is cut off)

(place-image (circle 40 "solid" "pink")
             WIDTH
             HEIGHT
             BACKDROP)

(place-image (circle 30 "solid" "red")
             0 HEIGHT
             (empty-scene WIDTH HEIGHT))

;=====
; remember that place-image returns a scene!
;
; so, it is fine to use a place-image compound expression
;     as the 4th argument to a place-image compound
;     expression!

(place-image (circle 15 "outline" "brown")
             50 50
             (place-image (triangle 20 "solid" "orange")
                          325 175
                          (place-image
                              (star 20 "solid" "teal")
                              225 125
                              (empty-scene WIDTH HEIGHT))))

;=====
; I decide I want to be able to create a scene of a
;     centered cyan star of a specified size;
;     a function could be useful for that!
;
; hey, last week's function cyan-star might be useful in
;     creating this new function!
; I am COPYING its signature, purpose, tests, and
;     definition from last week's examples into THIS file,
;     so I can use it here

;-----
; PASTED this in from Week 2 Lecture 2 posted examples
; (INCLUDING the signature, purpose, and tests!

;-----
; signature: cyan-star: number -> image
; purpose: expects the desired distance between
;    the points of a star and returns an image
;    of a cyan star of that size

(check-expect (cyan-star 10)
              (star 10 "solid" "cyan"))

(check-expect (cyan-star 4)
              (star 4 "solid" "cyan"))

(define (cyan-star star-size)  
   (star star-size "solid" "cyan")
)

;=====
; now, going on!
;
;----
; again, I want a function to create a scene
;     of a centered cyan star of a size I specify;
; I decide:
;     *   to name it cyan-star-scene
;     *   to only have the user specify the cyan star's
;         size
;     *   to have it always return a scene whose width is
;         WIDTH and whose height is HEIGHT

;=====
; signature: cyan-star-scene: number -> scene
; purpose: expects a cyan star size and returns a scene
;    of a cyan star of that size, centered. The scene will
;    always be WIDTH x HEIGHT pixels.

(check-expect (cyan-star-scene 20)
              (place-image (cyan-star 20)
                           (*  0.5 WIDTH)
                           (* 0.5 HEIGHT)
                           (empty-scene WIDTH HEIGHT)))

(check-expect (cyan-star-scene 50)
              (place-image (cyan-star 50)
                           (* 0.5 WIDTH)
                           (* 0.5 HEIGHT)
                           (empty-scene WIDTH HEIGHT)))

(define (cyan-star-scene star-size)
    (place-image (cyan-star star-size)
                 (* 0.5 WIDTH)
                 (* 0.5 HEIGHT)
                 (empty-scene WIDTH HEIGHT)))

(cyan-star-scene 20)
(cyan-star-scene 50)

;=====
; starting intro to function: big-bang
;=====

;=====
; function big-bang is defined in the module
;     2htdp/universe, so to use it, you need:
;
; (require 2htdp/universe)
;
; (I already put this at the begining of this file,
;     so I don't need to put it again)

;-----
; big-bang is a function with numerous side-effects!

;-----
; big-bang expects at least 2 arguments;
;    the first is the initial value of a new "world"
;        (and the type of that value becomes the type
;        of the new world)
;    the remainder are event-handler clauses,
;        special compound expressions
;        that start with the name of an event
;        and are followed with the NAME of a function
;        to be called when that event happens (an event-handler
;        function)
;        (and a few have additional optional arguments)
;
;    and, big-bang returns the value of its world when it is ended

;-----
; when you call big-bang, it starts a ticker ticking,
;     (about 28 times per second, although you can specify
;     a different speed)
;     *   and each time its ticker ticks, it wants to
;         create a scene and display it in a pop-up World
;         window

;-----
; when does a running big-bang expression end?
;
; *   when you CLOSE its World window (clicking on its
;     top-left corner)
;
; *   when you click DrRacket's Stop button in its
;     top-right corner (but this ends your current Racket
;     program, also)
;     *   (and the World window remains open until you close it,
;         even though big-bang is no longer running)
;
; *   there is also a clause, stop-when, you can add to
;     specify when it should stop (more on that later)
;
; *   and, a run-time error will kill it, too! (and the World window
;     remains open in this case, also...)

;-----
; GOING ON: the event you MUST handle is when big-bang wants to
;    depict its world, to draw a scene based on its current
;    world value;
;
;    to-draw
;
;    (big-bang initial-world-expr
;        (to-draw desired-funct)
;        ...)
;
; when the to-draw event occurs (for example, after each ticker tick),
;    big-bang calls the function YOU give to-draw as to-draw's argument
;    with the current world value as *its* argument,
;    and it displays the resulting scene in a pop-up window

"should see a pop-up window with an unchanging cyan star in"
"    the center;"
"CLOSE that window to continue!"

(big-bang 100
  (to-draw cyan-star-scene))

;=====
; but, um, that's not very dynamic!

;-----
; as mentioned, each time you call function big-bang,
;    big-bang starts up a ticker that ticks about
;    28 times per second;
; each time the ticker ticks, big-bang calls to-draw's function
;    to depict the current world value's scene;
; BUT -- IF you ALSO call big-bang with an on-tick clause --
;    then, at the event of each ticker tick,
;    big-bang calls its on-tick clause's function
;        with the current world value,
;    and what that function returns becomes the *new* world value!

;=====
; FUN FACT: Racket has a built-in function add1, that does what you
;    would probably guess it does: adds 1 to something!

;=====
; signature: add1: number -> number
; purpose: expects a number and returns 1 + that numbers

(add1 100)
(add1 13)

;=====
; SO, if big-bang's world type - the type of its first argument - is number,
;      I can use add1 as on-tick's argument,
;      and each time big-bang's ticker ticks,
;      big-bang will call add1 with the current world value
;      to result in a new world value:

"should see a pop-up window with a GROWING cyan star in"
"    the center;"
"CLOSE that window to continue!"

(big-bang 100
    (to-draw cyan-star-scene)
    (on-tick add1))

;=====
; FUN FACT: Racket also has a built-in function sub1, that
;     subtracts 1 from something!

;-----
; signature: sub1: number -> number
; purpose: expects any number, and returns the result
;    of subtracting 1 from it

(sub1 56)
(sub1 200)

;----
; SO -- see what happens when you use sub1 as the event-handler
;    function for the event on-tick:

"should see a pop-up window with a SHRINKING cyan star in"
"    the center;"
"CLOSE that window before world value gets to 0 to continue,"
"    otherwise big-bang will be stopped by the error that happens"
"    when cyan-star-scene calls cyan-star and cyan-star calls"
"    function star with a non-zero size!"
"    "
"    (if you try out the error, you'll need to close the world pop-up"
"    window or it just sticks around...)"

(big-bang 200
    (to-draw cyan-star-scene)
    (on-tick sub1))