Independent education · Sources and limitations documented
Portfolio / Smart NOA simulation

Software simulation

Source snapshot · 5 November 2026

simulator/engine/case-actions.js

// Shared case-control actions (phase buttons, airway preparation, extubation).
// Pure; no DOM. EDUCATIONAL SIMULATION — fictional patients — not a medical device.
//
// The manual Run-screen buttons (ui/monitor.js, ui/app.js extubation dialog) and the
// automatic runner (engine/autorun.js) both call these functions, so both paths drive the
// simulation through exactly the same sim.setPhase()/sim.action() calls, with the same
// interlocks, alarms and event-log entries. Each function returns { ok, message }.

const phase = (sim, ph, message) => { const r = sim.setPhase(ph); return { ok: r.ok, message: r.ok ? message : r.message }; };
const act = (sim, id, okMessage = null) => { const r = sim.action(id); return { ok: r.ok, message: r.ok ? (okMessage || r.message) : r.message }; };

export const CASE_ACTIONS = Object.freeze({
  // ---- pre-op holding → OR (timing review): the patient leaves holding after the premedication interval
  transfer_to_or: (sim) => act(sim, 'transfer_to_or'),
  // ---- clinician-only checklist items (never called by the automatic runner on its own)
  confirm_time_out: (sim) => act(sim, 'confirm_time_out'),
  acknowledge_depth_below_band: (sim) => act(sim, 'acknowledge_depth_below_band'),
  acknowledge_sedation_below_target: (sim) => act(sim, 'acknowledge_sedation_below_target'),
  // ---- GA phase controls
  start_induction: (sim) => phase(sim, 'induction', 'Induction started — plan induction steps run from now.'),
  secure_airway: (sim) => {
    const r = sim.action('secure_airway');
    if (!r.ok) return { ok: false, message: r.message };
    sim.action('start_ventilation');
    return { ok: true, message: `${r.message}. Mechanical ventilation started.` };
  },
  start_maintenance: (sim) => phase(sim, 'maintenance', 'Maintenance phase started.'),
  start_surgery: (sim) => act(sim, 'start_surgery'),
  end_surgery: (sim) => act(sim, 'end_surgery'),
  begin_emergence: (sim) => phase(sim, 'emergence', 'Emergence started — plan emergence steps run from now.'),
  // ---- MAC phase controls
  start_sedation: (sim) => phase(sim, 'sedation', 'Sedation started.'),
  start_procedure: (sim) => act(sim, 'start_surgery', 'Procedure started'),
  end_procedure: (sim) => act(sim, 'end_surgery', 'Procedure ended'),
  end_sedation: (sim) => phase(sim, 'emergence', 'Recovery phase started — plan stop steps run from now.'),
  // ---- airway panel actions
  set_fio2: (sim, v) => act(sim, `set_fio2:${v}`),
  mask_ventilate: (sim) => act(sim, 'mask_ventilate'),
  /** Extubate only when sim.extubationReadiness() is met at the moment of the call (guided gate / full demonstration). */
  extubate: (sim) => {
    const r = sim.extubationReadiness();
    if (!r.ready) return { ok: false, message: `Not ready: ${r.criteria.filter((c) => !c.met).map((c) => c.label).join('; ')}`, readiness: r };
    const res = sim.action('extubate');
    return { ok: res.ok, message: res.message, readiness: r };
  },
  /** The dialog's "Extubate" button (readiness was met when the dialog opened; unchanged manual path). */
  extubateFromDialog: (sim) => { const r = sim.extubationReadiness(); const res = sim.action('extubate'); return { ok: res.ok, message: res.message, readiness: r }; },
  /** The dialog's "Extubate anyway (logged)" path. The automatic runner never calls this. */
  extubateOverride: (sim) => {
    const r = sim.extubationReadiness();
    const unmet = r.criteria.filter((c) => !c.met).map((c) => c.label);
    const res = sim.action('extubate');
    sim.logNote('action', `User confirmed extubation despite unmet readiness criteria: ${unmet.join(', ')}`);
    return { ok: res.ok, message: res.message, readiness: r, unmet };
  },
});

/** Surgery/procedure state derived from the simulation (start → started; end → ended). */
export function surgeryState(sim) {
  const st = sim.stim || {};
  return { started: st.surgeryStartAt !== null && st.surgeryStartAt !== undefined, ended: st.surgeryEndAt !== null && st.surgeryEndAt !== undefined };
}
Source and scope

Published from Smart-NOA-Controller/simulator/engine/case-actions.js at revision 6e5b205e3843. Full source text is retained; HTML presentation does not establish independent clinical review. In-memory simulation with no patient, monitor or pump interface; not clinically validated.