[racket] use plot as render in universe

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Sun Aug 11 19:56:27 EDT 2013

Here is a more Rackety version of the program, including some graphical (failing) tests. 

world->list should have a test. 

purpose statements are missing. 




#lang racket

(require (prefix-in p: plot) 2htdp/image 2htdp/universe)

(module+ test (require rackunit))

;; ---------------------------------------------------------------------------------------------------
;; constants 
(define DAMPING 1/100)
(define UP 1.25) 
(define DOWN 0.75)

;; graphical constants 
(define BACKGROUND (square 600 'solid 'black)) 

;; ---------------------------------------------------------------------------------------------------
;; World = [List Price [List-of Price]]
;; World is a list of current price and a list of all past prices in chronological order

(define world0 (list 1 (list 1))) 
;; imagine adding a price pf 2 to world0
(define world1 (list 2 (list 1 2)))

;; ---------------------------------------------------------------------------------------------------
;; main function 

;; World -> World 
;; ???? what is the purpose of this main function ??? 
(define (sim init)
  (big-bang init
            (on-tick random-walk 1/2)
            (on-key shock)
            (to-draw plot-render)))

;; ---------------------------------------------------------------------------------------------------
;; World -> World
;; advances world by one more trading session

;; world = [list _ history0]
;; [list current history] = (random-walk world) 
;; => history = (append history0 (list current))
;; 

;; (Number n) => '(1 (1)) -> (n (1 n))

(module+ test (check-equal? (length (world-prices (random-walk world0))) 2))

(define (random-walk world)
  (match-define (list current historical) world)
  (define new-price (+ current (step)))
  (list new-price (append historical (list new-price))))

;; -> [-0.5/100, 0.5/100) 
(define (step)
  (* (damper) (random-btw-neg-half-and-pos-half)))

;; ---------------------------------------------------------------------------------------------------
;; World KeyEvent -> World

(module+ test (check-equal? (world-price (market-shock world0 1.5)) 1.5))

(define (shock world a-key)
  (cond
    [(key=? a-key "up")   (market-shock world UP)] 
    [(key=? a-key "down") (market-shock world DOWN)] 
    [else world]))

;; World Number -> World
;; ??? 
(define (market-shock world shock)
  (match-define (list current historical) world)
  (define new-price (* current shock))
  (list new-price (append historical (list new-price))))

;; -> [-0.5, 0.5) 
(define (random-btw-neg-half-and-pos-half)
  (- (random) 1/2))

;; -> Number
(define (damper) ;; why is this not a constant? 
  DAMPING)

;; ---------------------------------------------------------------------------------------------------
;; need to have at least 2 data points otherwise you are greeted by
;; plot: could not determine sensible plot bounds; got x ∈ [0,0], y ∈ [1,1]

(module+ test 
  (check-equal? (plot-render world0) BACKGROUND)
  
  (define history1 (world-prices world1))
  (check-equal? (plot-render world1) 
                (overlay (p:plot (p:lines (world->list-of-vectors history1))) BACKGROUND)))
  

(define (plot-render world)
  (if (< (length (world-prices world)) 2) ;; express this with rest/rest; this is slow! 
      BACKGROUND 
      (overlay (p:plot (p:lines (world->list-of-vectors world))) BACKGROUND)))

;; World -> [#(Int Number)]
(define (world->list-of-vectors world)
  (for/list ((price (world-prices world)) (i (in-naturals)))
    (vector i price)))

;; ---------------------------------------------------------------------------------------------------
;; general auxiliaries 

;; World -> Number
(module+ test (check-equal? (world-price world0) 1))
(define (world-price world)
  (first world))

;; World -> [List-of Number]
(module+ test (check-equal? (world-prices world0) (list 1)))
(define (world-prices world)
  (second world))

;; ---------------------------------------------------------------------------------------------------
;; run program run %% I recommend against running the main program from the definitions area 
; (define final-world (sim world0))



Posted on the users mailing list.