(function () {
function fmtT(s) { return "T+" + window.formatClock(s); }
function VitalsTable({ scenario, vitals }) {
const iv = scenario.initialVitals || {};
const rows = [
["Pulse (bpm)", Math.round(iv.hr), Math.round(vitals.hr)],
["BP (mmHg)", Math.round(iv.sys) + "/" + Math.round(iv.dia), Math.round(vitals.sys) + "/" + Math.round(vitals.dia)],
["MAP (mmHg)", window.computeMAP(iv.sys, iv.dia), window.computeMAP(vitals.sys, vitals.dia)],
["Resp (/min)", Math.round(iv.rr), Math.round(vitals.rr)],
["SpO₂ (%)", Math.round(iv.spo2), Math.round(vitals.spo2)],
["Pain (/10)", iv.pain, Math.round(vitals.pain)],
["AVPU", iv.avpu, vitals.avpu],
["GCS", iv.gcs, vitals.gcs],
["Temp (°C)", iv.temp, iv.temp != null ? (vitals.temp ?? iv.temp) : "—"]
];
return (
<table className="pr-table">
<thead><tr><th>Vital</th><th>On arrival</th><th>Latest recorded</th></tr></thead>
<tbody>
{rows.map((r, i) => <tr key={i}><td>{r[0]}</td><td>{r[1]}</td><td>{r[2]}</td></tr>)}
</tbody>
</table>
);
}
function PrintReport({ scenario, vitals, log, survival, elapsedSec, missionElapsedSec,
outcome, finished, criticalDone, criticalMissed, contraTaken, evacPriority }) {
const untreated = criticalDone.length === 0;
const interventions = (log || []).filter((l) => l.kind !== "sys");
const verdict = finished
? (outcome === "dead" ? "CASUALTY DID NOT SURVIVE" : outcome === "guarded" ? "UNSTABLE — HIGH TRANSPORT RISK" : "STABILIZED FOR EVACUATION")
: "SCENARIO IN PROGRESS";
const evacLabel = evacPriority ? evacPriority.replace("evac_", "").toUpperCase() : "NOT CALLED";
return (
<div className="print-report">
<div className="pr-head">
<div className="pr-title">TCCC · PATIENT TREATMENT REPORT</div>
<div className="pr-sub">
DD-1380 supplement · generated by the TCCC Patient Treatment Dashboard · {new Date().toLocaleString()}
</div>
</div>
<div className="pr-sec-head">1 · Casualty</div>
<table className="pr-table">
<tbody>
<tr><td>Name / Last-4</td><td>{scenario.name} / {scenario.last4}</td><td>Callsign</td><td>{scenario.callsign}</td></tr>
<tr><td>Age / Sex</td><td>{scenario.age} / {scenario.sex}</td><td>Working diagnosis</td><td>{scenario.diagnosis}</td></tr>
<tr><td>Patient clock</td><td>{fmtT(elapsedSec)}</td><td>Mission clock</td><td>{fmtT(missionElapsedSec || 0)}</td></tr>
</tbody>
</table>
<div className="pr-sec-head">2 · Mechanism of Injury</div>
<p className="pr-narrative">{scenario.mechanism}</p>
{scenario.moi &&
<table className="pr-table">
<tbody>
<tr><td>Event</td><td>{scenario.moi.event}</td></tr>
<tr><td>Forces</td><td>{scenario.moi.forces}</td></tr>
<tr><td>PPE</td><td>{scenario.moi.protection}</td></tr>
<tr><td>Timeline</td><td>{scenario.moi.timeline}</td></tr>
<tr><td>Findings</td><td>{scenario.moi.findings}</td></tr>
</tbody>
</table>
}
<div className="pr-sec-head">3 · Vital Signs</div>
<VitalsTable scenario={scenario} vitals={vitals} />
<div className="pr-sec-head">4 · Outcome</div>
<table className="pr-table">
<tbody>
<tr>
<td>Status</td>
<td className={outcome === "dead" ? "pr-dead" : ""}>{verdict}</td>
<td>Survival probability</td><td>{survival}% (textbook ceiling {scenario.expectedSurvival}% · untreated baseline {scenario.baseSurvival}%)</td>
</tr>
<tr>
<td>Critical actions</td><td>{criticalDone.length} of {criticalDone.length + criticalMissed.length}</td>
<td>EVAC priority</td><td>{evacLabel}</td>
</tr>
</tbody>
</table>
<div className="pr-sec-head">5 · Interventions Performed {untreated ? "— NONE" : `(${interventions.length})`}</div>
{untreated
? <p className="pr-narrative pr-dead">No interventions were recorded for this casualty.</p>
: <table className="pr-table">
<thead><tr><th>Time</th><th>Cat.</th><th>Action / event</th></tr></thead>
<tbody>
{interventions.map((l, i) =>
<tr key={i}><td>{fmtT(l.t)}</td><td>{l.tag}</td><td>{l.msg}</td></tr>
)}
</tbody>
</table>
}
<div className="pr-sec-head">6 · Critical Actions — Done / Missed</div>
<table className="pr-table">
<thead><tr><th></th><th>MARCH</th><th>Action</th><th>Ideal by</th><th>Weight</th></tr></thead>
<tbody>
{scenario.criticalActions.map((a) => {
const done = criticalDone.includes(a);
return (
<tr key={a.id} className={done ? "" : "pr-missed"}>
<td>{done ? "✓" : "✗"}</td><td>{a.category}</td><td>{a.label}</td>
<td>T+{String(a.byMin).padStart(2, "0")}:00</td><td>{a.weight} pts</td>
</tr>
);
})}
</tbody>
</table>
{contraTaken && contraTaken.size > 0 &&
<React.Fragment>
<div className="pr-sec-head">7 · Contraindicated Actions Taken</div>
<table className="pr-table">
<tbody>
{[...contraTaken].map((id) => {
const c = scenario.contraindications.find((x) => x.actionId === id);
return <tr key={id} className="pr-missed"><td>⚠</td><td>{c ? c.message : id}</td></tr>;
})}
</tbody>
</table>
</React.Fragment>
}
{untreated && outcome === "dead" &&
<React.Fragment>
<div className="pr-sec-head">{contraTaken && contraTaken.size > 0 ? "8" : "7"} · Why This Casualty Died — Untreated Course</div>
<p className="pr-narrative">
No treatment was rendered. {scenario.name} died of {scenario.diagnosis} — the untreated injury followed its
natural physiological course to cardiovascular collapse. The life-saving sequence below, executed inside each
action's time window, represents the textbook management for this casualty.
</p>
<table className="pr-table">
<thead><tr><th>#</th><th>MARCH</th><th>Life-saving measure</th><th>Required by</th><th>Survival weight</th></tr></thead>
<tbody>
{[...scenario.criticalActions].sort((a, b) => a.byMin - b.byMin || b.weight - a.weight).map((a, i) =>
<tr key={a.id}><td>{i + 1}</td><td>{a.category}</td><td>{a.label}</td><td>T+{String(a.byMin).padStart(2, "0")}:00</td><td>{a.weight} pts</td></tr>
)}
</tbody>
</table>
</React.Fragment>
}
<div className="pr-sign">
<div>Provider: ______________________________</div>
<div>Signature: ______________________________</div>
<div>Date / Time: ____________________________</div>
</div>
<div className="pr-foot">
Training simulation report — not a medical record. Generated from the SOCM Trauma Study Guide V2 scenario set,
aligned to TCCC Guidelines (May 2026 update).
</div>
</div>
);
}
window.PrintReport = PrintReport;
})();