examples/model-1.rkt
#lang racket
;;; Model 1 - Discrete Event Model

(require (planet williams/simulation/simulation-with-graphics))

;;; Simulation Parameters

;;; end-time : (>/c 0.0)
;;; n-pits : exact-nonnegative-integer?
(define end-time 720.0)
(define n-pits 7)

;;; Data Collection

;;; total-ingots : exact-nonnegative-integer?
;;; wait-time : (or/c variable? false/c)
(define total-ingots 0)
(define wait-time #f)

;;; Model Definition

;;; random-sources : (vectorof random-source?)
(define random-sources (make-random-source-vector 2))

;;; furnace : (or/c set? false/c)
;;; pit : (or/c resource? false/c)
(define furnace #f)
(define pit #f)

;;; (scheduler) -> void?
(define (scheduler)
  (for ((i (in-naturals)))
    (schedule #:now (ingot))
    (wait (random-exponential (vector-ref random-sources 0) 1.5))))

;;; process (ingot)
(define-process (ingot)
  (let ((arrive-time (current-simulation-time)))
    (with-resource (pit)
      (set-variable-value! wait-time (- (current-simulation-time) arrive-time))
      (queue-insert! furnace self)
      (work (random-flat (vector-ref random-sources 1) 4.0 8.0))
      (queue-remove! furnace self))
    (set! total-ingots (+ total-ingots 1))))

;;; (stop-sim) -> void?
(define (stop-sim)
  (printf "Report after ~a Simulated Hours - ~a Ingots Processed~n"
          (current-simulation-time) total-ingots)
  (printf "~n-- Ingot Waiting Time Statistics --~n")
  (printf "Mean Wait Time        = ~a~n" (variable-mean wait-time))
  (printf "Variance              = ~a~n" (variable-variance wait-time))
  (printf "Maximum Wait Time     = ~a~n" (variable-maximum wait-time))
  (printf "~n-- Furnace Utilization Statistics --~n")
  (printf "Mean No. of Ingots    = ~a~n"
          (variable-mean (queue-variable-n furnace)))
  (printf "Variance              = ~a~n"
          (variable-variance (queue-variable-n furnace)))
  (printf "Maximum No. of Ingots = ~a~n"
          (variable-maximum (queue-variable-n furnace)))
  (printf "Minimum No. of Ingots = ~a~n"
          (variable-minimum (queue-variable-n furnace)))
  (write-special
   (history-plot (variable-history (queue-variable-n furnace))
                 "Furnace Utilization History"))
  (newline)
  (stop-simulation))

;;; (initialize) -> void?
(define (initialize)
  (set! total-ingots 0)
  (set! wait-time (make-variable))
  (set! pit (make-resource n-pits))
  (set! furnace (make-queue))
  (accumulate (variable-history (queue-variable-n furnace)))
  (tally (variable-statistics wait-time))
  (schedule #:at 0.0 (scheduler))
  (schedule #:at end-time (stop-sim)))

;;; (run-simulation) -> void?
(define (run-simulation)
  (with-new-simulation-environment
    (initialize)
    (start-simulation)))

;;; Run the simulation.
(run-simulation)