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

; CS 111 - Week 6 Lecture 1 - 2016-09-27

;========
; let's say I'd like a big-bang world
;    that is a LIST of images

;========
; DATA DEFINITION
; an ImageList is one of:
;     - empty
;     - (cons image ImageList)

;========
; ImageList function template
; (template for a function that "walks through"
;    an ImageList
;==============================================
; (define (imglist-funct img-list ...)
;     (cond
;         [(empty? img-list) ...]
;         [else (... (first img-list) ...
;                    (imglist-funct (rest img-list) ...) ...)]
;     )
; )

;========
; BSL Racket provides a lovely pseudo-random
;    number function called random
;
; random expects a positive integer
;    and returns a pseudo-random integer
;    in the range [0, given-integer)

"should see a number in [0, 100)"
(random 100)

""
"should see a number in [100, 200)"

(+ 100 (random 100))

;========
; I decide to write a world where the world
;    is a list of images,
;    and at each ticker tick,
;    each image is depicted in a scene
;    at a random location

; these named constants will be useful:

(define WIDTH 300)
(define HEIGHT 200)
(define BACKDROP (empty-scene WIDTH HEIGHT))

;========
; on-tick NEEEEEDS a function that expects the
;    current world and returns the next world --

; return-current will just return its parameter.
;    since ticking the ticker DOESN'T change the
;    world here

;========
; signature: return-current: anything -> anything
; purpose: expects a value, and returns that value

;(define (return-current a-value)
;     ...
;)

(check-expect (return-current WIDTH)
              WIDTH)
(check-expect (return-current
                 (cons "george"
                     (cons "apple" (cons "milk" empty))))
              (cons "george"
                     (cons "apple" (cons "milk" empty))))
                                  
(define (return-current a-value)
     a-value
)

;========
; now: I need a function for to-draw!
; needs to expect a value of the world's type,
;    and return a scene depicting the current world value

; HERE, I want the images in the world-image-list
;    to be shown at random locations...

;========
; signature: draw-images-randomly: ImageList -> scene
; purpose: expects a list of images, and returns a
;    scene showing each image in a random location

;(define (draw-images-randomly list-o-imgs)
;    ...
;)

;========
; at LEAST 2 check-expects
; (because 2 items in the ImageList, and need to
;     test both! BUT additional non-empty image
;     lists would be lovely to test, also...)

(check-expect (draw-images-randomly empty)
              BACKDROP)

; gee, an example image list would be lovely about now

(define SHAPE-TRIO
    (cons (circle 50 "solid" "red")
          (cons (square 100 "outline" "purple")
                (cons (star 30 "solid" "maroon") empty))))

;========
; (writing the kluged-with-string-description-
;     of-what-I-should-see before finishing the
;     body, of course -- but have to PLACE it
;     after the function definition.
; for class purposes, I commented out the original
;     placement to stress that it was written
;     before finishing the function body...)

;"I should see a scene with a solid red circle,"
;"    a purple square outline,"
;"    and a solid maroon star at RANDOM locations"
;
;(draw-images-randomly SHAPE-TRIO)

;========
; I have a function that "walks through" an ImageList --
; PASTE IN the template I have for that!!

;(define (draw-images-randomly list-o-imgs)
;; (define (imglist-funct img-list ...)
;;     (cond
;;         [(empty? img-list) ...]
;;         [else (... (first img-list) ...
;;                    (imglist-funct (rest img-list) ...) ...)]
;;     )
;; )
;)

;========
; REPLACE/put in MY function's name and parameter(s)

;(define (draw-images-randomly list-o-imgs)
;     (cond
;         [(empty? list-o-imgs) ...]
;         [else (... (first list-o-imgs) ...
;                    (draw-images-randomly
;                         (rest list-o-imgs) ...) ...)]
;     )
;)

;========
; and complete function from there, using the
;    tests and the template for inspiration

(define (draw-images-randomly list-o-imgs)
     (cond
         [(empty? list-o-imgs) BACKDROP]
         [else (place-image (first list-o-imgs)
                            (random WIDTH)
                            (random HEIGHT)
                            (draw-images-randomly
                                (rest list-o-imgs)))]
     )
)

;========
; YES, a kluged-string-test MUST go after the
;   function definition

"I should see TWO scenes with a solid red circle,"
"    a purple square outline,"
"    and a solid maroon star at RANDOM locations"

(draw-images-randomly SHAPE-TRIO)
(draw-images-randomly SHAPE-TRIO)

;========
; hey, I have enough for big-bang!

(big-bang SHAPE-TRIO
          (on-tick return-current)
          (to-draw draw-images-randomly))

;========
; reminder: not ALL list functions end up
;   walking through the whole list...

;========
; SAY I want a keystroke handler that ADDS
;    an image to an image-list based on
;    the key typed

;========
; DATA DEFINITION:
; a ShapeKey is one of:
;    "c", "t", or "s"
;    ("c" is for circle,
;     "t" is for triangle,
;     "s" is star)

;========
; signature: add-shape: ImageList ShapeKey -> ImageList
; purpose: expects a list of images and a shape key,
;    and returns a new list of images with a new first
;    shape according to the shape key given:
;    *   for "c", adds a 20-pixel-radius solid black circle,
;    *   for "t", adds a 25-pixel-sided solid aqua triangle,
;    *   for "s", adds a 25-pixel-btwn-points solid orange star,
;    (added to the other images in the given image list),
;    BUT!!
;    *   (for any other string, it returns an EMPTY image list)
              
;(define (add-shape img-list a-shape-key)
;    ...
;)

;========
; dueling test guidelines!
;    function "driven" by the shape key,
;    need to test ALL 3 "legal" values,
;    and what-if-another, especially since
;    I specified that in my purpose ,
;    (and a user often types an errant key)

; BUT, ALSO make sure there's an empty list in
;    in ONE of those

(check-expect (add-shape empty "c")
              (cons (circle 20 "solid" "black") empty))

(check-expect (add-shape SHAPE-TRIO "t")
              (cons (triangle 25 "solid" "aqua")
                    SHAPE-TRIO))

(check-expect (add-shape (cons (text "moo" 20 "black") empty)
                         "s")
              (cons (star 25 "solid" "orange")
                    (cons (text "moo" 20 "black") empty)))

(check-expect (add-shape SHAPE-TRIO "f")
              empty)

;========
; dueling templates, too!
;    BUT the enumeration data "drives" this function,
;    so go with THAT template
;    3 elements in enumeration, plus test for "other"

;(define (add-shape img-list a-shape-key)
;    (cond
;        [... ...]
;        [... ...]
;        [... ...]
;        [else ...]
;    )
;)

(define (add-shape img-list a-shape-key)
    (cond
        [(string=? a-shape-key "c")
             (cons (circle 20 "solid" "black")
                   img-list)]
        [(string=? a-shape-key "t")
             (cons (triangle 25 "solid" "aqua")
                   img-list)]
        [(string=? a-shape-key "s")
             (cons (star 25 "solid" "orange")
                   img-list)]
        [else empty]
    )
)

;========
; now trying big-bang with add-shape in its
;    on-key clause

(big-bang SHAPE-TRIO
          (on-tick return-current 0.5)
          (on-draw draw-images-randomly)
          (on-key add-shape))