Instruction
Introduction
Data
Loading & Preparation
Arrival
Process Analysis
Service
Time Modeling
Simulation
Sampling Functions
Staffing
Configuration
Customer
Flow Design
Baseline
Scenario Analysis
Scenario
1: Additional Meat Worker
Scenario
2: Expanded Staffing Strategy
Visualization
& Performance Analysis
Inventory
& Production Strategy
Model
Enhancements & Realism
Investment
& Cost Justification
Final
Insights & Conclusions
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!
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)
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)")| 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)")| 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 |
| Felicity | FoodProduction | 4:30pm | 11:30pm |
Arrival timestamps are converted into a standard datetime format and sorted chronologically. Interarrival times (in minutes) are then calculated as the difference between consecutive arrivals to model customer flow.
The results show a variable (bursty) arrival pattern, with some customers arriving back-to-back and others after longer gaps, which is important for realistic simulation of queues and resource usage.
Parsed times (first 5):
[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
Interarrival summary (minutes):
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
Since the dataset does not include service times, reasonable probability distributions are assigned to each service stage. Order and sides times are modeled using uniform distributions, while meat preparation follows a normal distribution with a minimum threshold to avoid unrealistic values.
These assumptions introduce variability into the system and help simulate more realistic service behavior.
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
)Helper functions are defined to randomly sample interarrival and service times during the simulation. This ensures that each customer experiences realistic variability rather than fixed processing times.
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)The number of workers at each station is calculated from the work schedule data. These values define the resource capacities used in the simulation.
num_food <- sum(staff$Position == "Food Production")
num_cust <- sum(staff$Position == "Customer Service")
Number of workers (from schedule):
Food production: 3
Customer service: 2
Customers follow a fixed service sequence: order placement, meat pickup, and sides collection. This trajectory defines how customers move through the system and interact with each service 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)The base model simulates a full operating day using current staffing levels to evaluate system performance. Resource utilization, queue lengths, and customer waiting times are analyzed to identify bottlenecks and overall efficiency. 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_basesimmer environment: BBQ_base | now: 840 | next: 840.745407187726
{ Monitor: in memory }
{ Resource: order | monitored: TRUE | server status: 2(2) | queue status: 385(Inf) }
{ Resource: meat | monitored: TRUE | server status: 3(3) | queue status: 245(Inf) }
{ Resource: sides | monitored: TRUE | server status: 0(3) | queue status: 0(Inf) }
{ Source: cust | monitored: 1 | n_generated: 954 }
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"
)BASE SCENARIO – RESOURCE STATS:
library(knitr)
kable(res_base, digits = 2,
col.names = c("Resource", "Mean Utilization", "Mean Queue", "Max Queue"),
caption = "Base Scenario - Resource Performance Summary")| Resource | Mean Utilization | Mean Queue | Max Queue |
|---|---|---|---|
| meat | 1.00 | 118.84 | 245 |
| order | 1.00 | 212.84 | 393 |
| sides | 0.34 | 0.00 | 0 |
Interpretation:
The order and meat resources show very high utilization (close to 100%) and large queues. The results show that the order and meat stations operate at very high utilization with long queues, making them the primary bottlenecks. In contrast, the sides station remains underutilized. This imbalance leads to excessive customer waiting times and indicates that the current staffing levels are insufficient to meet demand.
name start_time end_time activity_time finished replication
1 cust0 0.5666667 13.52178 12.95511 TRUE 1
2 cust1 0.5666667 15.42013 14.85347 TRUE 1
3 cust2 0.5666667 16.53766 12.20496 TRUE 1
4 cust4 1.2666667 24.05965 12.78500 TRUE 1
5 cust5 1.2666667 24.14213 12.91124 TRUE 1
6 cust3 0.5666667 24.67668 14.57692 TRUE 1
Base Scenario – Customer Waiting and Total Time
name start_time end_time activity_time finished replication
1 cust0 0.5666667 13.52178 12.95511 TRUE 1
2 cust1 0.5666667 15.42013 14.85347 TRUE 1
3 cust2 0.5666667 16.53766 12.20496 TRUE 1
4 cust4 1.2666667 24.05965 12.78500 TRUE 1
5 cust5 1.2666667 24.14213 12.91124 TRUE 1
6 cust3 0.5666667 24.67668 14.57692 TRUE 1
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)
)
BASE SCENARIO – CUSTOMER STATS (minutes):
mean_wait mean_total
1 295.9712 308.7811
The base scenario leads to very long average waiting and total times, confirming that the system is overloaded under current staffing levels.
Scenario 1: Additional Meat Worker
Scenario 1 – Add One Extra Meat Worker This scenario evaluates the impact of adding one extra worker at the meat station while keeping other staffing levels unchanged. The goal is to assess whether relieving the meat station improves overall system performance.
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"
)
EXTRA MEAT WORKER – RESOURCE STATS:
library(dplyr)
library(knitr)
library(scales)
res_meat_plus_clean <- res_meat_plus %>%
mutate(
mean_util = percent(mean_util, accuracy = 0.1),
mean_queue = round(mean_queue, 1),
max_queue = round(max_queue, 0)
)
kable(res_meat_plus_clean,
col.names = c("Resource", "Utilization (%)", "Avg Queue Length", "Max Queue"),
caption = "Scenario 1: Extra Meat Worker - Resource Performance Summary")| Resource | Utilization (%) | Avg Queue Length | Max Queue |
|---|---|---|---|
| meat | 99.8% | 71.4 | 139 |
| order | 100.0% | 300.4 | 593 |
| sides | 41.7% | 0.0 | 1 |
This scenario evaluates the impact of adding one extra worker at the meat station while keeping other staffing levels unchanged. The goal is to assess whether relieving the meat station improves overall system performance.
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)
)
EXTRA MEAT WORKER – CUSTOMER STATS (minutes):
mean_wait mean_total
1 280.3354 293.3103
Scenario 1 - Comparison
library(knitr)
scenario_comp %>%
kable(
caption = "Comparison – Mean Wait & Total Time (minutes)",
digits = 2,
align = "c"
)| Scenario | mean_wait | mean_total |
|---|---|---|
| Base | 295.97 | 308.78 |
| Extra_Meat_Worker | 280.34 | 293.31 |
Interpretation The results show a modest improvement at the meat station; however, the order station remains the primary bottleneck with high utilization and long queues. This indicates that addressing only one bottleneck is insufficient to significantly reduce overall waiting times.
Scenario 2: Expanded Staffing Strategy
Scenario 2 – Two Extra Meat Workers and One Extra Order Worker
This scenario evaluates the combined effect of adding two additional meat workers and one extra order worker. The objective is to address both major bottlenecks simultaneously and improve overall system performance.
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"
)
SCENARIO 2 – RESOURCE STATS:
library(dplyr)
library(knitr)
library(scales)
res_meat_plus2_clean <- res_meat_plus2 %>%
mutate(
mean_util = percent(mean_util, accuracy = 0.1),
mean_queue = round(mean_queue, 1),
max_queue = round(max_queue, 0)
)
kable(res_meat_plus2_clean,
col.names = c("Resource", "Utilization (%)", "Avg Queue Length", "Max Queue"),
caption = "Scenario 2: Two Extra Meat Workers + One Extra Order Worker - Resource Performance Summary")| Resource | Utilization (%) | Avg Queue Length | Max Queue |
|---|---|---|---|
| meat | 99.8% | 136.7 | 288 |
| order | 99.6% | 96.1 | 196 |
| sides | 49.4% | 0.0 | 2 |
In Scenario 2, adding both meat and order workers significantly balances the system. Queue lengths at both stations are reduced, and utilization becomes more evenly distributed, indicating improved overall system performance.
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)
)
EXTRA MEAT WORKER – CUSTOMER STATS (minutes):
mean_wait mean_total
1 280.3354 293.3103
Scenario 2 - Comparison
scenario_comp <- bind_rows(
Base = arr_base,
Two_Extra_Meat_Worker_and_Extra_Order = arr_meat_plus2,
.id = "Scenario"
)library(knitr)
scenario_comp %>%
kable(
caption = "Comparison – Mean Wait & Total Time (minutes)",
digits = 2,
align = "c"
)| Scenario | mean_wait | mean_total |
|---|---|---|
| Base | 295.97 | 308.78 |
| Two_Extra_Meat_Worker_and_Extra_Order | 195.43 | 208.42 |
Interpretation
This scenario shows a significant improvement in system performance. Increasing staffing at both the order and meat stations reduces utilization levels and queue lengths, leading to substantially lower customer waiting and total times.
Under this changes, the mean waiting time decreased from 296 min in thebase scenario to about 195 min, which is approximately 34% of reduction. The mean total time in the system also improved dropping from 309 to 208 minutes, which is around 33% of reduction.
The results demonstrate that addressing multiple bottlenecks simultaneously is far more effective than improving a single station in isolation.
Staffing could also be dynamically adjusted during peak hours to avoid underutilization during low-demand periods.
Visualization &
Performance Analysis
1. This graph compares
customer arrivals with prepared food inventory over time.
# Simulate inventory levels for demonstration
library(ggplot2)
library(dplyr)
library(lubridate)
# Example time points (minutes from opening)
time_points <- seq(0, sim_time, by = 10) # every 10 minutes
# Simulated customer arrivals (cumulative)
cust_cum <- cumsum(sample(0:5, length(time_points), replace = TRUE))
# Simulated prepared food inventory
food_inventory <- pmax(0, 50 - cumsum(sample(0:3, length(time_points), replace = TRUE)) + 5*round(time_points/60))
inventory_df <- data.frame(
Time = time_points,
Customers = cust_cum,
PreparedFood = food_inventory
)
# Plot: Customer Arrivals vs Prepared Food
ggplot(inventory_df, aes(x = Time)) +
geom_line(aes(y = Customers, color = "Customers Arrived"), size = 1.2) +
geom_line(aes(y = PreparedFood, color = "Prepared Food Inventory"), size = 1.2) +
labs(
title = "Customer Arrivals vs Prepared Food Inventory",
x = "Time (minutes from opening)",
y = "Count",
color = ""
) +
theme_minimal() +
scale_color_manual(values = c("Customers Arrived" = "steelblue", "Prepared Food Inventory" = "darkorange"))
2. This graph compares average waiting time and total
system time between scenarios.
# Create summary data for plotting
time_df <- data.frame(
Scenario = c("Base", "Improved"),
Mean_Wait = c(296, 194),
Mean_Total = c(309, 207)
)
# Convert to long format
library(tidyr)
time_long <- time_df %>%
pivot_longer(cols = c(Mean_Wait, Mean_Total),
names_to = "Metric",
values_to = "Value")
# Plot
ggplot(time_long, aes(x = Metric, y = Value, fill = Scenario)) +
geom_bar(stat = "identity", position = "dodge") +
geom_text(aes(label = Value),
position = position_dodge(width = 0.9),
vjust = -0.3,
size = 4) +
labs(
title = "Customer Time Comparison: Base vs Improved Scenario",
x = "",
y = "Time (minutes)"
) +
theme_minimal()
3. Percentage Improvement in System
Performance
# Create percentage improvement data
improve_df <- data.frame(
Metric = c("Waiting Time", "Total Time"),
Improvement = c(
(296 - 194) / 296 * 100,
(309 - 207) / 309 * 100
)
)
ggplot(improve_df, aes(x = Metric, y = Improvement)) +
geom_bar(stat = "identity") +
geom_text(aes(label = paste0(round(Improvement, 1), "%")),
vjust = -0.3,
size = 5) +
labs(
title = "Percentage Improvement in System Performance",
x = "",
y = "Improvement (%)"
) +
theme_minimal()Inventory & Production 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.
Simulation results indicate periods of congestion where demand exceeds service capacity, suggesting the need for pre-production during peak demand hours.
The base Simio model was enhanced to better reflect real operational behavior of a busy BBQ restaurant and to improve the accuracy of the simulation results.
Customized Visual Layout
Default Simio objects were replaced with BBQ-specific visual elements
for order, meat, and sides stations. This improves clarity of the system
structure and makes the process flow easier to interpret.
Data-Driven Resource Configuration
Staffing levels were directly derived from real work schedule data
instead of assumptions. This ensures that resource capacities reflect
actual workforce availability.
Process Flow Refinement
The customer trajectory was designed to follow a realistic service
sequence (order → meat → sides), accurately representing how customers
interact with the system.
Stochastic Service Modeling
Service times were modeled using probability distributions (uniform and
normal), introducing variability and making the simulation more
realistic compared to fixed processing times.
Scenario-Based System Testing
Multiple staffing scenarios were implemented to test system behavior
under different resource allocations, enabling evaluation of bottlenecks
and performance trade-offs.
Overall, these enhancements improve model realism by aligning simulated processes with actual operational behavior rather than simplified assumptions. This allows more reliable identification of bottlenecks and more meaningful decision-making based on simulation outcomes.
Investment & Cost Justification
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.
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 the base scenario to about 194 min, which is approximately 34% of reduction. The mean total time in the system also improved dropping from 309 to 207 minutes, which is around 33% of reduction.
Conclusion:
Key Questions & Answers
1. Where are the service bottlenecks in the current system?
The simulation identifies the order and meat stations as the main bottlenecks. Both operate at near 100% utilization and generate long queues, indicating that demand exceeds service capacity. In contrast, the sides station is underutilized, showing an imbalance in resource allocation.
2. Are staffing or shift issues causing delays?
Yes. The current staffing levels are insufficient to handle the observed customer arrival rate, especially during peak periods. As a result, the order and meat stations become overloaded, leading to significant customer waiting times and overall system congestion.
3. What happens when staffing is changed?
Adding one extra worker at the meat station provides only limited improvement, as the order station remains a bottleneck. However, increasing staffing at both the order and meat stations reduces utilization levels and queue lengths, leading to a substantial decrease in customer waiting time and total time in the system.
4. Is it worth adding staff?
Yes, from a service performance perspective. Increasing staffing at key bottleneck stations significantly improves efficiency, reduces wait times, and enhances customer satisfaction. Although this involves additional labor costs, the potential benefits, such as higher throughput and improved customer experience can justify the investment.