library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✔ ggplot2 3.3.6     ✔ purrr   0.3.4
## ✔ tibble  3.1.7     ✔ dplyr   1.0.9
## ✔ tidyr   1.2.0     ✔ stringr 1.4.0
## ✔ readr   2.1.2     ✔ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
library(scales)
## 
## Attaching package: 'scales'
## The following object is masked from 'package:purrr':
## 
##     discard
## The following object is masked from 'package:readr':
## 
##     col_factor
customer <- setRefClass(
  "customer",
  fields = list(
    arrival = "numeric",
    waiting = "numeric",
    serviceStart = "numeric",
    serviceDuration = "numeric",
    exitTime = "numeric"
  ),
  methods = list(
    initialize = function(arrival=0, waiting=0, serviceStart=0, serviceDuration=0, exitTime=0) {
      "This method is called when you create an instance of the class."
      arrival <<- arrival
      waiting <<- waiting
      serviceStart <<- serviceStart
      serviceDuration <<- serviceDuration
      exitTime <<- exitTime
    }
  )
)

setMethod("show",
          "customer",
          function(object){
            cat("Customer arrival time:", object$arrival, "\n")
            cat("Waiting Time:", object$waiting, "\n")
            cat("Start Time:", object$serviceStart, "\n")
            cat("Exit Time:", object$exitTime, "\n")
          })

# Erik <- new("customer", 1, 2)
# Erik
runSimulation <- function(timeH, serviceLow, serviceHi, arrivalRate){
  customers = list()
  serverAvailable = 0
  currentTime = 0
  while(currentTime < timeH){
    # Generate customer arrivals
    c = new("customer")
    c$arrival = round(currentTime + rexp(1, arrivalRate), digits = 2)
    currentTime = c$arrival
    if(c$arrival <= timeH){
      if(serverAvailable <= c$arrival){ # First case, server is idle ready to process the customer
        c$waiting = 0
        c$serviceStart = c$arrival
        c$serviceDuration = sample(serviceLow:serviceHi, 1)
        c$exitTime = round(c$arrival+c$serviceDuration, digits = 2)
        serverAvailable = c$exitTime
      } else { # Second case, server is busy so customer must wait
        c$serviceStart = serverAvailable
        c$waiting = round(c$serviceStart - c$arrival, digits = 2)
        c$serviceDuration = sample(serviceLow:serviceHi, 1)
        c$exitTime = round(c$serviceStart + c$serviceDuration, digits = 2)
        serverAvailable = c$exitTime
        print(c)
        writeLines(paste("[current system time:",currentTime,"Server Available",serverAvailable,"]"))
        customers <- append(customers, c)
      }
    }
  }
  return(customers)
}
timeH = 30
serviceLow = 5
serviceHi = 10
arrivalRate = .2

results <- runSimulation(timeH, serviceLow, serviceHi, arrivalRate)
## Customer arrival time: 3.39 
## Waiting Time: 6.74 
## Start Time: 10.13 
## Exit Time: 20.13 
## [current system time: 3.39 Server Available 20.13 ]
## Customer arrival time: 4.79 
## Waiting Time: 15.34 
## Start Time: 20.13 
## Exit Time: 28.13 
## [current system time: 4.79 Server Available 28.13 ]
## Customer arrival time: 5.07 
## Waiting Time: 23.06 
## Start Time: 28.13 
## Exit Time: 33.13 
## [current system time: 5.07 Server Available 33.13 ]
## Customer arrival time: 6.41 
## Waiting Time: 26.72 
## Start Time: 33.13 
## Exit Time: 41.13 
## [current system time: 6.41 Server Available 41.13 ]
## Customer arrival time: 7.56 
## Waiting Time: 33.57 
## Start Time: 41.13 
## Exit Time: 51.13 
## [current system time: 7.56 Server Available 51.13 ]
## Customer arrival time: 8.42 
## Waiting Time: 42.71 
## Start Time: 51.13 
## Exit Time: 60.13 
## [current system time: 8.42 Server Available 60.13 ]
## Customer arrival time: 9.52 
## Waiting Time: 50.61 
## Start Time: 60.13 
## Exit Time: 65.13 
## [current system time: 9.52 Server Available 65.13 ]
## Customer arrival time: 14.53 
## Waiting Time: 50.6 
## Start Time: 65.13 
## Exit Time: 73.13 
## [current system time: 14.53 Server Available 73.13 ]
## Customer arrival time: 15.08 
## Waiting Time: 58.05 
## Start Time: 73.13 
## Exit Time: 83.13 
## [current system time: 15.08 Server Available 83.13 ]
## Customer arrival time: 15.08 
## Waiting Time: 68.05 
## Start Time: 83.13 
## Exit Time: 91.13 
## [current system time: 15.08 Server Available 91.13 ]
## Customer arrival time: 16.16 
## Waiting Time: 74.97 
## Start Time: 91.13 
## Exit Time: 99.13 
## [current system time: 16.16 Server Available 99.13 ]
## Customer arrival time: 16.42 
## Waiting Time: 82.71 
## Start Time: 99.13 
## Exit Time: 107.13 
## [current system time: 16.42 Server Available 107.13 ]