;=====
; examples for Week 3 Lecture 2 - 2025-09-11
;     Cleaned up after class!
; last modified: 2025-09-11

(require 2htdp/image)

;=====
; another testing function: check-within
;=====
; *   when testing functions involving fractional numbers,
;     if a check-expect fails, you can see if check-within
;     helps;
;     *   (to pass, check-expect expects its first two arguments
;         to have EXACTLY the same value; but fractional numbers
;         are sometimes hard to match EXACTLY when they have many 
;         less-significant digits, especially when they are not
;         all displayed...)
;
; *   check-within still expects the expression to test
;     and the expected value,
;     BUT it also expects a 3rd argument, the margin of error

;-----
; UNCOMMENT this check-expect to see that it fails --
;    (/ 1 3) and .333333333 are not EXACTLY the same value
;
;(check-expect (/ 1 3)
;              .333333333
;              )

;-----
; this check-within passes, however,
;     because the values of (/ 1 3) and .33333333 are,
;     while not exact, still within .001 from each other

(check-within (/ 1 3)
      	      .33333333
              .001)
;=====
; reminder: scene type
;===== 
; from: 2htdp/image !!!!! (corrected after class)
;
; a specialized subtype of the image type

;-----
; 2htdp/universe provides these two very-basic
;     scene operations:
;-----
; signature: empty-scene: number number -> scene
; purpose: expects the desired width and height of a scene
;     in pixels, and returns a scene of that width and height

(empty-scene 200 100)

;-----
; signature: place-image: image number number scene -> scene
; purpose: expects an image, the desired x and y coordinates,
;     and a scene, and returns a new scene with the image
;     centered at that (x, y) coordinate (and trimmed to fit
;     the scene if necessary)
;     (but (0, 0) is the top-left...!)
;         larger x values are further RIGHT,
;         larger y values are further DOWN...!!!!!)

;-----
; that is, here is a scene's coordinate system:
;
; (0,0)    1    2    3  x
;     -----|----|----|-->
;     |
;     |
;   1 -
;     |
;     |
;   2 -
;     |
;     |
;   3 -
;     |
;   y v

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

(place-image (circle 30 "solid" "purple")
             50
             100
             (empty-scene 200 200))

;----
; and, this results in a scene with a 35-pixels-between-its-points
;     pink star centered at 100 pixels from the left,
;     150 pixels down, and a 30-pixel-radius purple circle
;     centered at 50 pixels from the left, 100 pixels down,
;     in a scene that's 200 pixels wide, 200 pixels high

(place-image (star 35 "solid" "pink")
             100
             150
             (place-image (circle 30 "solid" "purple")
                          50
                          100
                          (empty-scene 200 200)))

;=====
; For some animations I would like to make,
;    I am going to have a number of scene instances of the
;    the same size and width
; SO: I am making some named constants to make this
;    more readable (and more maintainable)

(define WIDTH 400)
(define HEIGHT 200)

WIDTH
HEIGHT

(define BACKDROP (empty-scene WIDTH HEIGHT))

BACKDROP

;=====
; I would like a function that expects a star size
;    and returns a scene of a cyan star of that size
;    in its center

;-----
; I want to reuse cyan-star from Week 2 Lecture 2:
;     (NEED to copy its function header and body to do so --
;     and any other named constants or functions IT uses --
;     and CLASS STYLE is also to copy over its signature
;     and purpose comments, and its tests/check- expressions

;=====
; slightly-edited FROM WEEK 2 LECTURE 2
;=====
;-----
; signature: cyan-star: number -> image
; purpose: expects the distance between a 5-pointed
;    star's points, and returns a solid cyan star image
;    of that size

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

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

(define (cyan-star star-size)  
   (star star-size "solid" "cyan")
)
;===== (END of part copied over from Week 2 Lecture 2)

;-----
; continuing, now, with the design recipe steps for
;     this scene function:

;=====
; signature: cyan-star-scene: number -> scene
; purpose: expects a desired star size (distance in pixels
;    between its points) and returns a scene of size
;    WIDTH by HEIGHT with a cyan star of that size centered
;    within it

(check-expect (cyan-star-scene 50)
              (place-image (cyan-star 50)
                           (/ WIDTH 2)
                           (/ HEIGHT 2)
                           BACKDROP))

(check-expect (cyan-star-scene 150)
              (place-image (cyan-star 150)
                           (/ WIDTH 2)
                           (/ HEIGHT 2)
                           BACKDROP))


(define (cyan-star-scene star-size)
    (place-image (cyan-star star-size)
                 (/ WIDTH 2)
                 (/ HEIGHT 2)
                 BACKDROP)
)

(cyan-star-scene 50)
(cyan-star-scene 150)

;=====
; 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)

;-----
; 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 you can add to specify when it
;     should stop (see below)
;
; *   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 its 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 15
          (to-draw cyan-star-scene))

;-----
; 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 have an on-tick clause --
;    at the event of each ticker tick,
;    big-bang calls the 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 function add1, that does what you
;    would probably guess it does: adds 1 to something!

;-----
; signature: add1: number -> number
; purpose: expects any number, and returns the result
;    of adding 1 to it

(add1 56)

;=====
; 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 30
          (to-draw cyan-star-scene)
          (on-tick add1))

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

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

(sub1 56)

;----
; 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))

;-----
; BUT another optional event-handler clause big-bang has
;    is stop-when;
; stop-when expects a function that expects the current world
;    value type and returns a boolean,
;
;    and each time big-bang's ticker ticks, big-bang calls
;    stop-when's function with the current world,
;    and if that function returns #true, big-bang ENDS
;
;    (get it? "stop when this function is true"...)
;
; (but it does leave the World window open, oddly enough!)

"should see a pop-up window with a SHRINKING teal star in"
"    the center;"
" it will gracefully END when big-bang's world value reaches 0,"
"    BUT you will need to close the world pop-up"
"    window or it just sticks around...)"

(big-bang 150
          (to-draw cyan-star-scene)
          (on-tick sub1)
          (stop-when zero?))

;-----
; playing around:
;
; Racket has a random function that expects a
;    desired limit (max) and returns an integer
;    >= 0 and < than that maximum

(random 300)

; UNCOMMENT the following to see how our experiment trying
;     random as on-tick's event handler function is less than
;     successful...!
;
;"this attempt to use random as the on-tick event handler"
;"    function ends quickly with an error"
;"    because the world's value will quickly approach and reach 0"
;" "
;"(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 random))