;;> ********************** 
;;> * CSU-211 Lab 9 Code * 
;;> ********************** 


;;> Given Defs 
;; A Pt is (make-pt Number Number)
(define-struct pt (x y))

;; Screen Width and Height
(define scr-size 400)
;; MAX is the maximum point to be generated/drawn
(define MAX 50)
;; pt-size is the size (radius) of each point
(define pt-size (/ scr-size MAX))

;; rand: Number -> Number
;; Ignore the argument, return a random number [0..99]
(define (rand dummy)
  (random MAX))


;; make-points: (Number -> Number) -> (listof Pt)
;; Create a List of Pts that contains points with Xs from 0..(- MAX 1)
;;   and Ys from (f x) for each x scaled by pt-size.  In other worlds:
;;       (list (make-pt 0 (* (f 0) pt-size) ...
;;             (make-pt (* (- MAX 1) pt-size) (* (f (- MAX 1)) pt-size)))
(define (make-points f)
  (local ((define (mkpnt n)
            (make-pt (* n pt-size) (* (f n) pt-size))))
  (build-list MAX mkpnt)))


;; draw-points: (listof Pt) Symbol -> Scene
;; Draw the list of points into an empty scene using
;;   scr-size for the scene dimensions
(define (draw-points lop color)
  (local ((define (one p scn)
            (place-image (circle pt-size 'solid 'red)
                         (pt-x p) (pt-y p)
                         scn)))
    (foldl one (empty-scene scr-size scr-size) lop)))


;; center-points: (listof Pt) -> (listof Pt)
;; Move all points ys half-way toward the center
(define (center-points lop)
  (local ((define (one p)
            (make-pt (pt-x p) 
                     (/ (+ (pt-y p) (/ scr-size 2)) 2))))
    (map one lop)))


;; filter-points: (listof Pt) Number -> (listof Pt)
;; Remove the points that are not within (* n 20) of the center
;;   Y of the screen
(define (filter-points lop n)
  (local ((define (func p)
            (>= (* n 20) (abs (- (pt-y p) 
                                 (/ scr-size 2))))))
    (filter func lop)))

;;> Provided Code... 
;; Make changes/create a new List based on a key press
(define (do-char ch lop)
  (cond [(char=? ch #\r) (make-points rand)]
;;> Here's the modifications... 
        [(char=? ch #\c) (center-points lop)]
        [(char=? ch #\2) (filter-points lop 2)]
        [(char=? ch #\6) (filter-points lop 6)]
        [(char=? ch #\8) (filter-points lop 8)]
        [else lop]))

;;> Challenge Portion... Here: 
;; A World is (make-world Number (listof Pt))
(define-struct world (i lop))

(define (draw w) 
  (local ((define scn (draw-points (world-lop w) 'red)))
    (cond [(>= (world-i w) (length (world-lop w))) scn]
          [else (local ((define p (list-ref (world-lop w) (world-i w)))
                        (define txt (text (string-append "Pnt: (" 
                                                         (number->string (pt-x p)) ", "
                                                         (number->string (pt-y p)) ")")
                                          20 'black)))
                  (place-image txt 10 (- scr-size 40)
                               (place-image (circle 10 'solid 'blue)
                                            (pt-x p) (pt-y p) scn)))])))

(define (key w s/ch)
  (cond [(char? s/ch) (make-world (world-i w) (do-char s/ch (world-lop w)))]
        [(symbol=? s/ch 'right) (make-world (+ (world-i w) 1) (world-lop w))]
        [(= 0 (world-i w)) w]
        [(symbol=? s/ch 'left) (make-world (- (world-i w) 1) (world-lop w))]
        [else w]))
(big-bang scr-size scr-size 1 (make-world 0 '()))
(on-redraw draw)
(on-key-event key)