;=====
; CS 111 - Week 4 Lecture 1 - 2024-09-17
;=====

(require 2htdp/image)
(require 2htdp/universe)

;=====
;FROM WEEK 2 LECTURE 2
;=====
;=====
; signature: teal-star: number -> image
; purpose: expects the desired distance between
;   a star's points in pixels, and returns a solid
;   teal star of that size

(check-expect (teal-star 10)
              (star 10 "solid" "teal"))
(check-expect (teal-star 50)
              (star 50 "solid" "teal"))

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

;=====
;*** refactored**** starting from WEEK 3 LECTURE 2 version
;=====

(define WIDTH 400)
(define HEIGHT 200)
(define CENTER-X (/ WIDTH 2))
(define CENTER-Y (/ HEIGHT 2))

;=====
; signature: teal-star-scene: number -> scene
; purpose: expects a star size, and returns a scene
;    of a centered teal star of that size

(check-expect (teal-star-scene 50)
              (place-image
                  (teal-star 50)
                  CENTER-X
                  CENTER-Y
                  (empty-scene WIDTH HEIGHT)))

(check-expect (teal-star-scene 8)
              (place-image
                   (teal-star 8)
                   CENTER-X
                   CENTER-Y
                   (empty-scene WIDTH HEIGHT)))

(define (teal-star-scene star-size)
   (place-image (teal-star star-size)
                CENTER-X
                CENTER-Y
                (empty-scene WIDTH HEIGHT))
)

(teal-star-scene 50)
(teal-star-scene 8)

;===== (END of part copied over from Week 3 Lecture 2 and then refactored)

;=====
; cond expression
;
; syntax:
;    (cond
;        [boolean-expr1 expr1]
;        [boolean-expr2 expr2]
;        [boolean-expr3 expr3]
;        ...
;        [else expr-else]
;    )
;
;    *   the [bool-expr expr] parts can be called clauses or branches
;    *   the second expr in each clause can be of any type (but it must have
;        a value)
;
; semantics (meaning):
; *   evaluate each clause's boolean expression in order
;     until it finds one with the value #true --
;     that clause's 2nd expression becomes the value of the cond
;     expression
;
;     *   once a clause starting with a #true boolean expression
;         is found, the rest of the clauses are IGNORED, skipped!
;         *   at most one branch will be "taken", at most one
;             clause will have its 2nd expression evaluated
;
;     *   so the ORDER of the clauses matters!
;
;     *   if you include an [else ...] clause and it is reached,
;         else is always considered #true and the else clause's
;         2nd expression will be the value of the cond expression


;=====
; kind of inspired by the song "Yes, We Have No Bananas",
;   I decide I want a function that expects a quantity
;   of bananas, and produes a slightly-grammatical
;   report of that quantity

;=====
; signature: banana-report: number -> string
; purpose: expects a quantity of bananas
;    (assuming NO fractional bananas), and
;    returns a string reporting that quantity of
;    bananas (saying no bananas if quantity is 0 or fewer,
;    one banana if quantity is 1, and the given quantity
;    if quantity is more than 1)

;-----
; when your data involves INTERVALS of numbers,
;     need a test for EACH interval, PLUS a test for
;     each "boundary" BETWEEN intervals
;     (because boundaries are a common place for errors
;     in programs!)

(check-expect (banana-report -12)
              "Yes, we have no bananas!")

(check-expect (banana-report 0)
              "Yes, we have no bananas!")

(check-expect (banana-report 1)
             "Yes, we have one banana!")

(check-expect (banana-report 2)
              "Yes, we have 2 bananas!")

(check-expect (banana-report 8745)
              "Yes, we have 8745 bananas!")

(define (banana-report banana-num)
    (cond
        [(<= banana-num 0) "Yes, we have no bananas!"]
        [(= banana-num 1) "Yes, we have one banana!"]
        [else (string-append "Yes, we have "
                             (number->string banana-num)
                             " bananas!")]
    )
)

(banana-report 1)
(banana-report 8745)
(banana-report 0)

;=====
; another big-bang clause:
; stop-when
;
; *   expects the name of a function
;     that expects the current world type
;     and returns a boolean
;
; *   each time big-bang's ticker ticks,
;     it calls stop-when's function with the
;     current world value, and if that function returns
;     #true, big-bang ends (and returns its final world
;     value)
;     *   get it? you are asking big-bang to stop-when its
;         function is #true for the current world value
;
; ...but you still need to CLOSE the world window...sigh!

;=====
; fun fact!
; BSL Racket has a function zero? that expects
;    a number and returns #true if that number is 0
;    and returns #false otherwise
; so: zero? CAN be used as the argument for a stop-when clause
;    when big-bang's world type is number

"thanks to stop-when clause, this big-bang call ends"
"    gracefully! (but you should close the World window...)"

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