;; The first three lines of this file were inserted by DrScheme. They record metadata
;; about the language level of this file in a form that our tools can easily process.
#reader(lib "htdp-advanced-reader.ss" "lang")((modname ppt-stage2) (read-case-sensitive #t) (teachpacks ()) (htdp-settings #(#t constructor repeating-decimal #t #t none #f ())))
;; Kathi Fisler
;; Powerpoint exercise
;; Stage 2 : Adding timecond
;; January 19, 2003

;;;;;;;;;;;;;;; THE INTERFACE LANGUAGE ;;;;;;;;;;;;;;;;;;;;;;;

;; print-string : string -> void
;; prints string and a newline to the screen
(define (print-string str)
  (printf "~a~n" str))

;; print-newline : -> void
;; prints a newline on the screen
(define (print-newline) (printf "~n"))

;; print-unnumbered-strings : list[string] -> void
;; prints a list of strings to the screen, each prefixed with a -
(define (print-unnumbered-strings strlist)
  (for-each (lambda (str) (printf "- ~a~n" str)) strlist))

;; print-numbered-strings : list[string] -> void
;; prints a list of strings to the screen, each prefixed with
;;   a number (in consecutive increasing order)
(define (print-numbered-strings strlist label)
  (cond [(empty? strlist) void]
        [(cons? strlist) 
         (begin
           (printf "~a. ~a~n" label (first strlist))
           (print-numbered-strings (rest strlist) (+ 1 label)))]))

;; await-click : -> void
;; mimics a mouse click by waiting for the user to type a character
(define (await-click) (read))

;;;;;;;;;; INTERFACE HELPERS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; print-slide-title : string -> void
;; displays title of slide on screen
(define (print-slide-title title-str)
  (begin
    (print-string (string-append "Title: " title-str))
    (print-newline)))
  
;; print-slide-body : slide-body -> void
;; displays contents of body on screen
(define (print-slide-body body)
  (cond [(string? body) (print-string body)]
        [(pointlist? body) 
         (cond [(pointlist-numbered? body) 
                (print-numbered-strings (pointlist-points body) 1)]
               [else (print-unnumbered-strings (pointlist-points body))])]))

;; print-slide : slide -> void
;; displays contents of slide on screen
(define (print-slide aslide)
  (begin
    (print-string "------------------------------")    
    (print-slide-title (slide-title aslide))
    (print-slide-body (slide-body aslide))
    (print-string "------------------------------")))

;; end-show : -> void
;; displays end of show message on screen
(define (end-show) (print-string "End of show"))

;;;;;;;;;;;; THE DATA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; a slide is a (make-slide string slide-body)
(define-struct slide (title body))

;; a slide-body is either
;;  - a string (paragraph), or
;;  - a (make-pointlist list[string] boolean)
(define-struct pointlist (points numbered?))

;; A cmd is 
;; - (make-displaycmd slide)
;; - (make-timecond (time->boolean) list[cmd] list[cmd])

(define-struct displaycmd (slide))
(define-struct timecond (time-limit within-time over-time))

;; A talk is a list of commands
(define-struct talk (cmds))

;;;;;;;;;;;;;;; PROGRAMS ;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define talk1
  (let ([intro-slide
         (make-slide 
          "Hand Evals in DrScheme"
          "Hand evaluation helps you learn how Scheme reduces programs to values")]
        [arith-eg-slide
         (make-slide 
          "Example 1"
          (make-pointlist (list "(+ (* 2 3) 6)" "(+ 6 6)" "12") false))]
        [func-eg-slide
         (make-slide 
          "Example 2"
          (make-pointlist (list "(define (foo x) (+ x 3))" "(* (foo 5) 4)" "(* (+ 5 3) 4)" "(* 8 4)"
                                "32") false))]
        [summary-slide
         (make-slide
          "Summary: How to Hand Eval"
          (make-pointlist (list "Find the innermost expression"
                                "Evaluate one step"
                                "Repeat until have a value")
                          true))])
    (make-talk
     (list (make-displaycmd intro-slide) 
           (make-timecond (lambda (time-in-talk) (> 5 time-in-talk))
                          (list (make-displaycmd arith-eg-slide))
                          empty)
           (make-displaycmd func-eg-slide) 
           (make-displaycmd summary-slide)))))

;;;;;;;;;;;;;;;; INTERPRETER ;;;;;;;;;;;;;;;;;;;;;;;;;;
                                  
(define (elapsed-time) 
  (- (current-seconds) start-time))

;; run-cmd : cmd -> void
;; executes the given command
(define (run-cmd cmd)
  (cond [(displaycmd? cmd) 
         (begin (print-slide (displaycmd-slide cmd))
                (await-click))]
        [(timecond? cmd) 
         (cond [((timecond-time-limit cmd) (elapsed-time))
                (run-cmdlist (timecond-within-time cmd))]
               [else (run-cmdlist (timecond-over-time cmd))])]))

;; run-cmdlist : list[cmd] -> void
;; executes every command in a list
(define (run-cmdlist cmd-lst)
  (cond [(empty? cmd-lst) void]
        [(cons? cmd-lst)
         (begin 
           (run-cmd (first cmd-lst))
           (run-cmdlist (rest cmd-lst)))]))

(define start-time 0)

;; run-talk : talk -> void
;; executes the commands in a talk then displays end-of-show message
(define (run-talk a-talk)
  (begin
    (set! start-time (current-seconds))
    (run-cmdlist (talk-cmds a-talk))
    (end-show)))