Trae Assistant
Initial commit: Enhanced Queue Strategy Lab with Import/Export and Error Handling
6c4d394
import os
import random
import simpy
import numpy as np
from flask import Flask, render_template, jsonify, request, send_from_directory
app = Flask(__name__, template_folder='templates')
# Configuration
MAX_SIM_TIME = 480 # 8 hours in minutes for analysis
SEED = 42
@app.route('/')
def index():
return render_template('index.html')
@app.errorhandler(404)
def page_not_found(e):
return render_template('index.html'), 404
@app.errorhandler(500)
def internal_server_error(e):
return jsonify(error="Internal Server Error", message=str(e)), 500
@app.route('/api/upload_config', methods=['POST'])
def upload_config():
try:
if 'file' not in request.files:
return jsonify({'error': 'No file part'}), 400
file = request.files['file']
if file.filename == '':
return jsonify({'error': 'No selected file'}), 400
if file:
import json
content = json.load(file)
return jsonify({'message': 'Config uploaded successfully', 'config': content})
except Exception as e:
return jsonify({'error': str(e)}), 500
class CallCenter:
def __init__(self, env, num_employees, service_time_avg, service_time_std):
self.env = env
self.staff = simpy.Resource(env, num_employees)
self.service_time_avg = service_time_avg
self.service_time_std = service_time_std
self.wait_times = []
self.service_times = []
self.utilization_log = []
self.events_trace = [] # For visualization: {'time': t, 'type': '...', 'id': ...}
def support(self, customer):
arrival_time = self.env.now
self.events_trace.append({'time': arrival_time, 'type': 'arrival', 'id': customer})
with self.staff.request() as request:
yield request
wait = self.env.now - arrival_time
self.wait_times.append(wait)
self.events_trace.append({'time': self.env.now, 'type': 'start', 'id': customer, 'wait': wait})
# Service time (Normal distribution, clipped at 0.5 min)
service_duration = max(0.5, random.gauss(self.service_time_avg, self.service_time_std))
yield self.env.timeout(service_duration)
self.service_times.append(service_duration)
self.events_trace.append({'time': self.env.now, 'type': 'finish', 'id': customer})
def customer_generator(env, center, arrival_rate):
"""
arrival_rate: Customers per hour
"""
i = 0
while True:
# Inter-arrival time (Exponential distribution)
yield env.timeout(random.expovariate(arrival_rate / 60.0))
i += 1
env.process(center.support(f'C{i}'))
@app.route('/api/simulate', methods=['POST'])
def simulate():
data = request.json
# Parameters
arrival_rate = float(data.get('arrival_rate', 60)) # Cust/hr
service_time = float(data.get('service_time', 5)) # Avg min
service_std = float(data.get('service_std', 1)) # Std Dev min
num_servers = int(data.get('num_servers', 3))
duration = float(data.get('duration', 60)) # Minutes to simulate
random.seed(SEED)
env = simpy.Environment()
center = CallCenter(env, num_servers, service_time, service_std)
env.process(customer_generator(env, center, arrival_rate))
env.run(until=duration)
# Calculate stats
avg_wait = np.mean(center.wait_times) if center.wait_times else 0
max_wait = np.max(center.wait_times) if center.wait_times else 0
served_count = len(center.service_times)
# Utilization estimate (Total Service Time / (Num Servers * Duration))
total_service = sum(center.service_times)
utilization = (total_service / (num_servers * duration)) * 100 if num_servers > 0 else 0
return jsonify({
'metrics': {
'avg_wait': round(avg_wait, 2),
'max_wait': round(max_wait, 2),
'served': served_count,
'utilization': round(utilization, 2)
},
'trace': center.events_trace
})
@app.route('/api/optimize', methods=['POST'])
def optimize():
data = request.json
arrival_rate = float(data.get('arrival_rate', 60))
service_time = float(data.get('service_time', 5))
service_std = float(data.get('service_std', 1))
cost_per_server_hr = float(data.get('cost_server', 20)) # $20/hr
cost_per_wait_hr = float(data.get('cost_wait', 50)) # $50/hr (Value of customer time/frustration)
results = []
# Test 1 to 15 servers
for n in range(1, 16):
random.seed(SEED) # Reset seed for fair comparison
env = simpy.Environment()
center = CallCenter(env, n, service_time, service_std)
env.process(customer_generator(env, center, arrival_rate))
env.run(until=480) # 8 hours
avg_wait_min = np.mean(center.wait_times) if center.wait_times else 0
total_wait_hours = sum(center.wait_times) / 60.0
# Total Cost = (Server Cost * 8h) + (Total Wait Hours * Wait Cost)
server_cost = n * cost_per_server_hr * 8
wait_cost = total_wait_hours * cost_per_wait_hr
total_cost = server_cost + wait_cost
utilization = (sum(center.service_times) / (n * 480)) * 100
results.append({
'servers': n,
'total_cost': round(total_cost, 2),
'server_cost': round(server_cost, 2),
'wait_cost': round(wait_cost, 2),
'avg_wait': round(avg_wait_min, 2),
'utilization': round(utilization, 1)
})
# Optimization: if cost starts increasing significantly and wait is low, we can stop,
# but let's run all 15 for the chart.
return jsonify({'results': results})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=7860, debug=True)