# ShiftOps Team Estimation - Inconsistencies & Issues


**Last Updated:** 2025-11-20

## Critical Inconsistencies

### 1. Formula Differences

#### Analyzer vs Cost Calculator

- **Analyzer:** `sqrt(reviews) * multiplier * adjustments`
- **Cost Calculator:** `baseTeam * weighted_factors`
- **Impact:** Same business can get different estimates from different paths

#### JavaScript vs PHP

- **JavaScript:** Missing rating and service complexity adjustments
- **Impact:** Fallback estimates are less accurate than PHP versions

### 2. Data Structure Mismatch

**Problem:** Validation expects object, but Cost Calculator stores integer

**Location:** `v2/pages/shiftops-report.php:7563`

```javascript
hasTeamSizeEstimate: !!(
  data.analysis_data?.team_size_estimate?.estimated_team_size > 0
);
```

**Reality:** Cost Calculator stores:

```php
'team_size_estimate' => 12  // Integer, not object
```

**Impact:** Validation may fail even when team size exists

### 3. Multiple Fallback Formulas

#### Fallback 1: Analyzer Fallback (`shiftops.php:4617`)

```php
$teamSize = max(10, min(100, round($reviewCount / 50)));
```

- Formula: `reviews / 50`
- Range: 10-100

#### Fallback 2: Loading Screen (`shiftops.php:2822`)

```javascript
Math.max(10, Math.floor(reviewCount / 50));
```

- Formula: `reviews / 50`
- Range: 10+ (no max)

#### Fallback 3: Operational Insights (`shiftops-report.php:14874`)

```javascript
Math.max(5, Math.min(50, Math.round(bizInfo.user_ratings_total / 20)));
```

- Formula: `reviews / 20`
- Range: 5-50

#### Fallback 4: JavaScript (`shiftops-report.php:6867`)

```javascript
Math.sqrt(reviewCount) * multiplier;
```

- Formula: `sqrt(reviews) * multiplier`
- Range: 1+ (no max)

**Impact:** Same business gets different estimates depending on which fallback triggers

### 4. Default Value Inconsistencies

| Location             | Default | Rationale              |
| -------------------- | ------- | ---------------------- |
| Analyzer             | 10      | Hardcoded              |
| Cost Calculator      | 3-8     | Industry base staffing |
| JavaScript           | 1       | Minimum team size      |
| Loading Screen       | 10      | Hardcoded              |
| Report Fallback      | 10      | Hardcoded              |
| Operational Insights | 10      | Hardcoded              |

**Impact:** No consistent default when data is missing

### 5. Missing Factors

#### Analyzer Missing:

- Operating hours
- Price level
- Confidence scoring
- Data quality assessment
- Maximum cap

#### Cost Calculator Missing:

- None (most complete)

#### JavaScript Missing:

- Rating adjustment
- Service complexity adjustment
- Operating hours
- Price level
- Maximum cap

### 6. Hardcoded Values Without Documentation

#### Analyzer

- Rating thresholds: 4.5, 3.5 (no explanation)
- Service complexity multipliers: 1.3, 1.1 (no research cited)
- Rating adjustments: 1.2, 0.8 (no justification)

#### Cost Calculator

- Reviews per employee/month: 10, 6, 8, 4, 12, 7, 6 (claimed research, no citation)
- Base staffing: 5, 3, 3, 2, 8, 3, 3 (no validation)
- Factor weights: 0.4, 0.3, 0.2, 0.1 (no optimization)
- Business age thresholds: 50, 500, 1000 reviews (arbitrary)

#### JavaScript

- Confidence thresholds: 50, 100 reviews (no justification)

### 7. Edge Case Handling Differences

#### Zero Reviews

- **Analyzer:** Returns 1 (minimum)
- **Cost Calculator:** Returns baseTeam (3-8)
- **JavaScript:** Returns 1 (minimum)

#### Missing Business Type

- **All:** Default to 'general'
- **Consistent:** ✓

#### Missing Rating

- **Analyzer:** Defaults to 0 (may trigger low rating adjustment)
- **Cost Calculator:** Defaults to 3.5 (neutral)
- **Impact:** Analyzer may underestimate for businesses without ratings

#### Missing Service Options

- **All:** Count = 0
- **Consistent:** ✓

#### Missing Operating Hours

- **Analyzer:** Not used
- **Cost Calculator:** Defaults to 40 hours/week
- **Impact:** Cost Calculator assumes standard workweek

#### Extreme Review Counts

- **Analyzer:** No cap (can return very high estimates)
- **Cost Calculator:** Capped at `reviews / 20`
- **JavaScript:** No cap
- **Impact:** Analyzer and JavaScript can overestimate for very popular businesses

### 8. Access Pattern Inconsistencies

#### Pattern 1: Direct Integer

```php
$teamSize = $analysis['cost_savings']['team_size_estimate'];
```

#### Pattern 2: Object Property (Incorrect)

```javascript
data.analysis_data?.team_size_estimate?.estimated_team_size;
```

#### Pattern 3: Safe Access

```javascript
costSavings.team_size_estimate || 10;
```

#### Pattern 4: Nested Path

```javascript
data.analysis_data?.cost_savings?.team_size_estimate;
```

**Impact:** Code may break if structure changes

### 9. Industry Multiplier Differences

#### Analyzer & JavaScript

| Industry   | Multiplier |
| ---------- | ---------- |
| restaurant | 0.8        |
| cafe       | 0.6        |
| bar        | 0.7        |
| store      | 0.5        |
| hospital   | 2.0        |
| pharmacy   | 1.2        |
| general    | 0.7        |

#### Cost Calculator (Different Approach)

Uses base staffing + reviews per employee/month instead of multipliers

**Impact:** Different calculation methods for same industries

### 10. Confidence Calculation Differences

#### Cost Calculator

```php
score = 0
if (reviewCount > 50): score += 2
if (has opening_hours): score += 2
if (has service_options): score += 1
if (has price_level): score += 1

if (score >= 5): 'high'
if (score >= 3): 'medium'
else: 'low'
```

#### JavaScript

```javascript
if (reviewCount > 100): 'high'
else if (reviewCount > 50): 'medium'
else: 'low'
```

**Impact:** Different confidence levels for same business

### 11. Maximum Cap Inconsistencies

- **Analyzer:** No maximum cap
- **Cost Calculator:** `max(3, ceil(reviews / 20))`
- **JavaScript:** No maximum cap
- **Operational Insights:** `min(50, ...)` (different formula)

**Impact:** Estimates can vary wildly for high-review businesses

### 12. Business Age Estimation

**Only in Cost Calculator:**

- Based solely on review count
- Assumes linear relationship
- No validation against actual business data

**Impact:** May misestimate team size for new but popular businesses

### 13. Service Complexity Calculation

#### Analyzer

```php
$serviceTypes = count(array_filter($serviceOptions));
if ($serviceTypes >= 3): * 1.3
elseif ($serviceTypes >= 2): * 1.1
```

#### Cost Calculator

```php
$serviceTypes = count(array_filter($serviceOptions));
$complexityFactor = 1.0 + ($serviceTypes * 0.15);
```

**Impact:** Different multipliers for same service complexity

### 14. Rating Adjustment Differences

#### Analyzer

```php
if (rating >= 4.5 && reviewCount > 100): * 1.2
elseif (rating < 3.5): * 0.8
```

#### Cost Calculator

```php
if (rating >= 4.5 && priceLevel >= 3): 1.3
elseif (rating >= 4.0 && priceLevel >= 2): 1.15
elseif (rating < 3.5): 0.85
else: 1.0
```

**Impact:** Different adjustments for same rating

### 15. Missing Validation

- No validation that estimate is reasonable for business type
- No validation against industry benchmarks
- No sanity checks for extreme values
- No logging of estimation confidence in Analyzer

### 16. Return Type Inconsistencies

- **Analyzer:** Returns integer
- **Cost Calculator:** Returns array (but stores integer)
- **JavaScript:** Returns object

**Impact:** Code must handle multiple formats

## Summary of Issues

### High Priority

1. Formula differences between implementations
2. Data structure mismatch (object vs integer)
3. Multiple conflicting fallback formulas
4. No maximum cap in Analyzer/JavaScript
5. Validation expects wrong structure

### Medium Priority

6. Missing factors in Analyzer/JavaScript
7. Hardcoded values without research backing
8. Inconsistent default values
9. Different confidence calculations
10. Edge case handling differences

### Low Priority

11. Industry multiplier approach differences
12. Service complexity calculation differences
13. Rating adjustment differences
14. Missing validation and logging
15. Return type inconsistencies

## Recommendations

1. **Unify formulas** - Use same calculation method everywhere
2. **Standardize structure** - Consistent return format
3. **Consolidate fallbacks** - Single fallback formula
4. **Add maximum caps** - Prevent unrealistic estimates
5. **Fix validation** - Match expected structure
6. **Document hardcoded values** - Explain rationale
7. **Add validation** - Sanity checks and logging
8. **Research benchmarks** - Validate multipliers and factors
