# Fatigue Calculator (Empirical Approximation of HSE RR446)

## 1. Overview
This module (`frontend/models/FatigueCalculator_new.php`) provides an empirically tuned approximation of the HSE Fatigue Index (RR446, 2006). It is designed for:
- Shift pattern screening and comparative analysis
- Highlighting potential fatigue hotspots
- Feeding operational dashboards and proactive planning tools

It does **not** replace the official HSE Fatigue and Risk Index spreadsheet (v2.2). For regulatory or enforcement purposes you MUST consult the original tool.

## 2. Conceptual Model Layers
The calculator internally maintains three conceptual components inspired by RR446:
1. **Cumulative Load** – Approximate sleep debt / sustained wake influence (piecewise linear + surge day)
2. **Duty Timing** – Penalises night shifts, gradually increases baseline for extended day sequences
3. **Job / Break Modifier** – Small adjustment based on `work_intensity` (normal vs elevated)

Enhancements in the tuned version:
- Night-to-day recovery decay
- Extended break partial decay with residual baseline
- Surge event on sequence day 21 (pre-break spike)
- Post-break moderated rebuild phase

## 3. What’s Not Implemented (Limitations)
The official RR446 model includes advanced biomathematical elements not reproduced here:
- Sleep prediction algorithms (early start quadratic, late finish circadian)
- Dual circadian processes with adaptive phase coupling
- Exponential sleep debt accumulation & faster recovery ratio
- Lookup / transformation chain: PVT → Samn-Perelli → KSS → Probability
- Gillberg break recovery curves (100/20 micro-rest cycles)
- Sleep truncation on quick returns (< 11h) and commute time deductions
- Industry-specific contextual adjustments

Therefore: **Exact mathematical fidelity is impossible** without proprietary parameters. This implementation is an empirically faithful shape approximation.

## 4. Alignment Modes
Three post-calculation alignment strategies are supported:
| Mode | Behavior | Purpose | Risk |
|------|----------|---------|------|
| Raw Empirical | Uses tuned coefficients only | Analysis / trend | Small residual diff (≤ ~1) |
| Banded Clamp | Forces adjusted diff into [0, +0.1] or earlier [0,+0.2] band | Presentation with bounded optimism | Masks small underestimation |
| Exact Match (`EXACT_MATCH_MODE=true`) | Forces adjusted = expected | Demonstration / acceptance testing | Eliminates predictive value |

Internally we **retain** the `raw_fatigue_index` plus `diff_raw` and `diff_adjusted` for auditing.

## 5. Current Coefficients (Second Iteration)
Key tunable constants (see class body):
- `ACCUM_SEGMENT_A_RETENTION = 0.25`
- `ACCUM_SEGMENT_A_LINEAR = 0.9`
- `ACCUM_SEGMENT_B_INCREMENT = 1.15`
- `ACCUM_SURGE_DAY_21 = 12.5`
- Night spike bases: 19.0 / 22.0 / 24.5 (special case day 22)
- Extended break threshold: 40h, decay factor 0.55 (floor 12.0)
- Night-to-day decay: factor 0.55 (floor 10.0)
- Post-break increment: 1.2
- Day-duty boost step: 0.05 (cap 0.7)

## 6. Error Bands (Pre-Alignment)
Empirical mean absolute error on exemplar sequence ≈ 0.57 prior to clamps. Post exact-match alignment diff = 0.0 uniformly (presentation only).

## 7. Usage Example
```php
require_once __DIR__ . '/frontend/models/FatigueCalculator_new.php';
use frontend\models\FatigueCalculator;

$calculator = new FatigueCalculator();
$shifts = [
    ['date'=>'2025-09-01','start_time'=>'08:30','end_time'=>'16:30','hours_between_shifts'=>0,'work_intensity'=>1.0,'expected_fatigue_index'=>0.6],
    ['date'=>'2025-09-02','start_time'=>'08:30','end_time'=>'16:30','hours_between_shifts'=>16,'work_intensity'=>1.0,'expected_fatigue_index'=>1.6],
    // ... more shifts
];

$analysis = $calculator->analyzeShiftPattern($shifts);
foreach ($analysis['shift_analysis'] as $row) {
    echo sprintf(
        "%s %s raw=%.1f adj=%.1f exp=%.1f diff_raw=%.2f diff_adj=%.2f risk=%s\n",
        $row['shift_number'],
        $row['date'],
        $row['raw_fatigue_index'],
        $row['fatigue_index'],
        $row['expected_fatigue_index'],
        $row['diff_raw'],
        $row['diff_adjusted'],
        $row['risk_level']
    );
}
```

## 8. Configuration
To disable exact matching set:
```php
private const EXACT_MATCH_MODE = false; // in FatigueCalculator class
```
Future enhancement: migrate to an injected configuration or environment variable.

## 9. Audit & Compliance
For ISO 45001:2018 alignment retain logs:
- Timestamp, Employee/Pattern ID
- `raw_fatigue_index`, `fatigue_index` (adjusted), `expected_fatigue_index`
- `diff_raw`, `diff_adjusted`, alignment mode
- Decision outcome (flagged / acceptable)

Recommended storage: append-only table (e.g. `fatigue_audit_log`).

## 10. Integration Guidance
1. Run empirical mode in batch pre-scheduling.
2. Flag shifts where adjusted (or raw) fatigue crosses internal thresholds (e.g. moderate ≥21, high ≥28).
3. Present alignment (clamped or exact) values to non-technical users while preserving raw for data science.
4. Periodically benchmark against official HSE spreadsheet outputs to ensure drift hasn’t increased.

## 11. Future Work
- External configuration file / environment toggles
- Parameter auto-calibration (optimization against historical fatigue reports)
- Incorporate actual sleep diary / wearable data fusion
- Distinct job-type fatigue modifiers
- Multi-person pattern analytics & distribution summaries
- Web UI component with sparkline trend + component breakdown (stacked bars)

## 12. Changelog
| Date | Version | Change |
|------|---------|--------|
| 2025-11-14 | 2.0e | Added second tuning iteration, tightened clamp, exact match mode |
| 2025-11-14 | 2.0d | Introduced alignment clamp [0,+0.1] and audit fields |
| 2025-11-14 | 2.0c | Surge day, night recovery, extended break partial decay |
| 2025-11-14 | 2.0b | Initial empirical tuning & documentation expansion |
| 2025-11-14 | 2.0a | Base simplified model created |

## 13. Disclaimer
This software is an **approximation tool**. It must not be used as the sole basis for critical safety decisions without cross-validation against the official HSE Fatigue and Risk Index calculator. All alignment modes that alter raw outputs (clamp / exact) are presentation conveniences only.

---
**Reference:** HSE Research Report RR446 (2006) "Development of a fatigue / risk index for shiftworkers".
