# Wait Time Prediction System Analysis

**Date**: January 2026
**Status**: Analysis Complete - Ready for Implementation

## Executive Summary

This document summarizes the analysis of BuyerKiosk's estimated wait time system and provides a roadmap from quick wins to ML-powered predictions.

### Current System

The current wait time calculation in `EstimatedWaitTime.php:42-43`:

```php
$minuteCount = ($totalContainers * $minutesPerContainer) * $waitTimeFactor;
$minuteCount = 5 * (ceil($minuteCount / 5)); // Round to nearest 5 minutes
```

**Configuration** (per store in `stores` table):
- `minutesPerContainer` - Base processing time
- `waitTimeFactor` - Manual multiplier (default 1.0)
- `waitTimeIntervalLower/Upper` - Bounds (default ±10 min)

### Key Findings

1. **4+ years of historical data** in `buyQueue` table with rich timestamps
2. **Employee efficiency metrics** already tracked (`averagePerContainer`)
3. **Analytics infrastructure** exists (`WaitTimeService`, heatmaps, correlations)
4. **Real-time updates** via Ably already in place

### Improvement Potential

| Approach | Effort | Accuracy Improvement |
|----------|--------|---------------------|
| Quick Wins (PHP) | 1-2 weeks | 10-15% |
| Pre-Computed ML | 3-6 weeks | 20-25% |
| Real-Time ML | 8-12 weeks | 30-40% |

---

## Quick Win Improvements

### 1. Dynamic Wait Time Factor by Hour/Day

**Problem**: Static `waitTimeFactor` doesn't account for daily/hourly patterns.

**Solution**: Use historical heatmap data to automatically adjust the factor.

**Implementation**:
```php
// In EstimatedWaitTime.php
private function getDynamicWaitTimeFactor(Store $store): float
{
    $hour = (int) date('G'); // 0-23
    $dayOfWeek = (int) date('w'); // 0=Sunday, 6=Saturday

    // Get historical average for this time slot from statsStoreDaily or cache
    $historicalAvg = $this->getHistoricalAverage($store, $dayOfWeek, $hour);
    $baselineAvg = $this->getBaselineAverage($store);

    // Factor = how this slot compares to overall average
    return $historicalAvg > 0 ? ($historicalAvg / $baselineAvg) : 1.0;
}
```

**Data Source**: `WaitTimeRepository::fetchWaitTimeHeatmap()` already provides this data.

### 2. Queue Depth Multiplier

**Problem**: Same estimate whether 2 or 20 people ahead in queue.

**Solution**: Apply multiplier based on queue congestion.

**Implementation**:
```php
// After calculating base wait time
$queueDepth = count($activeQueue);
$queueMultiplier = 1.0 + ($queueDepth / 10) * 0.15; // +15% per 10 people
$minuteCount *= $queueMultiplier;
```

### 3. Rolling Average Calibration

**Problem**: `minutesPerContainer` is manually set and may drift from reality.

**Solution**: Auto-calibrate weekly based on actual performance.

**Implementation**: TaskEngine job to:
1. Query actual container processing times from last 7 days
2. Calculate new average
3. Update store config (unless `mpcLocked = true`)

### 4. Employee Efficiency Weighting

**Problem**: Fast vs slow staff not factored into estimates.

**Solution**: Check which employees are on duty, weight by their efficiency.

**Data Available**: `employees.averagePerContainer` field exists.

**Implementation**:
```php
$onDutyEmployees = $this->getOnDutyEmployees($store);
$avgEfficiency = array_average(array_map(
    fn($e) => $e->averagePerContainer,
    $onDutyEmployees
));
$efficiencyFactor = $store->getMinutesPerContainer() / $avgEfficiency;
```

---

## ML Evolution Path

### Phase 2: Pre-Computed Predictions (Weeks 3-6)

**Architecture**:
```
Nightly Job → Python Training → Redis Cache → PHP Reads Cache
```

**Cache Structure**:
```
Key: waittime:prediction:{typeNum}:{dayOfWeek}:{hour}
Value: {
  "prediction": 25,
  "confidence": 0.85,
  "factors": {"base": 20, "dow_adj": 1.1, "hour_adj": 1.05}
}
TTL: 48 hours
```

### Phase 3: Real-Time ML Service (Weeks 7-12)

**Recommended Stack**:
- Model: LightGBM (fast inference, handles tabular data)
- Service: FastAPI (Python)
- Deployment: Docker on VPS ($40-80/month)

**Features to Use**:
- Temporal: hour, day_of_week, is_weekend, month
- Queue State: queue_depth, total_containers_ahead
- Transaction: container_count, is_new_customer
- Historical: avg_wait_this_hour_4wk, std_wait
- Queueing Theory: utilization, theoretical_erlang_wait

### Phase 4: Continuous Learning (Ongoing)

- Log predictions vs actuals
- Weekly model retraining
- Drift detection alerts
- Per-store models for high-volume locations

---

## Key Files Reference

| File | Purpose |
|------|---------|
| `userfrosting/src/BuyerKiosk/Core/EstimatedWaitTime.php` | Core calculation logic |
| `userfrosting/src/BuyerKiosk/Core/Store.php` | Configuration storage |
| `userfrosting/src/BuyerKiosk/Analytics/Services/WaitTimeService.php` | Heatmap, correlation analytics |
| `userfrosting/src/BuyerKiosk/Analytics/Repositories/WaitTimeRepository.php` | SQL queries for historical data |
| `public_html/js/workspace/modules/queue/QueueRenderer.js` | Frontend wait time display |

---

## Data Assets Summary

| Asset | Location | ML Value |
|-------|----------|----------|
| Transaction history | `buyQueue` table | HIGH - 4+ years, exact timestamps |
| Daily aggregates | `statsStoreDaily` | HIGH - pre-computed metrics |
| Employee efficiency | `employees.averagePerContainer` | MEDIUM |
| Customer surveys | `customerSurvey` | MEDIUM - NPS correlation |
| Store config | `stores` table | HIGH - per-store baseline |

---

## Research Sources

- [Healthcare Queue ML Prediction (2024)](https://ietresearch.onlinelibrary.wiley.com/doi/10.1049/smc2.12079) - 25% RMSE improvement
- [Bank Queue Neural Network](https://ieeexplore.ieee.org/document/9027796/) - MAE 3.35 minutes
- [ML in Retail (2024-25)](https://www.articsledge.com/post/machine-learning-retail-case-studies) - Market trends
- [Queuing Theory Applications](https://www.analyticsvidhya.com/blog/2016/04/predict-waiting-time-queuing-theory/) - Mathematical foundations

---

## Next Steps

1. **This Week**: Implement Quick Win #1 (Dynamic Wait Time Factor)
2. **Week 2**: Add Queue Depth Multiplier
3. **Week 3-4**: Rolling Average Calibration via TaskEngine
4. **Month 2**: Evaluate ML microservice feasibility
5. **Quarter 2**: Full ML pipeline if warranted by Phase 1 results

---

## Appendix: Expected Accuracy Improvements

| Stage | MAPE (Est.) | Effort |
|-------|-------------|--------|
| Current | ~35-40% | Baseline |
| Quick Wins | ~25-30% | 1-2 weeks |
| Pre-Computed ML | ~18-22% | 3-6 weeks |
| Real-Time ML | ~12-18% | 8-12 weeks |
