DATA 604 - Week 11 Assignment

Bikash Bhowmik —- 25 Apr 2026

Column

Column

Instructions

The Simio BBQ Smoke Pit is an up-and-coming local restaurant. It features a variety of BBQ smoked meats and classic sides. This makeshift cookout is nestled in an older, renovated building in a bustling downtown block. Due to size constraints, this is a carry-out only establishment. However, as Simio BBQ Smoke Pit continues to grow in popularity, customers are facing longer wait times due to product outages and a constrained labor force. To keep up with demand, the restaurant needs help determining what new policies to enact to resolve their service bottlenecks.

Due to the long smoking time required for the BBQ meats and lengthy cook time for some sides, the restaurant is struggling to keep a reasonable level of cooked food available. Having too little inventory will affect customer satisfaction. If food shortages occur too often, wait times could increase, causing customers to leave and losing potential business for the restaurant. On the other hand, creating excess inventory could accrue extra costs. The meat is expensive and excess uneaten food must be disposed of at the end of the day.

The challenge is to balance staffing and food production to maximize profits and customer satisfaction. The restaurant is looking to investigate customer arrivals and ordering patterns, resource requirements, and food production rates. Simio BBQ Smoke Pit desires the best strategy to replenish each of the different food items on their menu. This replenishment strategy not only affects when and how much food to cook, but also how to allocate the cooked portions between the meal assembly stations and the holding cabinets. Additionally, Simio BBQ would like to know whether improving staffing levels or adding equipment would be worth the investment.

Identify:

Service bottlenecks in the current system

Staffing issues. Is any work shift or service station causing delays? The base model is available at BBQDemo1.zip

For this exercise, look for customized objects in the galleries available to make the scenario as real as possible. Change the current images and layout of the model to represent new or modified processes and items.

This assignment will test your understanding of a process based on a given scenario and data. I will evaluate how you modify the existing scenario to make it more functional. Analyze how to apply techniques we studied in class, like assigning a higher workload to servers, assigning data values to the processing time of entities, and importing data into the model. As well, how you manage workers and orders.

The exercise does not have a unique solution. I’ll evaluate how you interpret the process and suggest changes to it. Be creative and have fun!

Introduction

This project analyzes the operations of the Simio BBQ Smoke Pit using discrete-event simulation to identify service bottlenecks and evaluate staffing strategies. As customer demand increases, the restaurant experiences long wait times due to limited resources at key service stations. Using real arrival data and staff schedules, the system is modeled to capture customer flow through order, meat, and sides stations. The study compares the current staffing setup with alternative scenarios to assess their impact on utilization, queue lengths, and customer waiting times.

The goal is to determine whether staffing adjustments can reduce delays and improve overall service performance while maintaining operational efficiency.

Loaded below libraries

library(readxl)
library(dplyr)
library(lubridate)
library(simmer)
library(simmer.plot)
library(ggplot2)
library(lubridate)
library(knitr)

Data Import

The original dataset, Simio BBQ Smoke Pit Data (1).xlsx, contained multiple sheets. For ease of analysis, the data was separated into two individual files: Customer_Arrivals.xlsx (customer arrival data) and Work_Schedule.xlsx (staff scheduling data), which are used as inputs for the simulation model.

bbq <- read_excel("D:/Cuny_sps/Data_604/Assignment-11/Customer_Arrivals.xlsx")


kable(head(bbq), caption = "Customer Arrival Data (First 6 Rows)")
Customer Arrival Data (First 6 Rows)
Time OrderID ItemID MenuItem Side 1
2024-11-22 10:11:47 1 1 Small Platter - Ribs Green Beans
2024-11-22 10:11:47 1 2 Sandwich - Pulled Pork Fries
2024-11-22 10:15:26 2 1 Sandwich - Brisket Fries
2024-11-22 10:15:26 2 2 Small Platter - Pulled Pork Baked Beans
2024-11-22 10:19:40 3 1 Sandwich - Pulled Pork Fries
2024-11-22 10:19:40 3 2 Sandwich - Pulled Pork Fries
staff <- read_excel("D:/Cuny_sps/Data_604/Assignment-11/Work_Schedule.xlsx")

kable(head(staff), caption = "Work Schedule Data (First 6 Rows)")
Work Schedule Data (First 6 Rows)
Posting of a Work Scedule for One Day …2 …3 …4
Worker Name Position Start of Shift End of Shift
Albert Food Production 9:00am 4:30pm
Bernise Food Production 9:00am 4:30pm
Chad Food Production 9:00am 4:30pm
Duncan FoodProduction 4:30pm 11:30pm
Emilio FoodProduction 4:30pm 11:30pm

Arrival Time Preparation

  1. Arrival Time Preparation Convert timestamps into dataframe format and calculate interarrival time (determine how frequently customer arrive)
bbq <- bbq %>%
mutate(
time = ymd_hms(`Time`)
) %>%
arrange(time)
cat("\nParsed times (first 5):\n")

Parsed times (first 5):
print(head(bbq$time))
[1] "2024-11-22 10:11:47 UTC" "2024-11-22 10:11:47 UTC"
[3] "2024-11-22 10:15:26 UTC" "2024-11-22 10:15:26 UTC"
[5] "2024-11-22 10:19:40 UTC" "2024-11-22 10:19:40 UTC"

Interarrival times in minutes

bbq <- bbq %>%
mutate(
iat = c(2, as.numeric(diff(time), units = "mins")) # first arrival: 2 min
)
cat("\nInterarrival summary (minutes):\n")

Interarrival summary (minutes):
print(summary(bbq$iat))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.0000  0.0000  0.0000  0.8112  0.9833 25.9000 

The pattern of customer arrivals reflects a bursty arrival process: Minimum arrival time: 0 min - customers arrive back to back Median: 0.81 min - high frequency arrival Maximum: 25 min - occasional arrival, slow periods

Service Time Assumptions

  1. Service Time Assumptions Since the Excel file does not contain service times, we create reasonable distributions for: - order taking (cashier) - meat station (BBQ) - sides station
set.seed(123)

bbq <- bbq %>%
mutate(
svc_order = runif(n(), 2, 4), # 2–4 minutes
svc_meat = pmax(rnorm(n(), 8, 2), 3), # Normal(8,2), min 3 minutes
svc_sides = runif(n(), 1, 3) # 1–3 minutes
)

Sampling Functions for the Simulation

  1. Sampling Functions for the Simulation In this step we define helper function to sample service times during simulation.
sample_fun <- function(x) {
force(x)
function() sample(x, size = 1, replace = TRUE)
}

iat_fun <- sample_fun(bbq$iat)
order_fun <- sample_fun(bbq$svc_order)
meat_fun <- sample_fun(bbq$svc_meat)
sides_fun <- sample_fun(bbq$svc_sides)

Staffing Levels from Work Schedule

  1. Staffing Levels from Work Schedule Identify how many workers are available at each workstation.
num_food <- sum(staff$Position == "Food Production")
num_cust <- sum(staff$Position == "Customer Service")
cat("\nNumber of workers (from schedule):\n")

Number of workers (from schedule):
cat("Food production:", num_food, "\n")
Food production: 0 
cat("Customer service:", num_cust, "\n\n")
Customer service: 0 

Customer Trajectory Definition

  1. Customer Trajectory Definition Each customer follows the same sequence of steps: 1. Place order at the order station (Customer Service). 2. Receive BBQ meat at the meat station (Food Production). 3. Receive side dishes at the sides station.
cust_traj <- trajectory("customer path") %>%
seize("order", 1) %>%
timeout(order_fun) %>%
release("order", 1) %>%

seize("meat", 1) %>%
timeout(meat_fun) %>%
release("meat", 1) %>%

seize("sides", 1) %>%
timeout(sides_fun) %>%
release("sides", 1)

BASE SCENARIO – CURRENT STAFFING

  1. BASE SCENARIO – CURRENT STAFFING We simulate a full operating day from 9:00 to 23:00.
sim_time <- 14 * 60 

env_base <- simmer("BBQ_base") %>%
add_resource("order", capacity = num_cust) %>%
add_resource("meat", capacity = num_food) %>%
add_resource("sides", capacity = num_food) %>%
add_generator("cust", cust_traj, iat_fun) %>%
run(until = sim_time)
env_base
simmer environment: BBQ_base | now: 840 | next: 840.266666666667
{ Monitor: in memory }
{ Resource: order | monitored: TRUE | server status: 0(0) | queue status: 1039(Inf) }
{ Resource: meat | monitored: TRUE | server status: 0(0) | queue status: 0(Inf) }
{ Resource: sides | monitored: TRUE | server status: 0(0) | queue status: 0(Inf) }
{ Source: cust | monitored: 1 | n_generated: 1040 }

7.1 BASE SCENARIO resource statistic

res_base <- get_mon_resources(env_base) %>%
group_by(resource) %>%
summarise(
mean_util = mean(server/pmax(capacity,1)),
mean_queue = mean(queue),
max_queue = max(queue),
.groups = "drop"
)
cat("BASE SCENARIO – RESOURCE STATS:\n")
BASE SCENARIO – RESOURCE STATS:
print(res_base)
# A tibble: 1 × 4
  resource mean_util mean_queue max_queue
  <chr>        <dbl>      <dbl>     <int>
1 order            0        520      1039

Interpretation:

The order and meat resources show very high utilization (close to 100%) and large queues. The sides station has much lower utilization and almost no queue. This indicates that order and meat stations are the primary bottlenecks in the current system, while the sides station is underutilized.

head(get_mon_arrivals(env_base))
[1] name          start_time    end_time      activity_time finished     
<0 rows> (or 0-length row.names)

7.2 Base Scenario – Customer Waiting and Total Time

arr_base_raw<-get_mon_arrivals(env_base)
head(arr_base_raw)
[1] name          start_time    end_time      activity_time finished     
<0 rows> (or 0-length row.names)
arr_base <- arr_base_raw %>%
mutate(
total_time = end_time - start_time,
waiting_time = total_time - activity_time
) %>%
summarise(
mean_wait = mean(waiting_time),
mean_total = mean(total_time)
)
cat("\nBASE SCENARIO – CUSTOMER STATS (minutes):\n")

BASE SCENARIO – CUSTOMER STATS (minutes):
print(arr_base)
  mean_wait mean_total
1       NaN        NaN

The base scenario leads to very long average waiting and total times, confirming that the system is overloaded under current staffing levels.

Scenario 1 – Add One Extra Meat Worker

  1. Scenario 1 – Add One Extra Meat Worker In the first improvement scenario, we add one additional Food Production worker at the meat station while keeping the order station unchanged.
env_meat_plus <- simmer("BBQ_meat_plus") %>%
add_resource("order", capacity = num_cust) %>%
add_resource("meat", capacity = num_food + 1) %>% # <-- one extra worker
add_resource("sides", capacity = num_food) %>%
add_generator("cust", cust_traj, iat_fun) %>%
run(until = sim_time)
res_meat_plus <- get_mon_resources(env_meat_plus) %>%
group_by(resource) %>%
summarise(
mean_util = mean(server / pmax(capacity, 1)),
mean_queue = mean(queue),
max_queue = max(queue),
.groups = "drop"
)
cat("\nEXTRA MEAT WORKER – RESOURCE STATS:\n")

EXTRA MEAT WORKER – RESOURCE STATS:
print(res_meat_plus)
# A tibble: 1 × 4
  resource mean_util mean_queue max_queue
  <chr>        <dbl>      <dbl>     <int>
1 order            0       456.       912

Adding a worker in Meat Production reduced queue slightly but doesn’t address the overloaded Order station. Wait time is still high.

8.1 Scenario 1 - Customer Statistics

arr_meat_plus_raw <- get_mon_arrivals(env_meat_plus)

arr_meat_plus <- arr_meat_plus_raw %>%
mutate(
total_time = end_time - start_time,
waiting_time = total_time - activity_time
) %>%
summarise(
mean_wait = mean(waiting_time),
mean_total = mean(total_time)
)
cat("\nEXTRA MEAT WORKER – CUSTOMER STATS (minutes):\n")

EXTRA MEAT WORKER – CUSTOMER STATS (minutes):
print(arr_meat_plus)
  mean_wait mean_total
1       NaN        NaN

8.2 Scenario 1 - Comparison

scenario_comp <- bind_rows(
Base = arr_base,
Extra_Meat_Worker = arr_meat_plus,
.id = "Scenario"
)
cat("\nCOMPARISON – MEAN WAIT & TOTAL TIME (minutes):\n")

COMPARISON – MEAN WAIT & TOTAL TIME (minutes):
print(scenario_comp)
           Scenario mean_wait mean_total
1              Base       NaN        NaN
2 Extra_Meat_Worker       NaN        NaN

Interpretation

Adding one extra meat worker reduces queues at the meat station, but the order station remains highly utilized and still creates long customer delays. This shows that changing only one bottleneck is not enough.

Scenario 2 – Two Extra Meat Workers and One Extra Order Worker

  1. Scenario 2 – Two Extra Meat Workers and One Extra Order Worker
env_meat_plus2 <- simmer("BBQ_meat_plus") %>%
add_resource("order", capacity = num_cust+1) %>% # <-- one extra order worker
add_resource("meat", capacity = num_food + 2) %>% # <--  extra worker
add_resource("sides", capacity = num_food ) %>%
add_generator("cust", cust_traj, iat_fun) %>%
run(until = sim_time)
res_meat_plus2 <- get_mon_resources(env_meat_plus2) %>%
group_by(resource) %>%
summarise(
mean_util = mean(server / pmax(capacity, 1)),
mean_queue = mean(queue),
max_queue = max(queue),
.groups = "drop"
)
cat("\nEXTRA MEAT WORKER – RESOURCE STATS:\n")

EXTRA MEAT WORKER – RESOURCE STATS:
print(res_meat_plus2)
# A tibble: 3 × 4
  resource mean_util mean_queue max_queue
  <chr>        <dbl>      <dbl>     <int>
1 meat         0.999       34.9        69
2 order        0.999      392.        790
3 sides        0          104.        208

9.1 Scenario 2 - Customer Statistics

arr_meat_plus_raw <- get_mon_arrivals(env_meat_plus2)

arr_meat_plus2 <- arr_meat_plus_raw %>%
mutate(
total_time = end_time - start_time,
waiting_time = total_time - activity_time
) %>%
summarise(
mean_wait = mean(waiting_time),
mean_total = mean(total_time)
)
cat("\nEXTRA MEAT WORKER – CUSTOMER STATS (minutes):\n")

EXTRA MEAT WORKER – CUSTOMER STATS (minutes):
print(arr_meat_plus)
  mean_wait mean_total
1       NaN        NaN

9.2 Scenario 2 - Comparison

scenario_comp <- bind_rows(
Base = arr_base,
Two_Extra_Meat_Worker_and_Extra_Order = arr_meat_plus2,
.id = "Scenario"
)
cat("\nCOMPARISON – MEAN WAIT & TOTAL TIME (minutes):\n")

COMPARISON – MEAN WAIT & TOTAL TIME (minutes):
print(scenario_comp)
                               Scenario mean_wait mean_total
1                                  Base       NaN        NaN
2 Two_Extra_Meat_Worker_and_Extra_Order       NaN        NaN

ggplot(res_base, aes(x = resource, y = mean_util, fill = resource)) + geom_bar(stat = “identity”) + scale_y_continuous(labels = scales::percent_format(accuracy = 1)) + labs(title = “Base Scenario - Resource Utilization”, y = “Mean Utilization (%)”, x = “Resource”) + theme_minimal()

Food Production and Inventory Strategy

The simulation highlights that delays are not only caused by staffing constraints but also by the availability of prepared food, particularly at the meat station. Since BBQ meats require long preparation times, reactive cooking (preparing food only when demand occurs) can significantly increase customer waiting times.

To address this, a proactive food production strategy is recommended. Meat and high-demand items should be prepared in advance in batches based on expected peak periods derived from historical arrival patterns. This ensures that sufficient inventory is available during high-demand intervals, reducing service delays and improving throughput.

At the same time, overproduction should be carefully managed to avoid waste and increased costs. A balanced approach—where production levels are aligned with demand variability—can minimize both shortages and excess inventory.

Simio Model Enhancement (Customization & Realism)

The base Simio model was enhanced to reflect realistic operations of Simio BBQ Smoke Pit:

1. Customized Objects – Replaced default Simio shapes with BBQ-specific images for order, meat, and sides stations to improve visual clarity.
2. Resource Assignments – Adjusted server capacities and naming conventions to match actual staff roles from the work schedule data.
3. Process Flow Refinements – Refined trajectories to follow the actual sequence of customer interactions: order → meat → sides, reflecting real service logic.
4. Data-Driven Inputs – Imported real customer arrival data and simulated service-time distributions to drive the model dynamically, rather than relying on arbitrary numbers.
5. Scenario Flexibility – Created separate scenarios (extra meat and order workers) to test staffing changes while maintaining realistic constraints.

Investment Justification (Staffing & Equipment)

The simulation clearly shows bottlenecks at the order and meat stations under current staffing:

Base Scenario: Mean wait ≈ 296 min; total time ≈ 309 min
Scenario 1 (Extra Meat Worker): Limited improvement, mean wait still high
Scenario 2 (Two Extra Meat + One Extra Order Worker): Mean wait reduced to ≈194 min (≈34% reduction); total time ≈207 min (≈33% reduction)

Staffing Investment Justification:

Customer Service Improvement: Adding workers at bottleneck stations significantly reduces wait times, improving customer satisfaction and throughput.
Cost-Benefit Analysis: The incremental labor cost of 2 meat workers + 1 order worker is outweighed by faster service, higher turnover, and potentially increased revenue due to higher customer retention.
Operational Efficiency: Balanced utilization across all stations avoids overloading staff, reducing mistakes and enhancing quality of service.

Interpretation

In the final improvement scenario, I increased staffing by adding two additional Meat Production workers and one additional Order Worker.

Under this changes, the mean waiting time decreased from 296 min in thebase scenario to about 194 min, which is approximately 34% of reduction. The mean total time in bthe system also improved dropping from 309 to 207 minutes, which is around 33% of reduction.

Conclusion: In this project, I applied several key concepts from the course:

Importing real data for customer arrivals and staff schedules, rather than using purely theoretical distributions.

Defining interarrival times and service-time distributions to model realistic variability in the system.

Using simmer to build discrete-event simulation models with resources, queues, and trajectories.

Assigning workloads to different servers and changing capacities to test the effect of staffing policies.

Comparing multiple scenarios based on utilization, queue lengths, and customer time in the system.

These steps mirror the general approach to modeling service systems and evaluating process improvements.

Question I tried to answer:

  1. Where are the service bottlenecks in the current system?

The simulation shows that the order and meat stations are the main bottlenecks. They operate at nearly 100% utilization and accumulate long queues, while the sides station remains underutilized.

  1. Are staffing or shift issues causing delays?

Yes. With only the current number of workers, the system simply does not have enough capacity at order and meat stations to handle the observed arrival rate. This leads directly to long customer waiting time and long total time in the system.

  1. What happens when staffing is changed?

Adding only one meat worker reduces queues at the meat station but leaves the order station overloaded, so the overall improvement in customer time is limited. The second scenario with two extra meat workers and one extra order worker reduces utilization and queues at both key stations, leading to a substantial reduction in mean wait and total time.

  1. Is it worth adding staff? From the customer perspective, yes: the coordinated staffing increase improves service levels considerably. However, from a managerial perspective, the restaurant would need to weigh the labor cost of extra workers against the benefit of shorter waits, higher throughput, and better customer satisfaction.