;=====
; CS 111 - Week 4 Lecture 2 - 2025-09-18
;=====

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

;=====
; REMINDER
;=====
; cond expression
;
; syntax:
;    (cond
;        [boolean-expr1 result-expr1]
;        [boolean-expr2 result-expr2]
;        [boolean-expr3 result-expr3]
;        ...
;        [else result-expr-else]
;    )
;
; semantics:
; *   evaluate each clause's boolean expression in order
;     until it finds one with the value #true --
;     that clause's 2nd/result expression becomes the value
;     of the cond expression

;=====
; let's drop some penguins!

;=====
; some useful named constants

(define PENG-SC-WIDTH 300)
(define PENG-SC-HEIGHT 450)

(define PENG-SC-BACKGRD
        (empty-scene PENG-SC-WIDTH PENG-SC-HEIGHT))

(define PENG-CTR-X (/ PENG-SC-WIDTH 2))

(define FLOATING-PENGUIN
    (bitmap/url
       "https://nrs-projects.humboldt.edu/~st10/f25cs111/floating-penguin.png")
)

(define LANDED-PENGUIN
    (bitmap/url
       "https://nrs-projects.humboldt.edu/~st10/f25cs111/landed-penguin.png")
)

FLOATING-PENGUIN
LANDED-PENGUIN

;=====
; oh -- want the penguin to "land" when its feet roughly
;    reach the "ground" --
; BUT place-image tends to center the image at the (x, y) coordinates
;     specified (although there are also ways to change
;     what is considered its "center" -- see put-pinhole
;     in the 2htdp/image documentation)

; so -- a bigger y is further down in a scene coordinate system;
;    I want to switch to a landed penguin before PENG-SC-HEIGHT;
;    ...so, for a y value smaller than PEMG-SC-HEIGHT --
;    ...how much smaller? Half of the landed penguin's height smaller;
;
;    SO could subtract half the landed penguin's height
;         from PENG-SC-HEIGHT to get a better landing height;

(define LANDING-HEIGHT
        (- PENG-SC-HEIGHT
           (/ (image-height LANDED-PENGUIN)
              2)))

;=====
; signature: draw-penguin-scene: number -> scene
; purpose: expects a world-number, and if it is less than
;   LANDING-HEIGHT, it returns a scene with a floating penguin
;   with the world-number as its y coordinate;
;   otherwise, it returns a scene with the now-landed penguin
;   on the "ground"

; for this function, I want at least 3 tests:
;    one that results in a floating penguin scene,
;    one that results in a landed penguin scene,
;    and one for the boundary between these two world-num ranges
; (more tests are fine!)

(check-expect (draw-penguin-scene 10)
              (place-image FLOATING-PENGUIN
                           PENG-CTR-X
                           10
                           PENG-SC-BACKGRD))

(check-expect (draw-penguin-scene -70)
              (place-image FLOATING-PENGUIN
                           PENG-CTR-X
                           -70
                           PENG-SC-BACKGRD))

(check-expect (draw-penguin-scene (+ 10 PENG-SC-HEIGHT))
              (place-image LANDED-PENGUIN
                           PENG-CTR-X
                           LANDING-HEIGHT
                           PENG-SC-BACKGRD))

(check-expect (draw-penguin-scene LANDING-HEIGHT)
              (place-image LANDED-PENGUIN
                           PENG-CTR-X
                           LANDING-HEIGHT
                           PENG-SC-BACKGRD))

(define (draw-penguin-scene world-num)
    (cond
       [(< world-num LANDING-HEIGHT)
            (place-image FLOATING-PENGUIN
                         PENG-CTR-X
                         world-num
                         PENG-SC-BACKGRD)]
       [else (place-image LANDED-PENGUIN
                          PENG-CTR-X
                          LANDING-HEIGHT
                          PENG-SC-BACKGRD)]
    )
)

(big-bang 0
    (on-tick add1)
    (to-draw draw-penguin-scene))

;=====
; draw-penguin-scene involved interval-style data;
; here's an example involving enumeration-style data:

;=====
; signature: next-sound: string -> string
; purpose: expects an animal sound, and returns
;    the "next" animal sound based on the beginning
;    of Sandra Boynton's "Moo, Baa, La La La":
;    *   for moo, return baa
;    *   for baa, return la la la
;    *   for la la la, return oink
;    *   for oink, return moo
;    *   for anything else, return "???"

;-----
; I need at least 5 tests here --
;    one for each of the 4 possible sounds,
;    and because I specified what to do for a "bad" sound,
;        I also need to test for that

(check-expect (next-sound "moo") "baa")
(check-expect (next-sound "baa") "la la la")
(check-expect (next-sound "la la la") "oink")
(check-expect (next-sound "oink") "moo")
(check-expect (next-sound "fred") "???")

(define (next-sound animal-sound)
    (cond
        [(string=? animal-sound "moo") "baa"]
        [(string=? animal-sound "baa") "la la la"]
        [(string=? animal-sound "la la la") "oink"]
        [(string=? animal-sound "oink") "moo"]
        [else  "???"]        
    )
)

(next-sound "moo")
(next-sound "fred")