Ecg emergency case make ppt
mkdir -p /home/daytona/workspace/ecg-emergency-ppt && ls /home/daytona/workspace…
~/ecg-emergency-ppt/create_ecg_ppt.js
const pptxgen = require("pptxgenjs");
const pres = new pptxgen();
pres.layout = "LAYOUT_WIDE";
pres.title = "ECG Emergency Cases";
pres.author = "Emergency Medicine";
// ── Color Palette ──────────────────────────────────────────────
const C = {
darkBg: "0D1B2A", // deep navy – dominant dark
midBg: "1B2D45", // medium navy
cardBg: "162236", // card panel background
accent: "E63946", // vivid red – ECG / alert color
accent2:"FF6B35", // orange accent
accentG:"2EC4B6", // teal / green – normal/sinus
white: "FFFFFF",
light: "D8E4F0", // soft blue-white text
muted: "7B9CBF", // muted blue text
yellow: "FFD166", // highlight yellow
purple: "9B5DE5", // arrhythmia purple
};
// ── Shared helpers ─────────────────────────────────────────────
function darkSlide(slide) {
slide.addShape(pres.ShapeType.rect, {
x: 0, y: 0, w: "100%", h: "100%", fill: { color: C.darkBg }
});
}
function addSectionBar(slide, color) {
// left accent bar
slide.addShape(pres.ShapeType.rect, {
x: 0, y: 0, w: 0.12, h: "100%", fill: { color: color || C.accent }
});
}
function headerStrip(slide, color) {
slide.addShape(pres.ShapeType.rect, {
x: 0, y: 0, w: "100%", h: 1.1, fill: { color: color || C.midBg }
});
}
function slideTitle(slide, text, color) {
slide.addText(text, {
x: 0.22, y: 0.18, w: 12.8, h: 0.72,
fontSize: 26, bold: true, color: color || C.white,
fontFace: "Calibri", margin: 0
});
}
function badge(slide, label, x, y, bg, fg) {
slide.addShape(pres.ShapeType.roundRect, {
x, y, w: 2.0, h: 0.38, fill: { color: bg || C.accent },
line: { color: bg || C.accent, width: 0 }, rectRadius: 0.06
});
slide.addText(label, {
x, y, w: 2.0, h: 0.38,
fontSize: 11, bold: true, color: fg || C.white,
align: "center", valign: "middle", margin: 0, fontFace: "Calibri"
});
}
// ECG waveform drawn with lines (stylised)
function drawECGLine(slide, x, y, color, scale) {
const s = scale || 1;
const c = color || C.accentG;
const pts = [
[0,0],[0.18,0],[0.22,-0.04],[0.26,0],[0.3,0],
[0.32,-0.01],[0.34,0.28],[0.37,0],[0.4,-0.1],[0.44,0],[0.5,0],
[0.52,0.06],[0.54,0],[0.56,0],
[0.68,0],[0.72,-0.04],[0.76,0],[0.8,0],
[0.82,-0.01],[0.84,0.28],[0.87,0],[0.9,-0.1],[0.94,0],[1.0,0],
];
for (let i = 0; i < pts.length - 1; i++) {
slide.addShape(pres.ShapeType.line, {
x: x + pts[i][0]*s*3, y: y + pts[i][1]*s*1.2,
w: (pts[i+1][0]-pts[i][0])*s*3,
h: Math.abs((pts[i+1][1]-pts[i][1]))*s*1.2 + 0.001,
line: { color: c, width: 1.5 },
flipV: (pts[i+1][1] - pts[i][1]) < 0 ? true : false
});
}
}
// ══════════════════════════════════════════════════════════════
// SLIDE 1 – TITLE SLIDE
// ══════════════════════════════════════════════════════════════
{
const slide = pres.addSlide();
// Full dark bg
slide.addShape(pres.ShapeType.rect, {
x: 0, y: 0, w: "100%", h: "100%", fill: { color: C.darkBg }
});
// Red diagonal band
slide.addShape(pres.ShapeType.rect, {
x: 0, y: 3.4, w: "100%", h: 0.08, fill: { color: C.accent }
});
// Big ECG flatline with QRS spike decoration
slide.addShape(pres.ShapeType.rect, {
x: 0, y: 3.32, w: "100%", h: 0.08, fill: { color: C.accent }
});
// Title
slide.addText("ECG EMERGENCY CASES", {
x: 0.8, y: 0.7, w: 11.7, h: 1.2,
fontSize: 48, bold: true, color: C.white,
fontFace: "Calibri", charSpacing: 4, align: "center"
});
slide.addText("A Clinical Guide for Medical Students", {
x: 0.8, y: 1.95, w: 11.7, h: 0.55,
fontSize: 20, color: C.light, fontFace: "Calibri",
align: "center", italic: true
});
// 6 topic badges in a row
const topics = ["STEMI", "Heart Blocks", "VF/VT", "SVT/AF", "Bradyarrhythmias", "Life-Threatening"];
topics.forEach((t, i) => {
const cols = [C.accent, C.purple, C.accent, C.accentG, C.accent2, C.yellow];
const fgs = [C.white, C.white, C.white, C.white, C.white, C.darkBg];
slide.addShape(pres.ShapeType.roundRect, {
x: 0.6 + i*2.08, y: 2.8, w: 1.9, h: 0.42,
fill: { color: cols[i] }, line: { color: cols[i] }, rectRadius: 0.06
});
slide.addText(t, {
x: 0.6 + i*2.08, y: 2.8, w: 1.9, h: 0.42,
fontSize: 11, bold: true, color: fgs[i],
align: "center", valign: "middle", margin: 0, fontFace: "Calibri"
});
});
slide.addText("Emergency Medicine | 2026", {
x: 0.8, y: 6.8, w: 11.7, h: 0.4,
fontSize: 13, color: C.muted, align: "center", fontFace: "Calibri"
});
}
// ══════════════════════════════════════════════════════════════
// SLIDE 2 – HOW TO READ AN ECG (Quick Review)
// ══════════════════════════════════════════════════════════════
{
const slide = pres.addSlide();
darkSlide(slide);
headerStrip(slide, C.midBg);
addSectionBar(slide, C.accentG);
slideTitle(slide, "How to Read an ECG – The Systematic Approach");
// 6 boxes in 2 rows × 3 cols
const steps = [
{ n:"1", title:"Rate", val:"Normal: 60-100 bpm\nBradycardia: <60\nTachycardia: >100" },
{ n:"2", title:"Rhythm", val:"Regular vs Irregular\nP waves present?\nP:QRS ratio" },
{ n:"3", title:"Axis", val:"Normal: −30° to +90°\nLAD / RAD / Extreme" },
{ n:"4", title:"P Wave", val:"Present, upright in II\nDuration <0.12s\nLooks before every QRS?" },
{ n:"5", title:"PR Interval", val:"Normal: 0.12–0.20s\nShort = WPW / junctional\nLong = Heart Block" },
{ n:"6", title:"QRS / ST / T", val:"Width <0.12s\nST elevation/depression\nT-wave inversion" },
];
steps.forEach((s, i) => {
const col = i % 3;
const row = Math.floor(i / 3);
const bx = 0.22 + col * 4.35;
const by = 1.25 + row * 2.55;
const colors = [C.accentG, C.accent2, C.yellow, C.accent, C.purple, C.accentG];
slide.addShape(pres.ShapeType.roundRect, {
x: bx, y: by, w: 4.1, h: 2.35,
fill: { color: C.cardBg }, line: { color: colors[i], width: 1.5 }, rectRadius: 0.1
});
// Number circle
slide.addShape(pres.ShapeType.ellipse, {
x: bx + 0.1, y: by + 0.1, w: 0.52, h: 0.52,
fill: { color: colors[i] }, line: { color: colors[i] }
});
slide.addText(s.n, {
x: bx + 0.1, y: by + 0.1, w: 0.52, h: 0.52,
fontSize: 16, bold: true, color: C.white,
align: "center", valign: "middle", margin: 0, fontFace: "Calibri"
});
slide.addText(s.title, {
x: bx + 0.72, y: by + 0.12, w: 3.3, h: 0.45,
fontSize: 15, bold: true, color: colors[i], fontFace: "Calibri", margin: 0
});
slide.addText(s.val, {
x: bx + 0.15, y: by + 0.65, w: 3.8, h: 1.55,
fontSize: 12, color: C.light, fontFace: "Calibri", margin: 4
});
});
}
// ══════════════════════════════════════════════════════════════
// SLIDE 3 – STEMI
// ══════════════════════════════════════════════════════════════
{
const slide = pres.addSlide();
darkSlide(slide);
headerStrip(slide, C.midBg);
addSectionBar(slide, C.accent);
slideTitle(slide, "STEMI – ST-Elevation Myocardial Infarction");
badge(slide, "⚠ LIFE-THREATENING", 10.3, 0.18, C.accent, C.white);
// Left panel – ECG features
slide.addShape(pres.ShapeType.roundRect, {
x: 0.22, y: 1.2, w: 5.9, h: 5.5,
fill: { color: C.cardBg }, line: { color: C.accent, width: 1 }, rectRadius: 0.1
});
slide.addText("ECG Features", {
x: 0.4, y: 1.3, w: 5.5, h: 0.45,
fontSize: 15, bold: true, color: C.accent, fontFace: "Calibri", margin: 0
});
const feats = [
"ST elevation ≥1 mm in ≥2 contiguous leads",
"New LBBB (Sgarbossa criteria)",
"Reciprocal ST depression in opposite leads",
"Hyperacute T waves (earliest sign)",
"Q waves (late – irreversible necrosis)",
"De Winter T waves (LAD occlusion equivalent)",
"Wellens syndrome – critical LAD stenosis",
];
feats.forEach((f, i) => {
slide.addShape(pres.ShapeType.rect, {
x: 0.38, y: 1.88 + i*0.58, w: 0.06, h: 0.28, fill: { color: C.accent }
});
slide.addText(f, {
x: 0.55, y: 1.85 + i*0.58, w: 5.35, h: 0.35,
fontSize: 12.5, color: C.light, fontFace: "Calibri", margin: 0
});
});
// Right panel – territories
slide.addShape(pres.ShapeType.roundRect, {
x: 6.42, y: 1.2, w: 6.88, h: 5.5,
fill: { color: C.cardBg }, line: { color: C.accent2, width: 1 }, rectRadius: 0.1
});
slide.addText("Territory Localisation", {
x: 6.6, y: 1.3, w: 6.5, h: 0.45,
fontSize: 15, bold: true, color: C.accent2, fontFace: "Calibri", margin: 0
});
const terr = [
{ loc:"Anterior", leads:"V1–V4", art:"LAD", c: C.accent },
{ loc:"Lateral", leads:"I, aVL, V5–V6", art:"LCx", c: C.accent2 },
{ loc:"Inferior", leads:"II, III, aVF", art:"RCA", c: C.yellow },
{ loc:"Septal", leads:"V1–V2", art:"LAD", c: C.accentG },
{ loc:"Posterior (STEMI)",leads:"V1–V2 depression",art:"RCA/LCx",c: C.purple},
{ loc:"Right Ventricular",leads:"V3R–V4R", art:"RCA", c: C.accent },
];
terr.forEach((t, i) => {
const by = 1.88 + i*0.72;
slide.addShape(pres.ShapeType.roundRect, {
x: 6.58, y: by, w: 6.55, h: 0.62,
fill: { color: C.midBg }, line: { color: t.c, width: 1 }, rectRadius: 0.06
});
slide.addText(t.loc, {
x: 6.68, y: by+0.06, w: 2.5, h: 0.5,
fontSize: 12, bold: true, color: t.c, fontFace: "Calibri", margin: 0
});
slide.addText(`Leads: ${t.leads}`, {
x: 9.0, y: by+0.06, w: 2.3, h: 0.25,
fontSize: 10.5, color: C.light, fontFace: "Calibri", margin: 0
});
slide.addText(`Artery: ${t.art}`, {
x: 9.0, y: by+0.3, w: 2.3, h: 0.25,
fontSize: 10.5, color: C.muted, fontFace: "Calibri", margin: 0
});
});
// Management footer
slide.addShape(pres.ShapeType.roundRect, {
x: 0.22, y: 6.82, w: 13.08, h: 0.52,
fill: { color: C.accent }, line: { color: C.accent }, rectRadius: 0.06
});
slide.addText("Management: Activate Cath Lab (PCI within 90 min) | Aspirin 300 mg + Ticagrelor 180 mg | Heparin | O₂ if SpO₂ <94%", {
x: 0.22, y: 6.82, w: 13.08, h: 0.52,
fontSize: 12, bold: true, color: C.white,
align: "center", valign: "middle", margin: 0, fontFace: "Calibri"
});
}
// ══════════════════════════════════════════════════════════════
// SLIDE 4 – NSTEMI / UA
// ══════════════════════════════════════════════════════════════
{
const slide = pres.addSlide();
darkSlide(slide);
headerStrip(slide, C.midBg);
addSectionBar(slide, C.accent2);
slideTitle(slide, "NSTEMI & Unstable Angina – Non-ST Elevation ACS");
badge(slide, "⚠ URGENT", 11.4, 0.18, C.accent2, C.white);
const panels = [
{
title: "ECG Findings (NSTEMI/UA)",
color: C.accent2,
items: [
"ST depression ≥0.5 mm in ≥2 contiguous leads",
"Transient ST elevation (Prinzmetal's angina)",
"Deep T-wave inversions (diffuse)",
"Normal ECG (does NOT exclude NSTEMI)",
"Tall R waves in V1–V2 (posterior MI)",
"New ST changes compared to old ECG",
]
},
{
title: "Distinguish from STEMI",
color: C.yellow,
items: [
"No persistent ST elevation",
"No new LBBB",
"Troponin rise confirms myocyte damage",
"Unstable Angina = troponin NEGATIVE",
"NSTEMI = troponin POSITIVE",
"Both need urgent risk stratification (GRACE/TIMI)",
]
},
{
title: "Management",
color: C.accentG,
items: [
"Aspirin 300 mg + P2Y12 inhibitor (ticagrelor)",
"Anticoagulation (LMWH / fondaparinux)",
"High-dose statin (atorvastatin 80 mg)",
"Beta-blocker if no contraindication",
"GTN for ongoing chest pain",
"Invasive strategy within 24–72 hrs (angiography)",
]
}
];
panels.forEach((p, i) => {
const bx = 0.22 + i * 4.42;
slide.addShape(pres.ShapeType.roundRect, {
x: bx, y: 1.2, w: 4.2, h: 5.8,
fill: { color: C.cardBg }, line: { color: p.color, width: 1.5 }, rectRadius: 0.1
});
slide.addShape(pres.ShapeType.rect, {
x: bx, y: 1.2, w: 4.2, h: 0.55,
fill: { color: p.color }, line: { color: p.color }
});
slide.addText(p.title, {
x: bx + 0.12, y: 1.22, w: 3.96, h: 0.5,
fontSize: 13, bold: true, color: C.white,
fontFace: "Calibri", margin: 0, valign: "middle"
});
p.items.forEach((item, j) => {
slide.addShape(pres.ShapeType.ellipse, {
x: bx + 0.18, y: 1.9 + j*0.77, w: 0.15, h: 0.15,
fill: { color: p.color }, line: { color: p.color }
});
slide.addText(item, {
x: bx + 0.42, y: 1.85 + j*0.77, w: 3.68, h: 0.65,
fontSize: 12, color: C.light, fontFace: "Calibri", margin: 0
});
});
});
}
// ══════════════════════════════════════════════════════════════
// SLIDE 5 – VENTRICULAR FIBRILLATION & PULSELESS VT
// ══════════════════════════════════════════════════════════════
{
const slide = pres.addSlide();
darkSlide(slide);
headerStrip(slide, C.midBg);
addSectionBar(slide, C.accent);
slideTitle(slide, "Ventricular Fibrillation (VF) & Pulseless VT");
// DANGER banner
slide.addShape(pres.ShapeType.roundRect, {
x: 0.22, y: 1.1, w: 13.08, h: 0.62,
fill: { color: C.accent }, line: { color: C.accent }, rectRadius: 0.06
});
slide.addText("⚡ SHOCKABLE RHYTHM – Immediate Defibrillation Required – Begin CPR NOW", {
x: 0.22, y: 1.1, w: 13.08, h: 0.62,
fontSize: 16, bold: true, color: C.white,
align: "center", valign: "middle", margin: 0, fontFace: "Calibri"
});
// Two columns
const leftItems = [
{ heading: "Ventricular Fibrillation (VF)", color: C.accent, desc: [
"Chaotic, irregular waveforms – no discernible QRS",
"No organised cardiac activity → no output",
"Causes: IHD, electrolyte abnormalities, drugs, hypothermia",
"Fine VF (low amplitude) vs Coarse VF (high amplitude)",
]},
{ heading: "Pulseless VT", color: C.accent2, desc: [
"Wide QRS (>0.12s), monomorphic or polymorphic",
"Rate >100 bpm (usually 150–250 bpm)",
"No pulse despite organised rhythm on ECG",
"Torsades de Pointes: polymorphic VT, long QT syndrome",
]},
];
leftItems.forEach((item, i) => {
const by = 1.9 + i * 2.6;
slide.addShape(pres.ShapeType.roundRect, {
x: 0.22, y: by, w: 6.7, h: 2.35,
fill: { color: C.cardBg }, line: { color: item.color, width: 1.5 }, rectRadius: 0.1
});
slide.addText(item.heading, {
x: 0.4, y: by + 0.1, w: 6.3, h: 0.45,
fontSize: 14, bold: true, color: item.color, fontFace: "Calibri", margin: 0
});
item.desc.forEach((d, j) => {
slide.addText("▸ " + d, {
x: 0.4, y: by + 0.6 + j * 0.41, w: 6.3, h: 0.4,
fontSize: 12, color: C.light, fontFace: "Calibri", margin: 0
});
});
});
// Right: ALS algorithm steps
slide.addShape(pres.ShapeType.roundRect, {
x: 7.15, y: 1.9, w: 6.15, h: 5.5,
fill: { color: C.cardBg }, line: { color: C.yellow, width: 1.5 }, rectRadius: 0.1
});
slide.addText("ALS Algorithm (Shockable)", {
x: 7.32, y: 2.0, w: 5.8, h: 0.45,
fontSize: 14, bold: true, color: C.yellow, fontFace: "Calibri", margin: 0
});
const alg = [
{ s:"1", t:"Call for help / Confirm cardiac arrest", c: C.accent },
{ s:"2", t:"CPR 30:2 immediately – do not delay", c: C.accent },
{ s:"3", t:"Attach defibrillator, confirm VF/VT", c: C.accent2 },
{ s:"4", t:"Shock 200 J (biphasic) → resume CPR 2 min", c: C.yellow },
{ s:"5", t:"Adrenaline 1 mg IV after 3rd shock, then every 3–5 min", c: C.accentG },
{ s:"6", t:"Amiodarone 300 mg IV after 3rd shock", c: C.purple },
{ s:"7", t:"Identify reversible causes (4 Hs & 4 Ts)", c: C.accentG },
];
alg.forEach((a, i) => {
slide.addShape(pres.ShapeType.ellipse, {
x: 7.3, y: 2.58 + i*0.46, w: 0.36, h: 0.36,
fill: { color: a.c }, line: { color: a.c }
});
slide.addText(a.s, {
x: 7.3, y: 2.58 + i*0.46, w: 0.36, h: 0.36,
fontSize: 11, bold: true, color: C.white,
align: "center", valign: "middle", margin: 0
});
slide.addText(a.t, {
x: 7.75, y: 2.58 + i*0.46, w: 5.45, h: 0.38,
fontSize: 11.5, color: C.light, fontFace: "Calibri", margin: 0
});
});
}
// ══════════════════════════════════════════════════════════════
// SLIDE 6 – SUPRAVENTRICULAR TACHYCARDIA (SVT)
// ══════════════════════════════════════════════════════════════
{
const slide = pres.addSlide();
darkSlide(slide);
headerStrip(slide, C.midBg);
addSectionBar(slide, C.purple);
slideTitle(slide, "Supraventricular Tachycardia (SVT)");
// Three column cards
const cards = [
{
title: "ECG Features of SVT",
color: C.purple,
content: [
"Heart rate: 150–250 bpm",
"Regular, narrow QRS (<0.12s)",
"P waves absent or retrograde (negative in II)",
"No delta wave (unless AVRT in WPW)",
"Sudden onset and termination",
"May cause ST depression (rate-related ischaemia)",
]
},
{
title: "SVT Subtypes",
color: C.accent2,
content: [
"AVNRT (commonest) – P buried in or after QRS",
"AVRT (WPW) – delta wave in sinus rhythm",
"Atrial Tachycardia – P wave visible, different morphology",
"PSVT – paroxysmal, sudden onset/offset",
"Atrial Flutter – sawtooth P waves, rate ~300/min",
"Junctional Tachycardia – short PR / retrograde P",
]
},
{
title: "Management",
color: C.accentG,
content: [
"Vagal manoeuvres FIRST (Valsalva, carotid sinus massage)",
"Adenosine 6 mg IV rapid push (12 mg if no response)",
"Warn: transient chest tightness, flushing, asystole",
"If haemodynamically unstable → DC cardioversion",
"If WPW + AF: avoid AV nodal blockers (use procainamide)",
"Long-term: beta-blockers, CCBs, or ablation",
]
}
];
cards.forEach((c, i) => {
const bx = 0.22 + i * 4.42;
slide.addShape(pres.ShapeType.roundRect, {
x: bx, y: 1.2, w: 4.2, h: 5.8,
fill: { color: C.cardBg }, line: { color: c.color, width: 1.5 }, rectRadius: 0.1
});
slide.addShape(pres.ShapeType.rect, {
x: bx, y: 1.2, w: 4.2, h: 0.55,
fill: { color: c.color }, line: { color: c.color }
});
slide.addText(c.title, {
x: bx + 0.12, y: 1.22, w: 3.96, h: 0.5,
fontSize: 13, bold: true, color: C.white,
fontFace: "Calibri", margin: 0, valign: "middle"
});
c.content.forEach((item, j) => {
slide.addShape(pres.ShapeType.ellipse, {
x: bx + 0.18, y: 1.9 + j*0.77, w: 0.15, h: 0.15,
fill: { color: c.color }, line: { color: c.color }
});
slide.addText(item, {
x: bx + 0.42, y: 1.85 + j*0.77, w: 3.68, h: 0.68,
fontSize: 11.5, color: C.light, fontFace: "Calibri", margin: 0
});
});
});
}
// ══════════════════════════════════════════════════════════════
// SLIDE 7 – ATRIAL FIBRILLATION & FLUTTER
// ══════════════════════════════════════════════════════════════
{
const slide = pres.addSlide();
darkSlide(slide);
headerStrip(slide, C.midBg);
addSectionBar(slide, C.accent2);
slideTitle(slide, "Atrial Fibrillation & Atrial Flutter");
// AF card
slide.addShape(pres.ShapeType.roundRect, {
x: 0.22, y: 1.2, w: 6.3, h: 5.7,
fill: { color: C.cardBg }, line: { color: C.accent2, width: 1.5 }, rectRadius: 0.1
});
slide.addShape(pres.ShapeType.rect, {
x: 0.22, y: 1.2, w: 6.3, h: 0.55,
fill: { color: C.accent2 }, line: { color: C.accent2 }
});
slide.addText("Atrial Fibrillation (AF)", {
x: 0.34, y: 1.22, w: 6.06, h: 0.5,
fontSize: 15, bold: true, color: C.white, fontFace: "Calibri", margin: 0, valign: "middle"
});
const afItems = [
{ h: "ECG Features", items: ["Absent P waves (fibrillatory baseline)", "Irregularly irregular QRS", "Rate 100–180 bpm (uncontrolled)", "Narrow QRS (unless aberrant conduction)"] },
{ h: "Management", items: ["Rate control: metoprolol, diltiazem, digoxin", "Rhythm control: flecainide, amiodarone, DC cardioversion", "Anticoagulation: CHA₂DS₂-VASc score", "New AF <48 hrs: cardiovert safely; >48 hrs: anticoagulate 3 weeks first"] }
];
afItems.forEach((group, gi) => {
slide.addText(group.h, {
x: 0.38, y: 1.9 + gi*2.4, w: 5.9, h: 0.38,
fontSize: 13, bold: true, color: C.accent2, fontFace: "Calibri", margin: 0
});
group.items.forEach((item, j) => {
slide.addText("▸ " + item, {
x: 0.42, y: 2.3 + gi*2.4 + j*0.46, w: 5.9, h: 0.42,
fontSize: 11.5, color: C.light, fontFace: "Calibri", margin: 0
});
});
});
// Flutter card
slide.addShape(pres.ShapeType.roundRect, {
x: 6.82, y: 1.2, w: 6.48, h: 5.7,
fill: { color: C.cardBg }, line: { color: C.purple, width: 1.5 }, rectRadius: 0.1
});
slide.addShape(pres.ShapeType.rect, {
x: 6.82, y: 1.2, w: 6.48, h: 0.55,
fill: { color: C.purple }, line: { color: C.purple }
});
slide.addText("Atrial Flutter", {
x: 6.95, y: 1.22, w: 6.22, h: 0.5,
fontSize: 15, bold: true, color: C.white, fontFace: "Calibri", margin: 0, valign: "middle"
});
const flItems = [
{ h: "ECG Features", items: [
"Sawtooth flutter waves (F waves) at ~300/min",
"Most common: 2:1 block → ventricular rate ~150",
"Regular or regularly irregular QRS",
"No isoelectric baseline between flutter waves",
"Flutter most visible in inferior leads (II, III, aVF)"
]},
{ h: "Management", items: [
"Rate control: beta-blockers or CCBs",
"Anticoagulation same as AF",
"DC cardioversion effective (lower energy needed)",
"Atrial flutter ablation: high cure rate (>95%)"
]}
];
let fy = 1.9;
flItems.forEach((group) => {
slide.addText(group.h, {
x: 7.0, y: fy, w: 6.1, h: 0.38,
fontSize: 13, bold: true, color: C.purple, fontFace: "Calibri", margin: 0
});
fy += 0.42;
group.items.forEach((item) => {
slide.addText("▸ " + item, {
x: 7.04, y: fy, w: 6.1, h: 0.42,
fontSize: 11.5, color: C.light, fontFace: "Calibri", margin: 0
});
fy += 0.46;
});
fy += 0.2;
});
}
// ══════════════════════════════════════════════════════════════
// SLIDE 8 – HEART BLOCKS
// ══════════════════════════════════════════════════════════════
{
const slide = pres.addSlide();
darkSlide(slide);
headerStrip(slide, C.midBg);
addSectionBar(slide, C.yellow);
slideTitle(slide, "Atrioventricular (AV) Heart Blocks");
const blocks = [
{
degree: "1st Degree", color: C.accentG,
ecg: "PR interval >200 ms (>5 small squares)\nAll P waves conduct\nRegular rhythm",
tx: "Usually benign\nNo treatment required\nMonitor (may progress)",
badge: "BENIGN"
},
{
degree: "2nd Degree – Mobitz I (Wenckebach)", color: C.yellow,
ecg: "Progressive PR lengthening\nUntil a P wave is dropped (non-conducted)\nCycles repeat\nGrouped beating",
tx: "Usually benign\nAtropine if symptomatic\nTemporary pacing rarely needed\nMonitor",
badge: "MOSTLY BENIGN"
},
{
degree: "2nd Degree – Mobitz II", color: C.accent2,
ecg: "Fixed PR interval\nSudden non-conducted P waves\n2:1, 3:1 block pattern\nWide QRS (often LBBB/RBBB)",
tx: "High risk of progression to 3rd degree\nPermanent pacemaker indicated\nAtropine / transcutaneous pacing acutely",
badge: "⚠ URGENT"
},
{
degree: "3rd Degree (Complete Heart Block)", color: C.accent,
ecg: "Complete AV dissociation\nP waves & QRS independent\nEscape rhythm (junctional 40–60 or ventricular 20–40)\nBroad QRS if ventricular escape",
tx: "Emergency pacing (transcutaneous then transvenous)\nAtropine 0.5–1 mg IV\nDopamine infusion if unstable\nPermanent pacemaker",
badge: "⚠ EMERGENCY"
},
];
blocks.forEach((b, i) => {
const col = i % 2;
const row = Math.floor(i / 2);
const bx = 0.22 + col * 6.72;
const by = 1.2 + row * 3.1;
slide.addShape(pres.ShapeType.roundRect, {
x: bx, y: by, w: 6.4, h: 2.9,
fill: { color: C.cardBg }, line: { color: b.color, width: 1.5 }, rectRadius: 0.1
});
// Degree title
slide.addText(b.degree, {
x: bx + 0.18, y: by + 0.1, w: 4.8, h: 0.45,
fontSize: 13.5, bold: true, color: b.color, fontFace: "Calibri", margin: 0
});
// Badge
slide.addShape(pres.ShapeType.roundRect, {
x: bx + 4.7, y: by + 0.12, w: 1.5, h: 0.34,
fill: { color: b.color }, line: { color: b.color }, rectRadius: 0.05
});
slide.addText(b.badge, {
x: bx + 4.7, y: by + 0.12, w: 1.5, h: 0.34,
fontSize: 9, bold: true, color: C.white,
align: "center", valign: "middle", margin: 0
});
slide.addText("ECG: " + b.ecg, {
x: bx + 0.15, y: by + 0.6, w: 3.0, h: 2.12,
fontSize: 10.5, color: C.light, fontFace: "Calibri", margin: 4
});
slide.addText("Mx: " + b.tx, {
x: bx + 3.25, y: by + 0.6, w: 2.98, h: 2.12,
fontSize: 10.5, color: C.accentG, fontFace: "Calibri", margin: 4
});
});
}
// ══════════════════════════════════════════════════════════════
// SLIDE 9 – BRADYARRHYTHMIAS & BROAD COMPLEX TACHYCARDIA
// ══════════════════════════════════════════════════════════════
{
const slide = pres.addSlide();
darkSlide(slide);
headerStrip(slide, C.midBg);
addSectionBar(slide, C.accentG);
slideTitle(slide, "Bradyarrhythmias & Broad Complex Tachycardias");
// Left: Bradyarrhythmias
slide.addShape(pres.ShapeType.roundRect, {
x: 0.22, y: 1.2, w: 6.3, h: 5.9,
fill: { color: C.cardBg }, line: { color: C.accentG, width: 1.5 }, rectRadius: 0.1
});
slide.addShape(pres.ShapeType.rect, {
x: 0.22, y: 1.2, w: 6.3, h: 0.55,
fill: { color: C.accentG }, line: { color: C.accentG }
});
slide.addText("Bradyarrhythmias (HR <60)", {
x: 0.35, y: 1.22, w: 6.04, h: 0.5,
fontSize: 14, bold: true, color: C.darkBg, fontFace: "Calibri", margin: 0, valign: "middle"
});
const bradyData = [
{ t: "Sinus Bradycardia", c: C.accentG, d: "Rate <60, regular P waves, normal PR. Causes: athletes, vagal, hypothyroidism, beta-blockers. Treat if symptomatic: atropine 0.5 mg IV." },
{ t: "Sick Sinus Syndrome", c: C.yellow, d: "Alternating brady-tachycardia (brady-tachy syndrome). Often requires PPM + anticoagulation." },
{ t: "Junctional Rhythm", c: C.accent2, d: "Rate 40–60. Retrograde P waves, narrow QRS. No atrial activity. Pacing if symptomatic." },
{ t: "Idioventricular Rhythm", c: C.accent, d: "Rate 20–40. Wide QRS, no P waves. Ventricular escape. Emergency pacing required." },
];
bradyData.forEach((d, i) => {
slide.addShape(pres.ShapeType.roundRect, {
x: 0.35, y: 1.9 + i*1.2, w: 6.0, h: 1.1,
fill: { color: C.midBg }, line: { color: d.c, width: 1 }, rectRadius: 0.06
});
slide.addText(d.t, {
x: 0.5, y: 1.95 + i*1.2, w: 5.7, h: 0.32,
fontSize: 12, bold: true, color: d.c, fontFace: "Calibri", margin: 0
});
slide.addText(d.d, {
x: 0.5, y: 2.28 + i*1.2, w: 5.7, h: 0.6,
fontSize: 10.5, color: C.light, fontFace: "Calibri", margin: 0
});
});
// Atropine algorithm box
slide.addShape(pres.ShapeType.roundRect, {
x: 0.35, y: 6.7, w: 6.0, h: 0.35,
fill: { color: C.accentG }, line: { color: C.accentG }, rectRadius: 0.05
});
slide.addText("Symptomatic bradycardia: Atropine 0.5 mg IV → Transcutaneous Pacing", {
x: 0.35, y: 6.7, w: 6.0, h: 0.35,
fontSize: 10, bold: true, color: C.darkBg,
align: "center", valign: "middle", margin: 0
});
// Right: Broad complex tachycardia
slide.addShape(pres.ShapeType.roundRect, {
x: 6.82, y: 1.2, w: 6.48, h: 5.9,
fill: { color: C.cardBg }, line: { color: C.purple, width: 1.5 }, rectRadius: 0.1
});
slide.addShape(pres.ShapeType.rect, {
x: 6.82, y: 1.2, w: 6.48, h: 0.55,
fill: { color: C.purple }, line: { color: C.purple }
});
slide.addText("Broad Complex Tachycardia (QRS >0.12s, rate >100)", {
x: 6.95, y: 1.22, w: 6.22, h: 0.5,
fontSize: 13, bold: true, color: C.white, fontFace: "Calibri", margin: 0, valign: "middle"
});
const broadItems = [
{ t:"Always assume VT until proven otherwise", c: C.accent },
{ t:"Monomorphic VT: regular, uniform wide-complex QRS", c: C.light },
{ t:"Polymorphic VT: varying QRS morphology", c: C.light },
{ t:"Torsades de Pointes: twisting around baseline, long QT", c: C.yellow },
{ t:"SVT with aberrancy: looks wide but actually SVT", c: C.accent2 },
];
broadItems.forEach((bi, i) => {
slide.addText("▸ " + bi.t, {
x: 7.0, y: 1.95 + i*0.52, w: 6.1, h: 0.48,
fontSize: 12, color: bi.c, fontFace: "Calibri", margin: 0,
bold: i === 0 ? true : false
});
});
// Brugada criteria box
slide.addShape(pres.ShapeType.roundRect, {
x: 6.97, y: 4.7, w: 6.15, h: 2.2,
fill: { color: C.midBg }, line: { color: C.yellow, width: 1 }, rectRadius: 0.08
});
slide.addText("Differentiating VT from SVT with Aberrancy", {
x: 7.1, y: 4.78, w: 5.9, h: 0.38,
fontSize: 12.5, bold: true, color: C.yellow, fontFace: "Calibri", margin: 0
});
const brugItems = [
"AV dissociation → confirms VT",
"Capture / fusion beats → confirms VT",
"QRS >0.16s favours VT",
"Extreme axis deviation (NW axis) → VT",
"Brugada / Vereckei criteria for confirmation",
];
brugItems.forEach((bi, i) => {
slide.addText("• " + bi, {
x: 7.1, y: 5.2 + i*0.32, w: 5.9, h: 0.3,
fontSize: 11, color: C.light, fontFace: "Calibri", margin: 0
});
});
}
// ══════════════════════════════════════════════════════════════
// SLIDE 10 – WOLFF-PARKINSON-WHITE & LONG QT
// ══════════════════════════════════════════════════════════════
{
const slide = pres.addSlide();
darkSlide(slide);
headerStrip(slide, C.midBg);
addSectionBar(slide, C.purple);
slideTitle(slide, "WPW Syndrome & Long QT Syndrome");
// WPW
slide.addShape(pres.ShapeType.roundRect, {
x: 0.22, y: 1.2, w: 6.3, h: 5.9,
fill: { color: C.cardBg }, line: { color: C.purple, width: 1.5 }, rectRadius: 0.1
});
slide.addShape(pres.ShapeType.rect, {
x: 0.22, y: 1.2, w: 6.3, h: 0.55,
fill: { color: C.purple }, line: { color: C.purple }
});
slide.addText("Wolff-Parkinson-White (WPW)", {
x: 0.35, y: 1.22, w: 6.04, h: 0.5,
fontSize: 15, bold: true, color: C.white, fontFace: "Calibri", margin: 0, valign: "middle"
});
const wpwContent = [
{ h: "ECG Findings", c: C.purple, items: [
"Short PR interval (<0.12s)",
"Delta wave (slurred QRS upstroke)",
"Wide QRS complex",
"Secondary ST-T wave changes",
"Pseudo-infarction patterns possible",
]},
{ h: "Key Danger: AF in WPW", c: C.accent, items: [
"Rapid conduction via accessory pathway",
"Can cause ventricular rates >250 bpm",
"Risk of VF and sudden cardiac death",
"NEVER give adenosine, digoxin, or verapamil",
"Treatment: DC cardioversion or procainamide",
]},
];
let wy = 1.9;
wpwContent.forEach((grp) => {
slide.addText(grp.h, {
x: 0.4, y: wy, w: 5.9, h: 0.38,
fontSize: 13, bold: true, color: grp.c, fontFace: "Calibri", margin: 0
});
wy += 0.42;
grp.items.forEach((item) => {
slide.addText("▸ " + item, {
x: 0.42, y: wy, w: 5.9, h: 0.42,
fontSize: 12, color: C.light, fontFace: "Calibri", margin: 0
});
wy += 0.46;
});
wy += 0.22;
});
// Long QT
slide.addShape(pres.ShapeType.roundRect, {
x: 6.82, y: 1.2, w: 6.48, h: 5.9,
fill: { color: C.cardBg }, line: { color: C.yellow, width: 1.5 }, rectRadius: 0.1
});
slide.addShape(pres.ShapeType.rect, {
x: 6.82, y: 1.2, w: 6.48, h: 0.55,
fill: { color: C.yellow }, line: { color: C.yellow }
});
slide.addText("Long QT Syndrome", {
x: 6.95, y: 1.22, w: 6.22, h: 0.5,
fontSize: 15, bold: true, color: C.darkBg, fontFace: "Calibri", margin: 0, valign: "middle"
});
const lqtContent = [
{ h: "ECG Findings", c: C.yellow, items: [
"QTc >440 ms (men) / >460 ms (women)",
"Prolonged T-wave duration",
"May show T-wave alternans",
"Predisposes to Torsades de Pointes",
]},
{ h: "Causes (LQTS)", c: C.accent2, items: [
"Congenital: LQT1–3 (gene mutations)",
"Drugs: antiarrhythmics, antibiotics (clarithromycin), antipsychotics",
"Electrolytes: hypokalaemia, hypomagnesaemia, hypocalcaemia",
"Hypothyroidism, hypothermia, intracranial events",
]},
{ h: "Management", c: C.accentG, items: [
"Stop offending drugs",
"Correct electrolytes (IV MgSO₄ for Torsades)",
"IV MgSO₄ 2g is first-line for Torsades de Pointes",
"Overdrive pacing / isoproterenol to shorten QT",
"ICD for congenital LQTS",
]},
];
let ly = 1.9;
lqtContent.forEach((grp) => {
slide.addText(grp.h, {
x: 7.0, y: ly, w: 6.1, h: 0.38,
fontSize: 13, bold: true, color: grp.c, fontFace: "Calibri", margin: 0
});
ly += 0.42;
grp.items.forEach((item) => {
slide.addText("▸ " + item, {
x: 7.04, y: ly, w: 6.1, h: 0.42,
fontSize: 11.5, color: C.light, fontFace: "Calibri", margin: 0
});
ly += 0.46;
});
ly += 0.16;
});
}
// ══════════════════════════════════════════════════════════════
// SLIDE 11 – PERICARDITIS & HYPERKALEMIA
// ══════════════════════════════════════════════════════════════
{
const slide = pres.addSlide();
darkSlide(slide);
headerStrip(slide, C.midBg);
addSectionBar(slide, C.accent2);
slideTitle(slide, "Pericarditis & Hyperkalaemia – ECG Patterns");
// Pericarditis
slide.addShape(pres.ShapeType.roundRect, {
x: 0.22, y: 1.2, w: 6.3, h: 5.9,
fill: { color: C.cardBg }, line: { color: C.accent2, width: 1.5 }, rectRadius: 0.1
});
slide.addShape(pres.ShapeType.rect, {
x: 0.22, y: 1.2, w: 6.3, h: 0.55,
fill: { color: C.accent2 }, line: { color: C.accent2 }
});
slide.addText("Pericarditis", {
x: 0.35, y: 1.22, w: 6.04, h: 0.5,
fontSize: 15, bold: true, color: C.white, fontFace: "Calibri", margin: 0, valign: "middle"
});
const pericItems = [
{ h: "ECG Stages", c: C.accent2, items: [
"Stage 1: Saddle-shaped (concave up) ST elevation in most leads; PR depression",
"Stage 2: ST returns to baseline, T waves flatten",
"Stage 3: T-wave inversion (diffuse)",
"Stage 4: ECG normalises (weeks to months)",
]},
{ h: "Key Features (vs STEMI)", c: C.yellow, items: [
"ST elevation is diffuse (not territorial)",
"PR segment depression (highly specific)",
"No reciprocal ST depression",
"No Q waves",
"Spitzweg sign: PR depression in V5/V6",
]},
{ h: "Management", c: C.accentG, items: [
"NSAIDs (ibuprofen 600 mg TDS) + colchicine 0.5 mg BD",
"Avoid strenuous activity for 3 months",
"Steroids only if NSAIDs fail (increased recurrence risk)",
]},
];
let py = 1.9;
pericItems.forEach((grp) => {
slide.addText(grp.h, {
x: 0.4, y: py, w: 5.9, h: 0.38,
fontSize: 12.5, bold: true, color: grp.c, fontFace: "Calibri", margin: 0
});
py += 0.42;
grp.items.forEach((item) => {
slide.addText("▸ " + item, {
x: 0.42, y: py, w: 5.9, h: 0.42,
fontSize: 11.5, color: C.light, fontFace: "Calibri", margin: 0
});
py += 0.46;
});
py += 0.16;
});
// Hyperkalaemia
slide.addShape(pres.ShapeType.roundRect, {
x: 6.82, y: 1.2, w: 6.48, h: 5.9,
fill: { color: C.cardBg }, line: { color: C.accent, width: 1.5 }, rectRadius: 0.1
});
slide.addShape(pres.ShapeType.rect, {
x: 6.82, y: 1.2, w: 6.48, h: 0.55,
fill: { color: C.accent }, line: { color: C.accent }
});
slide.addText("Hyperkalaemia (K⁺ >5.5 mmol/L)", {
x: 6.95, y: 1.22, w: 6.22, h: 0.5,
fontSize: 14, bold: true, color: C.white, fontFace: "Calibri", margin: 0, valign: "middle"
});
const hyperKStages = [
{ k: "K⁺ 5.5–6.5", changes: "Peaked/tented T waves (earliest sign)", c: C.yellow },
{ k: "K⁺ 6.5–7.0", changes: "Prolonged PR, wide QRS, flattened P waves", c: C.accent2 },
{ k: "K⁺ >7.0", changes: "Sine wave pattern (P merges into QRS)", c: C.accent },
{ k: "K⁺ >8.0", changes: "VF / asystole – cardiac arrest risk", c: C.accent },
];
slide.addText("ECG Changes by Severity", {
x: 6.95, y: 1.88, w: 6.22, h: 0.38,
fontSize: 13, bold: true, color: C.yellow, fontFace: "Calibri", margin: 0
});
hyperKStages.forEach((s, i) => {
slide.addShape(pres.ShapeType.roundRect, {
x: 7.0, y: 2.38 + i*0.74, w: 6.15, h: 0.62,
fill: { color: C.midBg }, line: { color: s.c, width: 1 }, rectRadius: 0.06
});
slide.addText(s.k, {
x: 7.1, y: 2.44 + i*0.74, w: 1.7, h: 0.5,
fontSize: 11, bold: true, color: s.c, fontFace: "Calibri", margin: 0
});
slide.addText(s.changes, {
x: 8.88, y: 2.44 + i*0.74, w: 4.2, h: 0.5,
fontSize: 11, color: C.light, fontFace: "Calibri", margin: 0
});
});
slide.addText("Management", {
x: 6.95, y: 5.42, w: 6.22, h: 0.38,
fontSize: 13, bold: true, color: C.accentG, fontFace: "Calibri", margin: 0
});
const hkMx = [
"Cardiac membrane stabilisation: IV Calcium Gluconate 10% 10 mL",
"Shift K⁺ into cells: insulin+dextrose, salbutamol nebuliser, NaHCO₃",
"Remove K⁺: kayexalate, furosemide, dialysis",
"Monitor on continuous cardiac monitoring throughout",
];
hkMx.forEach((item, i) => {
slide.addText("▸ " + item, {
x: 7.0, y: 5.85 + i*0.32, w: 6.1, h: 0.3,
fontSize: 10.5, color: C.light, fontFace: "Calibri", margin: 0
});
});
}
// ══════════════════════════════════════════════════════════════
// SLIDE 12 – PULMONARY EMBOLISM ECG & BUNDLE BRANCH BLOCKS
// ══════════════════════════════════════════════════════════════
{
const slide = pres.addSlide();
darkSlide(slide);
headerStrip(slide, C.midBg);
addSectionBar(slide, C.accentG);
slideTitle(slide, "Pulmonary Embolism ECG & Bundle Branch Blocks");
// PE ECG
slide.addShape(pres.ShapeType.roundRect, {
x: 0.22, y: 1.2, w: 6.3, h: 5.9,
fill: { color: C.cardBg }, line: { color: C.accentG, width: 1.5 }, rectRadius: 0.1
});
slide.addShape(pres.ShapeType.rect, {
x: 0.22, y: 1.2, w: 6.3, h: 0.55,
fill: { color: C.accentG }, line: { color: C.accentG }
});
slide.addText("Pulmonary Embolism – ECG Signs", {
x: 0.35, y: 1.22, w: 6.04, h: 0.5,
fontSize: 14, bold: true, color: C.darkBg, fontFace: "Calibri", margin: 0, valign: "middle"
});
const peItems = [
{ t: "Tachycardia", d: "Most common finding (sinus tachycardia)", c: C.accentG },
{ t: "S1Q3T3 Pattern", d: "S wave in I, Q wave + T inversion in III – only 20% sensitive", c: C.yellow },
{ t: "Right Heart Strain", d: "New RBBB, RAD, T inversion in V1–V4", c: C.accent2 },
{ t: "P Pulmonale", d: "Peaked P waves in II (>2.5mm) – right atrial enlargement", c: C.accentG },
{ t: "AF / Atrial Flutter", d: "New onset arrhythmia can be presenting feature", c: C.purple },
{ t: "Non-specific ST-T changes", d: "Often present but not diagnostic", c: C.muted },
];
peItems.forEach((pi, i) => {
slide.addShape(pres.ShapeType.roundRect, {
x: 0.35, y: 1.9 + i*0.77, w: 6.0, h: 0.68,
fill: { color: C.midBg }, line: { color: pi.c, width: 1 }, rectRadius: 0.06
});
slide.addText(pi.t, {
x: 0.5, y: 1.96 + i*0.77, w: 2.1, h: 0.55,
fontSize: 11.5, bold: true, color: pi.c, fontFace: "Calibri", margin: 0, valign: "middle"
});
slide.addText(pi.d, {
x: 2.68, y: 1.96 + i*0.77, w: 3.55, h: 0.55,
fontSize: 11, color: C.light, fontFace: "Calibri", margin: 0, valign: "middle"
});
});
slide.addText("⚠ ECG cannot rule out PE – use clinical probability (Wells) + CT-PA", {
x: 0.35, y: 6.7, w: 6.0, h: 0.35,
fontSize: 10, bold: true, color: C.yellow,
align: "center", valign: "middle", margin: 0
});
// Bundle branch blocks
slide.addShape(pres.ShapeType.roundRect, {
x: 6.82, y: 1.2, w: 6.48, h: 5.9,
fill: { color: C.cardBg }, line: { color: C.accent2, width: 1.5 }, rectRadius: 0.1
});
slide.addShape(pres.ShapeType.rect, {
x: 6.82, y: 1.2, w: 6.48, h: 0.55,
fill: { color: C.accent2 }, line: { color: C.accent2 }
});
slide.addText("Bundle Branch Blocks", {
x: 6.95, y: 1.22, w: 6.22, h: 0.5,
fontSize: 15, bold: true, color: C.white, fontFace: "Calibri", margin: 0, valign: "middle"
});
// RBBB
slide.addShape(pres.ShapeType.roundRect, {
x: 6.97, y: 1.9, w: 6.15, h: 2.15,
fill: { color: C.midBg }, line: { color: C.accent2, width: 1 }, rectRadius: 0.08
});
slide.addText("RBBB (Right Bundle Branch Block)", {
x: 7.1, y: 1.98, w: 5.9, h: 0.38,
fontSize: 13, bold: true, color: C.accent2, fontFace: "Calibri", margin: 0
});
const rbbbItems = [
"QRS >0.12s (wide)",
"RSR' pattern (M-shaped) in V1–V2 ('rabbit ears')",
"Deep slurred S wave in V5–V6, I, aVL",
"ST depression + T inversion in V1–V2",
];
rbbbItems.forEach((r, i) => {
slide.addText("• " + r, {
x: 7.1, y: 2.4 + i*0.36, w: 5.9, h: 0.34,
fontSize: 11, color: C.light, fontFace: "Calibri", margin: 0
});
});
// LBBB
slide.addShape(pres.ShapeType.roundRect, {
x: 6.97, y: 4.18, w: 6.15, h: 2.15,
fill: { color: C.midBg }, line: { color: C.purple, width: 1 }, rectRadius: 0.08
});
slide.addText("LBBB (Left Bundle Branch Block)", {
x: 7.1, y: 4.26, w: 5.9, h: 0.38,
fontSize: 13, bold: true, color: C.purple, fontFace: "Calibri", margin: 0
});
const lbbbItems = [
"QRS >0.12s (wide), broad notched R in I, aVL, V5–V6",
"Deep S in V1, no septal Q waves",
"Concordant ST changes (discordant in ischaemia – Sgarbossa)",
"New LBBB in chest pain context = treat as STEMI equivalent",
];
lbbbItems.forEach((l, i) => {
slide.addText("• " + l, {
x: 7.1, y: 4.68 + i*0.38, w: 5.9, h: 0.36,
fontSize: 11, color: C.light, fontFace: "Calibri", margin: 0
});
});
slide.addShape(pres.ShapeType.roundRect, {
x: 6.97, y: 6.46, w: 6.15, h: 0.38,
fill: { color: C.purple }, line: { color: C.purple }, rectRadius: 0.05
});
slide.addText("New LBBB + chest pain → Activate Cath Lab immediately", {
x: 6.97, y: 6.46, w: 6.15, h: 0.38,
fontSize: 11, bold: true, color: C.white,
align: "center", valign: "middle", margin: 0
});
}
// ══════════════════════════════════════════════════════════════
// SLIDE 13 – 4H 4T REVERSIBLE CAUSES & QUICK REFERENCE SUMMARY
// ══════════════════════════════════════════════════════════════
{
const slide = pres.addSlide();
darkSlide(slide);
headerStrip(slide, C.midBg);
addSectionBar(slide, C.yellow);
slideTitle(slide, "Reversible Causes of Cardiac Arrest – 4H & 4T");
const Hs = [
{ t: "Hypoxia", hint: "Ensure airway, high-flow O₂, ventilation" },
{ t: "Hypovolaemia", hint: "IV fluid challenge, control haemorrhage" },
{ t: "Hypo/Hyperkalaemia", hint: "Electrolytes, Ca gluconate, IV MgSO₄" },
{ t: "Hypothermia", hint: "Warm IV fluids, active rewarming, ECMO" },
];
const Ts = [
{ t: "Tension Pneumothorax", hint: "Needle decompression 2nd ICS MCL, then chest drain" },
{ t: "Tamponade (cardiac)", hint: "Pericardiocentesis or emergency thoracotomy" },
{ t: "Toxins / Overdose", hint: "Naloxone, flumazenil, specific antidotes" },
{ t: "Thrombosis (PE/MI)", hint: "Thrombolysis, PPCI, surgical embolectomy" },
];
// 4H box
slide.addShape(pres.ShapeType.roundRect, {
x: 0.22, y: 1.2, w: 6.3, h: 5.7,
fill: { color: C.cardBg }, line: { color: C.accentG, width: 1.5 }, rectRadius: 0.1
});
slide.addShape(pres.ShapeType.rect, {
x: 0.22, y: 1.2, w: 6.3, h: 0.55,
fill: { color: C.accentG }, line: { color: C.accentG }
});
slide.addText("4 H's", {
x: 0.35, y: 1.22, w: 6.04, h: 0.5,
fontSize: 22, bold: true, color: C.darkBg, fontFace: "Calibri",
align: "center", margin: 0, valign: "middle"
});
Hs.forEach((h, i) => {
slide.addShape(pres.ShapeType.roundRect, {
x: 0.35, y: 1.9 + i*1.18, w: 6.0, h: 1.05,
fill: { color: C.midBg }, line: { color: C.accentG, width: 0.8 }, rectRadius: 0.07
});
slide.addShape(pres.ShapeType.ellipse, {
x: 0.42, y: 1.97 + i*1.18, w: 0.55, h: 0.55,
fill: { color: C.accentG }, line: { color: C.accentG }
});
slide.addText("H", {
x: 0.42, y: 1.97 + i*1.18, w: 0.55, h: 0.55,
fontSize: 18, bold: true, color: C.darkBg,
align: "center", valign: "middle", margin: 0
});
slide.addText(h.t, {
x: 1.06, y: 1.97 + i*1.18, w: 4.9, h: 0.36,
fontSize: 13, bold: true, color: C.light, fontFace: "Calibri", margin: 0
});
slide.addText(h.hint, {
x: 1.06, y: 2.36 + i*1.18, w: 4.9, h: 0.36,
fontSize: 11, color: C.accentG, fontFace: "Calibri", margin: 0
});
});
// 4T box
slide.addShape(pres.ShapeType.roundRect, {
x: 6.82, y: 1.2, w: 6.48, h: 5.7,
fill: { color: C.cardBg }, line: { color: C.yellow, width: 1.5 }, rectRadius: 0.1
});
slide.addShape(pres.ShapeType.rect, {
x: 6.82, y: 1.2, w: 6.48, h: 0.55,
fill: { color: C.yellow }, line: { color: C.yellow }
});
slide.addText("4 T's", {
x: 6.95, y: 1.22, w: 6.22, h: 0.5,
fontSize: 22, bold: true, color: C.darkBg, fontFace: "Calibri",
align: "center", margin: 0, valign: "middle"
});
Ts.forEach((t, i) => {
slide.addShape(pres.ShapeType.roundRect, {
x: 6.95, y: 1.9 + i*1.18, w: 6.18, h: 1.05,
fill: { color: C.midBg }, line: { color: C.yellow, width: 0.8 }, rectRadius: 0.07
});
slide.addShape(pres.ShapeType.ellipse, {
x: 7.0, y: 1.97 + i*1.18, w: 0.55, h: 0.55,
fill: { color: C.yellow }, line: { color: C.yellow }
});
slide.addText("T", {
x: 7.0, y: 1.97 + i*1.18, w: 0.55, h: 0.55,
fontSize: 18, bold: true, color: C.darkBg,
align: "center", valign: "middle", margin: 0
});
slide.addText(t.t, {
x: 7.65, y: 1.97 + i*1.18, w: 5.1, h: 0.36,
fontSize: 13, bold: true, color: C.light, fontFace: "Calibri", margin: 0
});
slide.addText(t.hint, {
x: 7.65, y: 2.36 + i*1.18, w: 5.1, h: 0.36,
fontSize: 11, color: C.yellow, fontFace: "Calibri", margin: 0
});
});
}
// ══════════════════════════════════════════════════════════════
// SLIDE 14 – SUMMARY TABLE
// ══════════════════════════════════════════════════════════════
{
const slide = pres.addSlide();
darkSlide(slide);
headerStrip(slide, C.midBg);
addSectionBar(slide, C.accentG);
slideTitle(slide, "Quick Reference Summary");
const rows = [
{ cond: "STEMI", ecg: "ST elevation ≥1mm in 2+ leads, new LBBB", action: "PCI within 90 min, aspirin+ticagrelor", urgency: "EMERGENCY", uc: C.accent },
{ cond: "NSTEMI/UA", ecg: "ST depression, T inversion, or normal ECG", action: "GRACE score, anticoagulate, angiography <72h", urgency: "URGENT", uc: C.accent2 },
{ cond: "VF/Pulseless VT", ecg: "Chaotic/wide QRS, no organised rhythm", action: "Defibrillate + CPR, adrenaline + amiodarone", urgency: "EMERGENCY", uc: C.accent },
{ cond: "SVT", ecg: "Narrow QRS tachycardia 150–250 bpm", action: "Vagal manoeuvre → adenosine → cardioversion", urgency: "URGENT", uc: C.purple },
{ cond: "AF", ecg: "Irregularly irregular, absent P waves", action: "Rate/rhythm control, anticoagulate", urgency: "MONITOR", uc: C.accent2 },
{ cond: "3rd Degree HB", ecg: "AV dissociation, slow escape rhythm", action: "Atropine, transcutaneous then transvenous pacing",urgency: "EMERGENCY",uc: C.accent },
{ cond: "WPW + AF", ecg: "Fast, irregular, wide QRS – delta waves in sinus", action: "DC cardioversion; avoid adenosine/digoxin", urgency: "EMERGENCY", uc: C.accent },
{ cond: "Long QT/TdP", ecg: "QTc >440ms, twisting polymorphic VT", action: "IV MgSO₄ 2g, stop offending drugs, overdrive pacing", urgency: "EMERGENCY", uc: C.accent },
{ cond: "Hyperkalaemia", ecg: "Peaked T, wide QRS, sine wave", action: "Ca gluconate, insulin+dextrose, dialysis", urgency: "URGENT", uc: C.yellow },
{ cond: "PE", ecg: "Sinus tach, S1Q3T3, new RBBB", action: "CTPA, anticoagulate, thrombolysis if massive", urgency: "URGENT", uc: C.accentG },
];
// Header row
slide.addShape(pres.ShapeType.rect, {
x: 0.18, y: 1.1, w: 13.14, h: 0.45,
fill: { color: C.accentG }, line: { color: C.accentG }
});
["Condition", "ECG Features", "Immediate Action", "Priority"].forEach((hdr, i) => {
const widths = [2.1, 4.4, 5.2, 1.35];
const xs = [0.2, 2.34, 6.78, 12.02];
slide.addText(hdr, {
x: xs[i], y: 1.1, w: widths[i], h: 0.45,
fontSize: 12, bold: true, color: C.darkBg,
fontFace: "Calibri", margin: 4, valign: "middle"
});
});
rows.forEach((r, i) => {
const by = 1.58 + i * 0.49;
const rowBg = i % 2 === 0 ? C.cardBg : C.midBg;
slide.addShape(pres.ShapeType.rect, {
x: 0.18, y: by, w: 13.14, h: 0.47,
fill: { color: rowBg }, line: { color: C.midBg }
});
slide.addText(r.cond, {
x: 0.22, y: by + 0.03, w: 2.08, h: 0.41,
fontSize: 10.5, bold: true, color: r.uc, fontFace: "Calibri", margin: 3, valign: "middle"
});
slide.addText(r.ecg, {
x: 2.34, y: by + 0.03, w: 4.38, h: 0.41,
fontSize: 10, color: C.light, fontFace: "Calibri", margin: 3, valign: "middle"
});
slide.addText(r.action, {
x: 6.78, y: by + 0.03, w: 5.2, h: 0.41,
fontSize: 10, color: C.light, fontFace: "Calibri", margin: 3, valign: "middle"
});
// Priority badge
slide.addShape(pres.ShapeType.roundRect, {
x: 12.06, y: by + 0.06, w: 1.18, h: 0.34,
fill: { color: r.uc }, line: { color: r.uc }, rectRadius: 0.05
});
slide.addText(r.urgency, {
x: 12.06, y: by + 0.06, w: 1.18, h: 0.34,
fontSize: 8, bold: true, color: r.urgency === "MONITOR" ? C.darkBg : C.white,
align: "center", valign: "middle", margin: 0
});
});
}
// ══════════════════════════════════════════════════════════════
// SLIDE 15 – CLOSING SLIDE
// ══════════════════════════════════════════════════════════════
{
const slide = pres.addSlide();
slide.addShape(pres.ShapeType.rect, {
x: 0, y: 0, w: "100%", h: "100%", fill: { color: C.darkBg }
});
slide.addShape(pres.ShapeType.rect, {
x: 0, y: 2.8, w: "100%", h: 0.08, fill: { color: C.accent }
});
slide.addText("KEY TAKEAWAYS", {
x: 0.8, y: 0.5, w: 11.7, h: 0.65,
fontSize: 28, bold: true, color: C.accent, fontFace: "Calibri",
align: "center", charSpacing: 4
});
const takeaways = [
{ icon: "1", msg: "Systematic approach to every ECG: Rate → Rhythm → Axis → Intervals → ST-T", c: C.accentG },
{ icon: "2", msg: "Time = Myocardium: New STEMI or LBBB → activate cath lab immediately", c: C.accent },
{ icon: "3", msg: "VF/pulseless VT = shockable: CPR + defibrillate + adrenaline + amiodarone", c: C.accent },
{ icon: "4", msg: "SVT: vagal manoeuvres first → adenosine. WPW + AF: never give AV nodal blockers", c: C.purple },
{ icon: "5", msg: "Always look for reversible causes (4H & 4T) in any cardiac arrest", c: C.yellow },
{ icon: "6", msg: "ECG is a snapshot: compare with old ECGs and correlate with clinical picture", c: C.accentG },
];
takeaways.forEach((t, i) => {
const col = i % 2;
const row = Math.floor(i / 2);
const bx = 0.4 + col * 6.65;
const by = 3.1 + row * 1.3;
slide.addShape(pres.ShapeType.roundRect, {
x: bx, y: by, w: 6.3, h: 1.1,
fill: { color: C.cardBg }, line: { color: t.c, width: 1 }, rectRadius: 0.08
});
slide.addShape(pres.ShapeType.ellipse, {
x: bx + 0.12, y: by + 0.27, w: 0.55, h: 0.55,
fill: { color: t.c }, line: { color: t.c }
});
slide.addText(t.icon, {
x: bx + 0.12, y: by + 0.27, w: 0.55, h: 0.55,
fontSize: 16, bold: true, color: C.white,
align: "center", valign: "middle", margin: 0
});
slide.addText(t.msg, {
x: bx + 0.78, y: by + 0.12, w: 5.42, h: 0.86,
fontSize: 12, color: C.light, fontFace: "Calibri", margin: 4
});
});
slide.addText("Emergency Medicine | ECG Emergency Cases | 2026", {
x: 0.8, y: 7.0, w: 11.7, h: 0.35,
fontSize: 12, color: C.muted, align: "center", fontFace: "Calibri"
});
}
// ── Write file ────────────────────────────────────────────────
pres.writeFile({ fileName: "/home/daytona/workspace/ecg-emergency-ppt/ECG_Emergency_Cases.pptx" })
.then(() => console.log("Done: ECG_Emergency_Cases.pptx"))
.catch(err => { console.error(err); process.exit(1); });
cd /home/daytona/workspace/ecg-emergency-ppt && node create_ecg_ppt.js
ls -lh /home/daytona/workspace/ecg-emergency-ppt/ECG_Emergency_Cases.pptx
ECG Emergency Cases
Presentation · PPTX
| Slide | Topic |
|---|---|
| 1 | Title slide |
| 2 | How to Read an ECG - systematic 6-step approach |
| 3 | STEMI - territories, lead localisation, PCI management |
| 4 | NSTEMI & Unstable Angina - ECG findings, risk stratification |
| 5 | VF & Pulseless VT - ALS shockable algorithm |
| 6 | SVT - subtypes (AVNRT, AVRT, WPW), adenosine protocol |
| 7 | Atrial Fibrillation & Atrial Flutter |
| 8 | AV Heart Blocks (1st, 2nd Mobitz I & II, 3rd degree - complete) |
| 9 | Bradyarrhythmias & Broad Complex Tachycardias (VT vs SVT) |
| 10 | WPW Syndrome & Long QT / Torsades de Pointes |
| 11 | Pericarditis ECG stages & Hyperkalaemia (K⁺ progression) |
| 12 | Pulmonary Embolism ECG signs & Bundle Branch Blocks (RBBB/LBBB) |
| 13 | Reversible Causes of Cardiac Arrest - 4H & 4T |
| 14 | Quick Reference Summary Table (all 10 conditions at a glance) |
| 15 | Key Takeaways / Closing slide |