Make a ppt on peptic ulcer disease for undergraduate medical students (mbbs) in India from Bailey and love Ot should not have more than 25 slides and end in one hour it should also have case based discussion at the first and last and pictures related to each slide it should be interactive and should have lot of flow chart and each slide should have not more than 10 points and each point should not have more than 10 words I will also provide with a checklist of peer review and it should have heading and subheadings accordingly
mkdir -p /home/daytona/workspace/peptic-ulcer-ppt && ls /home/daytona/workspace/…
~/peptic-ulcer-ppt/create_ppt.js
const pptxgen = require("pptxgenjs");
const { execSync } = require("child_process");
// ─── FETCH IMAGES ──────────────────────────────────────────────────────────
const imageUrls = [
"https://cdn.orris.care/cdss_images/9b8c9b80815ac3526d6c02271dd7a0ea8b3a0d054a5db153ca8b9827c1b8fb42.png", // Duodenal ulcer endoscopy
"https://cdn.orris.care/cdss_images/675c6b1515e8f1b218a165f8bee0054477bcedf899e353e0883df93d04bf5587.png", // Barium meal duodenal ulcer
"https://cdn.orris.care/cdss_images/ec56874995d0dbd5dae7706865ecb332a07f6afd474a8fe534c6d384e4ed95bb.png" // Chest X-ray - free air
];
let imgDuodenal = "", imgBarium = "", imgCXR = "";
try {
const raw = execSync(
`node /home/daytona/skills/shared/scripts/fetch_images.js "${imageUrls[0]}" "${imageUrls[1]}" "${imageUrls[2]}"`,
{ maxBuffer: 50 * 1024 * 1024 }
).toString();
const imgs = JSON.parse(raw);
imgDuodenal = imgs[0] && !imgs[0].error ? imgs[0].base64 : "";
imgBarium = imgs[1] && !imgs[1].error ? imgs[1].base64 : "";
imgCXR = imgs[2] && !imgs[2].error ? imgs[2].base64 : "";
} catch(e) {
console.error("Image fetch error:", e.message);
}
// ─── COLOR PALETTE ─────────────────────────────────────────────────────────
const C = {
navy: "0D2B4E",
teal: "1A7A8A",
orange: "E05A1A",
cream: "FDF6EC",
white: "FFFFFF",
light: "E8F4F8",
gray: "F4F4F4",
darkGray:"444444",
red: "C0392B",
green: "1E7E34",
yellow: "F39C12",
purple: "6C3483",
lime: "27AE60"
};
// ─── HELPERS ───────────────────────────────────────────────────────────────
function addSlideBg(slide, color) {
slide.addShape("rect", { x: 0, y: 0, w: "100%", h: "100%", fill: { color } });
}
function addHeader(slide, title, subtitle, bgColor, textColor) {
bgColor = bgColor || C.navy;
textColor = textColor || C.white;
slide.addShape("rect", { x: 0, y: 0, w: "100%", h: 0.85, fill: { color: bgColor } });
slide.addText(title, {
x: 0.15, y: 0.05, w: 9.7, h: 0.6,
fontSize: 20, bold: true, color: textColor, fontFace: "Calibri",
align: "left", valign: "middle", margin: 2
});
if (subtitle) {
slide.addShape("rect", { x: 0, y: 0.82, w: "100%", h: 0.07, fill: { color: C.orange } });
}
}
function addFooter(slide, source) {
source = source || "Source: Bailey & Love's Short Practice of Surgery, 28th Ed.";
slide.addShape("rect", { x: 0, y: 5.35, w: "100%", h: 0.27, fill: { color: C.navy } });
slide.addText(source, {
x: 0.2, y: 5.36, w: 9.6, h: 0.24,
fontSize: 7, color: C.white, fontFace: "Calibri", italic: true,
align: "left", valign: "middle"
});
}
function bullet(text, bold, color) {
return {
text: text,
options: {
bullet: { type: "bullet", characterCode: "25B6", color: C.orange },
bold: bold || false,
color: color || C.darkGray,
fontSize: 13,
fontFace: "Calibri",
breakLine: true,
paraSpaceAfter: 4
}
};
}
function subbullet(text) {
return {
text: " " + text,
options: {
bullet: false,
bold: false,
color: "555555",
fontSize: 11.5,
fontFace: "Calibri",
breakLine: true,
paraSpaceAfter: 2,
indentLevel: 1
}
};
}
function box(slide, x, y, w, h, text, bgColor, textColor, fontSize, bold) {
slide.addShape("roundRect", {
x, y, w, h,
fill: { color: bgColor || C.teal },
line: { color: bgColor || C.teal, width: 0 },
rectRadius: 0.08
});
slide.addText(text, {
x, y, w, h,
fontSize: fontSize || 11,
bold: bold !== undefined ? bold : true,
color: textColor || C.white,
fontFace: "Calibri",
align: "center",
valign: "middle",
wrap: true
});
}
function arrow(slide, x, y, vertical) {
if (vertical) {
slide.addShape("downArrow", { x, y, w: 0.22, h: 0.28, fill: { color: C.orange } });
} else {
slide.addShape("rightArrow", { x, y, w: 0.28, h: 0.22, fill: { color: C.orange } });
}
}
// ─── PRESENTATION ──────────────────────────────────────────────────────────
const pres = new pptxgen();
pres.layout = "LAYOUT_16x9";
pres.author = "Dept of Surgery";
pres.title = "Peptic Ulcer Disease";
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 1 — TITLE SLIDE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.navy);
// Top accent bar
s.addShape("rect", { x: 0, y: 0, w: "100%", h: 0.12, fill: { color: C.orange } });
// Stomach silhouette background shape (decorative rectangle)
s.addShape("roundRect", {
x: 6.8, y: 0.5, w: 3.0, h: 4.8,
fill: { color: "0A2240" }, line: { color: "0A2240" }, rectRadius: 0.3
});
// Main title
s.addText("PEPTIC ULCER DISEASE", {
x: 0.3, y: 0.8, w: 6.3, h: 1.1,
fontSize: 34, bold: true, color: C.white,
fontFace: "Calibri", charSpacing: 2
});
// Subtitle
s.addShape("rect", { x: 0.3, y: 2.0, w: 5.8, h: 0.06, fill: { color: C.orange } });
s.addText("An Interactive Case-Based Session", {
x: 0.3, y: 2.1, w: 6.0, h: 0.5,
fontSize: 16, color: C.light, fontFace: "Calibri", italic: true
});
// Info boxes
const infoItems = [
["For MBBS Students – Surgery", C.teal],
["Based on Bailey & Love, 28th Ed.", "1A5276"],
["Duration: 60 Minutes", C.orange]
];
infoItems.forEach(([txt, col], i) => {
s.addShape("roundRect", { x: 0.3, y: 2.75 + i * 0.52, w: 5.6, h: 0.44, fill: { color: col }, rectRadius: 0.05 });
s.addText(txt, {
x: 0.3, y: 2.75 + i * 0.52, w: 5.6, h: 0.44,
fontSize: 13, color: C.white, bold: true, fontFace: "Calibri",
align: "center", valign: "middle"
});
});
// Right panel content
const topics = ["Anatomy & Pathophysiology","Aetiology & Risk Factors","Clinical Features","Investigations","Medical Management","Complications","Surgical Management","Case Discussion"];
s.addText("TOPICS COVERED", { x: 6.85, y: 0.65, w: 2.85, h: 0.38, fontSize: 10.5, bold: true, color: C.orange, fontFace: "Calibri", align: "center" });
topics.forEach((t, i) => {
s.addText(`${i + 1}. ${t}`, {
x: 6.9, y: 1.08 + i * 0.47, w: 2.75, h: 0.4,
fontSize: 9.5, color: C.light, fontFace: "Calibri", align: "left"
});
});
// Bottom bar
s.addShape("rect", { x: 0, y: 5.35, w: "100%", h: 0.27, fill: { color: C.orange } });
s.addText("Peer Review Checklist Aligned • Interactive Q&A • Flowcharts & Images", {
x: 0.2, y: 5.36, w: 9.6, h: 0.24, fontSize: 8, color: C.navy, bold: true,
fontFace: "Calibri", align: "center"
});
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 2 — LEARNING OBJECTIVES + STRUCTURE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.cream);
addHeader(s, "Learning Objectives", true);
// Left column
s.addShape("roundRect", { x: 0.15, y: 0.95, w: 4.6, h: 4.28, fill: { color: C.navy }, rectRadius: 0.1 });
s.addText("By end of session, students will:", {
x: 0.25, y: 0.98, w: 4.4, h: 0.42, fontSize: 11.5, bold: true, color: C.orange, fontFace: "Calibri", align: "center"
});
const objectives = [
"Define peptic ulcer disease (PUD)",
"Describe anatomy & pathophysiology",
"List aetiological factors (H. pylori, NSAIDs)",
"Identify clinical features & signs",
"Choose appropriate investigations",
"Plan medical management (PPIs, eradication)",
"Recognise & manage complications",
"Outline indications for surgery"
];
objectives.forEach((obj, i) => {
s.addShape("circle", { x: 0.28, y: 1.47 + i * 0.45, w: 0.22, h: 0.22, fill: { color: C.orange } });
s.addText(`${i + 1}`, { x: 0.28, y: 1.47 + i * 0.45, w: 0.22, h: 0.22, fontSize: 9, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(obj, {
x: 0.55, y: 1.44 + i * 0.45, w: 4.1, h: 0.38,
fontSize: 11, color: C.white, fontFace: "Calibri", valign: "middle"
});
});
// Right - Session structure
s.addShape("roundRect", { x: 4.9, y: 0.95, w: 4.9, h: 4.28, fill: { color: C.light }, rectRadius: 0.1 });
s.addText("SESSION STRUCTURE (60 min)", {
x: 5.0, y: 0.98, w: 4.7, h: 0.42, fontSize: 11.5, bold: true, color: C.navy, fontFace: "Calibri", align: "center"
});
const structure = [
["Case Vignette (Opening)", "5 min", C.orange],
["Basics: Definition & Anatomy", "5 min", C.teal],
["Aetiology & Pathophysiology", "8 min", C.teal],
["Clinical Features & Investigations", "8 min", C.teal],
["Medical Management", "8 min", C.teal],
["Complications & Surgery", "10 min", C.teal],
["Case Discussion & Q&A", "10 min", C.orange],
["MCQs & Summary", "6 min", C.navy]
];
structure.forEach(([item, time, col], i) => {
s.addShape("roundRect", { x: 5.05, y: 1.47 + i * 0.44, w: 3.5, h: 0.38, fill: { color: col }, rectRadius: 0.04 });
s.addText(item, { x: 5.05, y: 1.47 + i * 0.44, w: 2.85, h: 0.38, fontSize: 10.5, color: C.white, fontFace: "Calibri", bold: true, valign: "middle", margin: 4 });
s.addText(time, { x: 7.9, y: 1.47 + i * 0.44, w: 0.68, h: 0.38, fontSize: 10, color: C.white, fontFace: "Calibri", align: "center", valign: "middle", bold: true });
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 3 — OPENING CASE (CASE 1)
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, "FFF8F0");
addHeader(s, "Opening Case Vignette – THINK!", null, C.orange, C.white);
// Case box
s.addShape("roundRect", { x: 0.15, y: 0.98, w: 9.7, h: 2.15, fill: { color: C.navy }, rectRadius: 0.12 });
s.addText("CASE VIGNETTE", { x: 0.25, y: 1.0, w: 2.2, h: 0.36, fontSize: 10.5, bold: true, color: C.orange, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(
"Raju, 35-year-old male, smoker, construction worker presents with 3-month history of episodic " +
"burning epigastric pain, worse at night, relieved by food/antacids. He takes diclofenac for back pain. " +
"O/E: mild epigastric tenderness. No guarding.",
{
x: 0.25, y: 1.4, w: 9.4, h: 1.6,
fontSize: 13.5, color: C.white, fontFace: "Calibri", bold: false,
align: "left", valign: "top", wrap: true
}
);
// Questions
s.addText("Interactive Questions:", { x: 0.15, y: 3.22, w: 4.0, h: 0.35, fontSize: 13, bold: true, color: C.navy, fontFace: "Calibri" });
const questions = [
["Q1", "What is your provisional diagnosis?", C.teal],
["Q2", "What are the risk factors in this case?", C.orange],
["Q3", "What investigations would you order first?", C.purple],
["Q4", "What would you do immediately to treat?", C.red]
];
questions.forEach(([num, q, col], i) => {
const col2 = i < 2 ? 0.15 : 5.1;
const row2 = i < 2 ? i : i - 2;
s.addShape("roundRect", { x: col2, y: 3.62 + row2 * 0.7, w: 4.75, h: 0.6, fill: { color: col }, rectRadius: 0.06 });
s.addText(num, { x: col2 + 0.07, y: 3.62 + row2 * 0.7, w: 0.45, h: 0.6, fontSize: 12, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(q, { x: col2 + 0.55, y: 3.62 + row2 * 0.7, w: 4.1, h: 0.6, fontSize: 11.5, color: C.white, fontFace: "Calibri", valign: "middle" });
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 4 — DEFINITION & ANATOMY
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.cream);
addHeader(s, "Definition & Anatomy", true, C.navy, C.white);
// Definition box
s.addShape("roundRect", { x: 0.15, y: 0.98, w: 9.7, h: 0.85, fill: { color: C.teal }, rectRadius: 0.1 });
s.addText("DEFINITION: A breach in the mucosa of the GI tract exposed to acid-pepsin, extending through muscularis mucosae.", {
x: 0.25, y: 0.98, w: 9.5, h: 0.85, fontSize: 13, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle", wrap: true
});
// Left: Sites
s.addText("Common Sites", { x: 0.15, y: 1.9, w: 4.5, h: 0.38, fontSize: 14, bold: true, color: C.navy, fontFace: "Calibri" });
const sites = [
["1st part of duodenum", C.orange, "Most common"],
["Lesser curve of stomach", C.teal, "Gastric ulcer"],
["Prepyloric / Pyloric channel", C.navy, "Like duodenal"],
["Post-op stoma (Billroth II)", "888888", "Stomal ulcer"],
["Ectopic gastric epithelium", "888888", "Meckel's"]
];
sites.forEach(([name, col, note], i) => {
s.addShape("roundRect", { x: 0.15, y: 2.34 + i * 0.56, w: 3.2, h: 0.48, fill: { color: col }, rectRadius: 0.06 });
s.addText(name, { x: 0.15, y: 2.34 + i * 0.56, w: 3.2, h: 0.48, fontSize: 11, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addShape("roundRect", { x: 3.38, y: 2.34 + i * 0.56, w: 1.4, h: 0.48, fill: { color: "EEEEEE" }, rectRadius: 0.04 });
s.addText(note, { x: 3.38, y: 2.34 + i * 0.56, w: 1.4, h: 0.48, fontSize: 10, color: C.darkGray, fontFace: "Calibri", align: "center", valign: "middle", italic: true });
});
// Right: Key facts
s.addText("Key Anatomical Facts", { x: 5.1, y: 1.9, w: 4.7, h: 0.38, fontSize: 14, bold: true, color: C.navy, fontFace: "Calibri" });
const facts = [
"Ulcer = at junction of different epithelium",
"Acid sine qua non — no acid = no ulcer",
"DU: anterior tend to perforate",
"DU: posterior tend to bleed (GDA)",
"GU: must biopsy — risk of malignancy",
"Kissing ulcers: anterior + posterior DU",
"Meckel's: ectopic gastric mucosa bleeds"
];
s.addText(facts.map(f => ({ text: f, options: { bullet: { type: "bullet", characterCode: "25BA", color: C.orange }, breakLine: true, fontSize: 11.5, color: C.darkGray, fontFace: "Calibri", paraSpaceAfter: 5 } })),
{ x: 5.1, y: 2.35, w: 4.65, h: 3.05 }
);
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 5 — AETIOLOGY FLOWCHART
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.gray);
addHeader(s, "Aetiology of Peptic Ulcer Disease", true, C.navy, C.white);
// Central box
box(s, 3.8, 1.6, 2.4, 0.7, "PEPTIC ULCER", C.red, C.white, 13, true);
// Left side causes
const leftCauses = [
["H. pylori\n(80% DU, 60% GU)", C.orange, 0.2, 1.05],
["NSAIDs / Aspirin\n(Mucosal damage)", C.teal, 0.2, 2.05],
["Cigarette Smoking\n(↓ mucosal defence)", "5D4037", 0.2, 3.05],
["Steroids\n(Combined with NSAIDs)", "6C3483", 0.2, 4.05]
];
leftCauses.forEach(([txt, col, bx, by]) => {
box(s, bx, by, 2.2, 0.72, txt, col, C.white, 10, true);
s.addShape("rightArrow", { x: 2.45, y: by + 0.22, w: 1.3, h: 0.28, fill: { color: C.orange } });
});
// Right side causes
const rightCauses = [
["Zollinger-Ellison\n(Gastrinoma - ↑↑ acid)", C.red, 7.6, 1.05],
["Stress Ulcers\n(ICU, burns, trauma)", "1565C0", 7.6, 2.05],
["Blood Group O\n(Genetic predisposition)", "4A235B", 7.6, 3.05],
["Alcohol / Reflux\n(Minor role)", "424242", 7.6, 4.05]
];
rightCauses.forEach(([txt, col, bx, by]) => {
s.addShape("leftArrow", { x: 6.2, y: by + 0.22, w: 1.3, h: 0.28, fill: { color: C.teal } });
box(s, bx, by, 2.2, 0.72, txt, col, C.white, 10, true);
});
// H pylori note at bottom
s.addShape("roundRect", { x: 0.15, y: 5.0, w: 9.7, h: 0.28, fill: { color: C.navy }, rectRadius: 0.04 });
s.addText("H. pylori + NSAIDs account for >90% of peptic ulcers | Smoking doubles relapse rate (Bailey & Love)", {
x: 0.15, y: 5.0, w: 9.7, h: 0.28, fontSize: 9.5, bold: true, color: C.orange, fontFace: "Calibri", align: "center", valign: "middle"
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 6 — PATHOPHYSIOLOGY
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.cream);
addHeader(s, "Pathophysiology – Imbalance of Forces", true, C.navy, C.white);
// Left: Aggressive
s.addShape("roundRect", { x: 0.15, y: 0.98, w: 4.0, h: 3.8, fill: { color: "FDEDEC" }, rectRadius: 0.1, line: { color: C.red, width: 2 } });
s.addText("⚔ AGGRESSIVE FACTORS", { x: 0.15, y: 0.98, w: 4.0, h: 0.48, fontSize: 12, bold: true, color: C.red, fontFace: "Calibri", align: "center", valign: "middle" });
const agg = ["Hydrochloric acid (HCl)", "Pepsin", "H. pylori (urease, VacA, CagA)", "NSAIDs (↓ PGE2 synthesis)", "Bile reflux", "Reactive oxygen species", "Stress-induced cortisol"];
agg.forEach((a, i) => {
s.addShape("rect", { x: 0.25, y: 1.5 + i * 0.33, w: 0.16, h: 0.22, fill: { color: C.red } });
s.addText(a, { x: 0.48, y: 1.47 + i * 0.33, w: 3.6, h: 0.3, fontSize: 11, color: C.darkGray, fontFace: "Calibri" });
});
// Center balance symbol
s.addShape("roundRect", { x: 4.22, y: 1.9, w: 1.56, h: 1.6, fill: { color: C.navy }, rectRadius: 0.12 });
s.addText("⚖\nIMBALANCE\n=\nULCER", { x: 4.22, y: 1.9, w: 1.56, h: 1.6, fontSize: 12, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
// Right: Defensive
s.addShape("roundRect", { x: 5.85, y: 0.98, w: 4.0, h: 3.8, fill: { color: "EAF7EA" }, rectRadius: 0.1, line: { color: C.green, width: 2 } });
s.addText("🛡 DEFENSIVE FACTORS", { x: 5.85, y: 0.98, w: 4.0, h: 0.48, fontSize: 12, bold: true, color: C.green, fontFace: "Calibri", align: "center", valign: "middle" });
const def = ["Mucus-bicarbonate layer", "Prostaglandin E2 (PGE2)", "Mucosal blood flow", "Tight epithelial junctions", "Epithelial restitution", "Trefoil peptides", "Duodenal alkaline secretion"];
def.forEach((d, i) => {
s.addShape("rect", { x: 5.95, y: 1.5 + i * 0.33, w: 0.16, h: 0.22, fill: { color: C.green } });
s.addText(d, { x: 6.18, y: 1.47 + i * 0.33, w: 3.6, h: 0.3, fontSize: 11, color: C.darkGray, fontFace: "Calibri" });
});
// H pylori mechanism
s.addShape("roundRect", { x: 0.15, y: 4.85, w: 9.7, h: 0.4, fill: { color: C.teal }, rectRadius: 0.05 });
s.addText("H. pylori → Urease → NH3 → Local toxicity + ↑ gastrin → ↑ acid → Ulcer", {
x: 0.15, y: 4.85, w: 9.7, h: 0.4, fontSize: 11, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle"
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 7 — H. PYLORI DETAILS
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.cream);
addHeader(s, "H. pylori – The Ulcer Pathogen", true, C.orange, C.white);
// Top facts
const topFacts = [
["Gram -ve\nSpiral Rod", C.teal],
["Urease +ve\n(Rapid test)", C.orange],
["Lives in\nAntrum", C.navy],
["WHO Class I\nCarcinogen", C.red],
["50%+\nWorld Pop", "6C3483"]
];
topFacts.forEach(([txt, col], i) => {
box(s, 0.15 + i * 1.94, 1.0, 1.78, 0.88, txt, col, C.white, 10.5, true);
});
// Virulence factors
s.addText("Virulence Factors:", { x: 0.15, y: 2.0, w: 4.5, h: 0.35, fontSize: 13, bold: true, color: C.navy, fontFace: "Calibri" });
const virulence = [
"Urease: splits urea → NH3 + CO2 (local toxicity)",
"VacA: vacuolating cytotoxin — epithelial injury",
"CagA (cag pathogenicity island): inflammation",
"BabA: adhesin — binds Lewis blood antigens",
"OipA: outer inflammatory protein"
];
virulence.forEach((v, i) => {
s.addShape("circle", { x: 0.18, y: 2.42 + i * 0.42, w: 0.2, h: 0.2, fill: { color: C.orange } });
s.addText(v, { x: 0.45, y: 2.38 + i * 0.42, w: 4.55, h: 0.38, fontSize: 11, color: C.darkGray, fontFace: "Calibri" });
});
// Right: Diagnosis methods
s.addText("Diagnosis of H. pylori:", { x: 5.2, y: 2.0, w: 4.6, h: 0.35, fontSize: 13, bold: true, color: C.navy, fontFace: "Calibri" });
const diagData = [
["Urea Breath Test", "Non-invasive, 95% sens", C.lime],
["CLO Test (Biopsy)", "Invasive, rapid, cheap", C.teal],
["Stool Antigen Test", "Non-invasive, 90%+", C.lime],
["Serology (IgG)", "Cannot confirm active", "888888"],
["Histology (Biopsy)", "Gold standard", C.orange],
["Culture (Biopsy)", "Sensitivity testing", "888888"]
];
diagData.forEach(([test, note, col], i) => {
s.addShape("roundRect", { x: 5.2, y: 2.42 + i * 0.42, w: 2.8, h: 0.36, fill: { color: col }, rectRadius: 0.04 });
s.addText(test, { x: 5.2, y: 2.42 + i * 0.42, w: 2.8, h: 0.36, fontSize: 10.5, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(note, { x: 8.05, y: 2.42 + i * 0.42, w: 1.75, h: 0.36, fontSize: 10, color: C.darkGray, fontFace: "Calibri", italic: true, valign: "middle" });
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 8 — DU vs GU COMPARISON
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.cream);
addHeader(s, "Duodenal Ulcer vs Gastric Ulcer", true, C.navy, C.white);
const headers = ["Feature", "Duodenal Ulcer", "Gastric Ulcer"];
const rows = [
["Incidence", "More common (4:1)", "Less common"],
["Age", "Younger (30-50 yrs)", "Older (50-70 yrs)"],
["Gender", "M>F (3:1)", "M=F"],
["Acid secretion", "↑ or normal", "Normal or ↓"],
["H. pylori", "~80% cases", "~60% cases"],
["Malignancy", "Virtually never", "Must exclude!"],
["Night pain", "Classic - food relieves", "Food may worsen"],
["Weight", "Normal / gain", "Weight loss"],
["Perforation", "Anterior wall", "Rare"],
["Bleeding", "Posterior (GDA)", "Lesser curve"]
];
const colW = [2.5, 3.4, 3.4];
const startX = [0.15, 2.68, 6.1];
// Header row
headers.forEach((h, c) => {
s.addShape("roundRect", { x: startX[c], y: 0.95, w: colW[c], h: 0.5, fill: { color: c === 0 ? C.navy : c === 1 ? C.teal : C.orange }, rectRadius: 0.05 });
s.addText(h, { x: startX[c], y: 0.95, w: colW[c], h: 0.5, fontSize: 13, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
});
// Data rows
rows.forEach((row, r) => {
const rowBg = r % 2 === 0 ? "FFFFFF" : C.light;
row.forEach((cell, c) => {
s.addShape("rect", { x: startX[c], y: 1.48 + r * 0.38, w: colW[c], h: 0.38, fill: { color: rowBg }, line: { color: "CCCCCC", width: 0.5 } });
s.addText(cell, {
x: startX[c] + 0.06, y: 1.48 + r * 0.38, w: colW[c] - 0.1, h: 0.38,
fontSize: 10.5, color: c === 0 ? C.navy : C.darkGray, bold: c === 0,
fontFace: "Calibri", valign: "middle"
});
});
});
// Key rule
s.addShape("roundRect", { x: 0.15, y: 5.05, w: 9.7, h: 0.32, fill: { color: C.red }, rectRadius: 0.05 });
s.addText("⚠ All gastric ulcers must be biopsied to exclude malignancy! (Bailey & Love Rule)", {
x: 0.15, y: 5.05, w: 9.7, h: 0.32, fontSize: 11, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle"
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 9 — CLINICAL FEATURES
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.cream);
addHeader(s, "Clinical Features of Peptic Ulcer", true, C.navy, C.white);
// Symptom cards - top row
const symptoms = [
["PAIN", "Epigastric burning/gnawing\nRadiates to back\nEpisodic, periodic\nNight waking", C.orange],
["RELIEF", "Food (DU typical)\nAntacids\nSpontaneous healing\nRecurrence pattern", C.lime],
["VOMITING", "Uncommon unless stenosis\nMay relieve pain\nProjectile if pyloric\nVoiding gastric remnant", C.teal]
];
symptoms.forEach(([title, content, col], i) => {
s.addShape("roundRect", { x: 0.15 + i * 3.25, y: 1.0, w: 3.1, h: 2.3, fill: { color: col }, rectRadius: 0.12 });
s.addText(title, { x: 0.15 + i * 3.25, y: 1.0, w: 3.1, h: 0.42, fontSize: 13, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(content, { x: 0.25 + i * 3.25, y: 1.45, w: 2.9, h: 1.75, fontSize: 11, color: C.white, fontFace: "Calibri", valign: "top" });
});
// Signs
s.addText("Clinical Signs:", { x: 0.15, y: 3.42, w: 4.0, h: 0.35, fontSize: 13, bold: true, color: C.navy, fontFace: "Calibri" });
const signs = [
"Epigastric tenderness (mild, no guarding in uncomplicated)",
"Succussion splash → gastric outlet obstruction",
"Board-like rigidity → perforation",
"PR blood / melaena → GI bleed",
"No localising signs in most uncomplicated cases"
];
signs.forEach((sign, i) => {
const isWarning = sign.includes("→");
s.addShape("roundRect", { x: 0.15, y: 3.82 + i * 0.3, w: 9.7, h: 0.28, fill: { color: isWarning ? "FFF3E0" : "F8F8F8" }, rectRadius: 0.04, line: { color: isWarning ? C.orange : "CCCCCC", width: 0.5 } });
s.addText(`${isWarning ? "⚠" : "•"} ${sign}`, { x: 0.25, y: 3.82 + i * 0.3, w: 9.4, h: 0.28, fontSize: 11, color: isWarning ? C.orange : C.darkGray, fontFace: "Calibri", bold: isWarning, valign: "middle" });
});
// Additional features
s.addShape("roundRect", { x: 6.6, y: 3.42, w: 3.25, h: 0.9, fill: { color: C.navy }, rectRadius: 0.08 });
s.addText("Other Features\n• Weight loss (GU)\n• Anaemia (chronic bleed)\n• Periodicity of symptoms", { x: 6.6, y: 3.42, w: 3.25, h: 0.9, fontSize: 10.5, color: C.white, fontFace: "Calibri", valign: "middle", margin: 6 });
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 10 — INVESTIGATIONS FLOWCHART
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.gray);
addHeader(s, "Investigations – Step-by-Step Approach", true, C.navy, C.white);
// Flowchart boxes top to bottom
box(s, 3.5, 1.02, 3.0, 0.58, "SUSPECTED PUD\n(Symptoms + Risk Factors)", C.navy, C.white, 10.5, true);
// Arrow down
s.addShape("downArrow", { x: 4.7, y: 1.63, w: 0.6, h: 0.3, fill: { color: C.orange } });
box(s, 3.1, 1.96, 3.8, 0.52, "OGD (Gold Standard)\n+ Biopsy if GU", C.orange, C.white, 11, true);
// Arrow down
s.addShape("downArrow", { x: 4.7, y: 2.52, w: 0.6, h: 0.3, fill: { color: C.orange } });
box(s, 3.1, 2.85, 3.8, 0.52, "H. pylori Testing\n(CLO / Histology from biopsy)", C.teal, C.white, 11, true);
// Branch left and right
s.addShape("rightArrow", { x: 2.0, y: 3.07, w: 1.05, h: 0.28, fill: { color: C.teal } });
s.addShape("leftArrow", { x: 6.95, y: 3.07, w: 1.05, h: 0.28, fill: { color: C.teal } });
box(s, 0.15, 2.85, 1.8, 0.52, "If +ve\nEradicate", C.lime, C.white, 10, true);
box(s, 8.05, 2.85, 1.8, 0.52, "If -ve\nOther causes", "888888", C.white, 10, true);
// Supporting investigations
s.addText("Supporting Tests:", { x: 0.15, y: 3.6, w: 4.5, h: 0.35, fontSize: 12, bold: true, color: C.navy, fontFace: "Calibri" });
const suppTests = [
["Blood Tests", "FBC (anaemia), LFT, amylase (perforation)", C.teal],
["Erect CXR", "Free air under diaphragm → perforation (>50%)", C.orange],
["CT Abdomen", "Most accurate — perforation & pancreatitis", C.red],
["Barium Meal", "Less used — niche/unavailable OGD", "888888"],
["Serum Gastrin", "Fasting → Zollinger-Ellison syndrome", C.purple]
];
suppTests.forEach(([test, desc, col], i) => {
s.addShape("roundRect", { x: 0.15, y: 4.02 + i * 0.24, w: 1.85, h: 0.22, fill: { color: col }, rectRadius: 0.03 });
s.addText(test, { x: 0.15, y: 4.02 + i * 0.24, w: 1.85, h: 0.22, fontSize: 9.5, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(desc, { x: 2.05, y: 4.02 + i * 0.24, w: 7.7, h: 0.22, fontSize: 10, color: C.darkGray, fontFace: "Calibri", valign: "middle" });
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 11 — ENDOSCOPY IMAGE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.navy);
addHeader(s, "Endoscopic & Radiological Appearance", null, C.teal, C.white);
s.addText("GOLD STANDARD: Oesophago-gastro-duodenoscopy (OGD)", {
x: 0.15, y: 0.95, w: 9.7, h: 0.35, fontSize: 12, bold: true, color: C.orange, fontFace: "Calibri", align: "center"
});
// Left image: endoscopy
if (imgDuodenal) {
s.addImage({ data: imgDuodenal, x: 0.15, y: 1.35, w: 4.55, h: 3.4 });
} else {
s.addShape("rect", { x: 0.15, y: 1.35, w: 4.55, h: 3.4, fill: { color: "111111" } });
s.addText("Duodenal Ulcer (OGD)\n[Image from Bailey & Love]", { x: 0.15, y: 1.35, w: 4.55, h: 3.4, fontSize: 13, color: C.white, fontFace: "Calibri", align: "center", valign: "middle", italic: true });
}
s.addShape("roundRect", { x: 0.15, y: 4.78, w: 4.55, h: 0.42, fill: { color: C.teal }, rectRadius: 0.05 });
s.addText("Fig: Duodenal ulcer at gastroduodenoscopy\n(Courtesy Dr G.N.J. Tytgat, Amsterdam)", {
x: 0.15, y: 4.78, w: 4.55, h: 0.42, fontSize: 9, color: C.white, fontFace: "Calibri", align: "center", valign: "middle", italic: true
});
// Right image: barium
if (imgBarium) {
s.addImage({ data: imgBarium, x: 5.1, y: 1.35, w: 4.75, h: 3.4 });
} else {
s.addShape("rect", { x: 5.1, y: 1.35, w: 4.75, h: 3.4, fill: { color: "111111" } });
s.addText("Barium Meal\n[Image from Bailey & Love]", { x: 5.1, y: 1.35, w: 4.75, h: 3.4, fontSize: 13, color: C.white, fontFace: "Calibri", align: "center", valign: "middle", italic: true });
}
s.addShape("roundRect", { x: 5.1, y: 4.78, w: 4.75, h: 0.42, fill: { color: C.orange }, rectRadius: 0.05 });
s.addText("Fig: Duodenal ulcer shown by barium meal\n(Bailey & Love 28th Ed.)", {
x: 5.1, y: 4.78, w: 4.75, h: 0.42, fontSize: 9, color: C.white, fontFace: "Calibri", align: "center", valign: "middle", italic: true
});
addFooter(s, "Source: Bailey & Love's Short Practice of Surgery, 28th Ed. — Fig 67.10 & 67.11");
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 12 — MEDICAL MANAGEMENT FLOWCHART
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.gray);
addHeader(s, "Medical Management – Step-Up Approach", true, C.navy, C.white);
// Step boxes
const steps = [
{ label: "STEP 1", title: "Lifestyle Modification", items: ["Stop NSAIDs / aspirin", "Quit smoking & alcohol", "Avoid spicy foods", "Reduce stress"], col: C.teal },
{ label: "STEP 2", title: "Acid Suppression (PPI)", items: ["Omeprazole 20-40mg OD", "Lansoprazole 30mg OD", "Pantoprazole 40mg OD", "Duration: 4-8 weeks"], col: C.orange },
{ label: "STEP 3", title: "H. pylori Eradication", items: ["Triple therapy 7-14 days", "PPI + Amoxicillin + Clarithromycin", "OR PPI + Metronidazole + Clarithromycin", "Confirm eradication UBT"], col: C.red },
{ label: "STEP 4", title: "Follow-Up OGD (GU)", items: ["Repeat at 8 weeks GU", "Confirm healing", "Re-biopsy if non-healing", "Consider causes of failure"], col: C.navy }
];
steps.forEach((step, i) => {
const xPos = 0.15 + i * 2.45;
s.addShape("roundRect", { x: xPos, y: 1.0, w: 2.3, h: 4.2, fill: { color: step.col }, rectRadius: 0.1 });
s.addShape("roundRect", { x: xPos + 0.08, y: 1.05, w: 2.15, h: 0.4, fill: { color: "FFFFFF40" }, rectRadius: 0.06 });
s.addText(step.label, { x: xPos, y: 1.06, w: 2.3, h: 0.36, fontSize: 10, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(step.title, { x: xPos + 0.05, y: 1.5, w: 2.2, h: 0.52, fontSize: 11.5, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
step.items.forEach((item, j) => {
s.addText(`• ${item}`, { x: xPos + 0.1, y: 2.1 + j * 0.56, w: 2.1, h: 0.5, fontSize: 10, color: C.white, fontFace: "Calibri", valign: "top", wrap: true });
});
if (i < 3) {
s.addShape("rightArrow", { x: xPos + 2.32, y: 2.8, w: 0.1, h: 0.22, fill: { color: C.orange } });
}
});
// Triple therapy note
s.addShape("roundRect", { x: 0.15, y: 5.2, w: 9.7, h: 0.28, fill: { color: C.orange }, rectRadius: 0.04 });
s.addText("Triple Therapy eradication rate: ~80-90% | Confirm cure with UBT ≥4 weeks after stopping PPI & antibiotics", {
x: 0.15, y: 5.2, w: 9.7, h: 0.28, fontSize: 9.5, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle"
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 13 — H. PYLORI ERADICATION REGIMENS
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.cream);
addHeader(s, "H. pylori Eradication Therapy", true, C.orange, C.white);
// Triple therapy box
s.addShape("roundRect", { x: 0.15, y: 1.0, w: 4.65, h: 4.3, fill: { color: "FFF3E0" }, rectRadius: 0.12, line: { color: C.orange, width: 2 } });
s.addText("TRIPLE THERAPY (1st Line)", { x: 0.15, y: 1.0, w: 4.65, h: 0.48, fontSize: 13, bold: true, color: C.orange, fontFace: "Calibri", align: "center", valign: "middle" });
const triple = [
"PPI (standard dose) BD",
"+ Amoxicillin 1g BD",
"+ Clarithromycin 500mg BD",
"Duration: 7-14 days",
"OR: PPI + Metronidazole + Clarithromycin",
"(Use metronidazole if penicillin allergy)",
"Success: ~80-90%"
];
triple.forEach((t, i) => {
const isAnd = t.startsWith("+");
s.addShape("rect", { x: 0.3, y: 1.55 + i * 0.41, w: 0.15, h: 0.3, fill: { color: isAnd ? C.orange : C.teal } });
s.addText(t, { x: 0.52, y: 1.52 + i * 0.41, w: 4.2, h: 0.36, fontSize: 11.5, color: C.darkGray, fontFace: "Calibri", bold: isAnd, valign: "middle" });
});
// Quadruple therapy
s.addShape("roundRect", { x: 5.0, y: 1.0, w: 4.85, h: 2.15, fill: { color: "EBF5FB" }, rectRadius: 0.12, line: { color: C.navy, width: 2 } });
s.addText("QUADRUPLE THERAPY (2nd Line / Bismuth)", { x: 5.0, y: 1.0, w: 4.85, h: 0.48, fontSize: 11.5, bold: true, color: C.navy, fontFace: "Calibri", align: "center", valign: "middle" });
const quad = ["PPI BD", "+ Bismuth subcitrate QID", "+ Tetracycline 500mg QID", "+ Metronidazole 400mg TID", "Duration: 10-14 days", "Use: clarithromycin resistance / 2nd line"];
quad.forEach((q, i) => {
s.addText(`• ${q}`, { x: 5.1, y: 1.52 + i * 0.27, w: 4.6, h: 0.26, fontSize: 11, color: C.darkGray, fontFace: "Calibri" });
});
// Monitoring + Pitfalls
s.addShape("roundRect", { x: 5.0, y: 3.22, w: 4.85, h: 2.08, fill: { color: "FDEDEC" }, rectRadius: 0.12, line: { color: C.red, width: 2 } });
s.addText("⚠ Common Pitfalls", { x: 5.0, y: 3.22, w: 4.85, h: 0.42, fontSize: 12, bold: true, color: C.red, fontFace: "Calibri", align: "center", valign: "middle" });
const pitfalls = [
"Stop PPI 2 weeks before UBT (false negative)",
"Complete full antibiotic course",
"Rising clarithromycin resistance globally",
"Test & Treat strategy for dyspepsia <55 yrs",
"Always confirm eradication post-treatment"
];
pitfalls.forEach((p, i) => {
s.addText(`• ${p}`, { x: 5.1, y: 3.7 + i * 0.3, w: 4.6, h: 0.28, fontSize: 10.5, color: C.darkGray, fontFace: "Calibri" });
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 14 — COMPLICATIONS OVERVIEW
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.cream);
addHeader(s, "Complications of Peptic Ulcer Disease", true, C.red, C.white);
// Central complications wheel-like layout
s.addShape("roundRect", { x: 3.8, y: 2.0, w: 2.4, h: 1.0, fill: { color: C.navy }, rectRadius: 0.1 });
s.addText("PEPTIC ULCER\nCOMPLICATIONS", { x: 3.8, y: 2.0, w: 2.4, h: 1.0, fontSize: 11, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
const complications = [
{ name: "PERFORATION\n(Most dangerous)", col: C.red, x: 0.15, y: 1.0, icon: "💥" },
{ name: "HAEMORRHAGE\n(Most common)", col: C.orange, x: 7.7, y: 1.0, icon: "🩸" },
{ name: "PYLORIC STENOSIS\n(Chronic obstruction)", col: C.teal, x: 0.15, y: 3.6, icon: "🚫" },
{ name: "MALIGNANCY\n(GU — must exclude)", col: C.purple, x: 7.7, y: 3.6, icon: "☢" }
];
complications.forEach((comp, i) => {
s.addShape("roundRect", { x: comp.x, y: comp.y, w: 2.35, h: 1.05, fill: { color: comp.col }, rectRadius: 0.1 });
s.addText(comp.icon + "\n" + comp.name, { x: comp.x, y: comp.y, w: 2.35, h: 1.05, fontSize: 12, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
});
// Arrows from center to corners (simplified lines)
[[1.72, 1.5], [7.68, 1.5], [1.72, 3.6], [7.68, 3.6]].forEach(([ax, ay]) => {
s.addShape("rect", { x: ax, y: ay, w: 2.08, h: 0.04, fill: { color: "CCCCCC" } });
});
// Key points below
s.addShape("roundRect", { x: 0.15, y: 4.72, w: 9.7, h: 0.62, fill: { color: C.navy }, rectRadius: 0.06 });
s.addText(
"Perforation — 50%+ show free air on CXR | Bleeding — most common complication, UGIB | " +
"Stenosis — succussion splash, projectile vomiting | Malignancy — GU only",
{
x: 0.25, y: 4.72, w: 9.5, h: 0.62, fontSize: 10.5, color: C.white, fontFace: "Calibri",
align: "center", valign: "middle", wrap: true
}
);
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 15 — PERFORATION: CLINICAL FEATURES & MANAGEMENT
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, "FFF5F5");
addHeader(s, "Complication 1: Perforated Peptic Ulcer", true, C.red, C.white);
// Left: Clinical
s.addShape("roundRect", { x: 0.15, y: 1.0, w: 4.65, h: 2.35, fill: { color: "FDEDEC" }, rectRadius: 0.1, line: { color: C.red, width: 2 } });
s.addText("Clinical Features:", { x: 0.25, y: 1.05, w: 4.4, h: 0.38, fontSize: 13, bold: true, color: C.red, fontFace: "Calibri" });
const perfClinical = [
"Sudden-onset severe epigastric pain",
"Board-like rigidity of abdomen",
"Referred pain to shoulder (phrenic)",
"Shock: tachycardia, hypotension",
"Fever develops after few hours",
"Abdomen doesn't move with respiration",
"Elderly: may have atypical presentation"
];
perfClinical.forEach((p, i) => {
s.addText(`• ${p}`, { x: 0.28, y: 1.47 + i * 0.27, w: 4.45, h: 0.26, fontSize: 10.5, color: C.darkGray, fontFace: "Calibri" });
});
// Right: Management flowchart
s.addShape("roundRect", { x: 4.95, y: 1.0, w: 4.9, h: 2.35, fill: { color: "EBF5FB" }, rectRadius: 0.1, line: { color: C.navy, width: 2 } });
s.addText("Management:", { x: 5.05, y: 1.05, w: 4.7, h: 0.38, fontSize: 13, bold: true, color: C.navy, fontFace: "Calibri" });
const perfMgmt = [
"Resuscitation + IV fluids",
"Analgesia (do NOT withhold)",
"NGT + urinary catheter",
"Erect CXR → Free air?",
"CT abdomen (most accurate)",
"Serum amylase (rule out pancreatitis)",
"SURGERY: Laparotomy or laparoscopy"
];
perfMgmt.forEach((p, i) => {
s.addText(`${i + 1}. ${p}`, { x: 5.08, y: 1.47 + i * 0.27, w: 4.65, h: 0.26, fontSize: 10.5, color: C.darkGray, fontFace: "Calibri" });
});
// CXR image
if (imgCXR) {
s.addImage({ data: imgCXR, x: 0.15, y: 3.4, w: 4.0, h: 1.95 });
s.addShape("roundRect", { x: 0.15, y: 5.35, w: 4.0, h: 0.0, fill: { color: C.teal }, rectRadius: 0 });
} else {
s.addShape("rect", { x: 0.15, y: 3.4, w: 4.0, h: 1.95, fill: { color: "222222" } });
s.addText("Erect CXR: Free Air Under Diaphragm\n[Fig 67.22 — Bailey & Love]", { x: 0.15, y: 3.4, w: 4.0, h: 1.95, fontSize: 11, color: C.white, fontFace: "Calibri", align: "center", valign: "middle", italic: true });
}
s.addText("↑ Fig 67.22: Free air under R diaphragm — Perforated DU (Bailey & Love)", { x: 0.15, y: 5.32, w: 4.0, h: 0.2, fontSize: 8, color: C.teal, fontFace: "Calibri", italic: true, align: "center" });
// Surgical options
s.addShape("roundRect", { x: 4.25, y: 3.4, w: 5.6, h: 1.95, fill: { color: C.navy }, rectRadius: 0.1 });
s.addText("Surgical Options:", { x: 4.35, y: 3.42, w: 5.4, h: 0.38, fontSize: 12, bold: true, color: C.orange, fontFace: "Calibri" });
const surgOpts = [
"Closure + omental patch (Graham's patch) — DU",
"Excision + closure — GU (for histology)",
"Laparoscopic repair if expertise available",
"Distal gastrectomy (Roux-en-Y) — massive perf",
"Conservative: Bed rest + IV abs + NGT (selected)"
];
surgOpts.forEach((opt, i) => {
s.addText(`• ${opt}`, { x: 4.35, y: 3.85 + i * 0.28, w: 5.35, h: 0.26, fontSize: 10.5, color: C.white, fontFace: "Calibri" });
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 16 — GI HAEMORRHAGE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.cream);
addHeader(s, "Complication 2: Upper GI Haemorrhage", true, C.orange, C.white);
// Key facts bar
s.addShape("roundRect", { x: 0.15, y: 1.0, w: 9.7, h: 0.48, fill: { color: C.orange }, rectRadius: 0.06 });
s.addText("Incidence: >100/100,000/year | Mortality: 10-14% | Incidence ↑ with age | Associated with NSAIDs", {
x: 0.2, y: 1.0, w: 9.6, h: 0.48, fontSize: 11.5, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle"
});
// Left: Forrest Classification
s.addText("Forrest Classification (Endoscopic):", { x: 0.15, y: 1.57, w: 5.0, h: 0.35, fontSize: 12, bold: true, color: C.navy, fontFace: "Calibri" });
const forrest = [
["Ia", "Spurting arterial bleed", "55%", C.red],
["Ib", "Oozing arterial bleed", "55%", C.red],
["IIa", "Non-bleeding visible vessel", "43%", C.orange],
["IIb", "Adherent clot", "22%", C.yellow],
["IIc", "Haematin stained base", "10%", "888888"],
["III", "Clean based ulcer", "5%", C.lime]
];
s.addShape("rect", { x: 0.15, y: 1.95, w: 1.2, h: 0.3, fill: { color: C.navy } });
s.addText("Class", { x: 0.15, y: 1.95, w: 1.2, h: 0.3, fontSize: 10, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addShape("rect", { x: 1.38, y: 1.95, w: 2.8, h: 0.3, fill: { color: C.navy } });
s.addText("Description", { x: 1.38, y: 1.95, w: 2.8, h: 0.3, fontSize: 10, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addShape("rect", { x: 4.21, y: 1.95, w: 1.1, h: 0.3, fill: { color: C.navy } });
s.addText("Re-bleed", { x: 4.21, y: 1.95, w: 1.1, h: 0.3, fontSize: 10, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
forrest.forEach(([cls, desc, risk, col], i) => {
s.addShape("rect", { x: 0.15, y: 2.28 + i * 0.32, w: 1.2, h: 0.3, fill: { color: col } });
s.addText(cls, { x: 0.15, y: 2.28 + i * 0.32, w: 1.2, h: 0.3, fontSize: 10.5, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addShape("rect", { x: 1.38, y: 2.28 + i * 0.32, w: 2.8, h: 0.3, fill: { color: i % 2 === 0 ? "F8F8F8" : C.light } });
s.addText(desc, { x: 1.45, y: 2.28 + i * 0.32, w: 2.7, h: 0.3, fontSize: 10, color: C.darkGray, fontFace: "Calibri", valign: "middle" });
s.addShape("rect", { x: 4.21, y: 2.28 + i * 0.32, w: 1.1, h: 0.3, fill: { color: i % 2 === 0 ? "F8F8F8" : C.light } });
s.addText(risk, { x: 4.21, y: 2.28 + i * 0.32, w: 1.1, h: 0.3, fontSize: 10, bold: true, color: col === C.lime ? C.lime : col, fontFace: "Calibri", align: "center", valign: "middle" });
});
// Right: Management
s.addText("Management of UGIB:", { x: 5.5, y: 1.57, w: 4.35, h: 0.35, fontSize: 12, bold: true, color: C.navy, fontFace: "Calibri" });
const ugibMgmt = [
["Resuscitation", "IV access, fluids, blood", C.teal],
["IV PPI infusion", "High-dose omeprazole", C.orange],
["Urgent OGD", "Within 24 hrs (12 hrs if unstable)", C.red],
["Endoscopic Rx", "Adrenaline + clips/heater", C.purple],
["If fails", "Interventional radiology", "888888"],
["Last resort", "Surgery (underrunning/gastrectomy)", C.navy]
];
ugibMgmt.forEach(([step, detail, col], i) => {
s.addShape("roundRect", { x: 5.5, y: 1.98 + i * 0.5, w: 2.0, h: 0.44, fill: { color: col }, rectRadius: 0.04 });
s.addText(step, { x: 5.5, y: 1.98 + i * 0.5, w: 2.0, h: 0.44, fontSize: 10.5, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(detail, { x: 7.55, y: 2.02 + i * 0.5, w: 2.3, h: 0.36, fontSize: 10, color: C.darkGray, fontFace: "Calibri", italic: true, valign: "middle" });
if (i < 5) s.addShape("downArrow", { x: 6.28, y: 2.44 + i * 0.5, w: 0.44, h: 0.08, fill: { color: C.orange } });
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 17 — PYLORIC STENOSIS & ZE SYNDROME
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.cream);
addHeader(s, "Pyloric Stenosis & Zollinger-Ellison Syndrome", true, C.navy, C.white);
// Pyloric Stenosis
s.addShape("roundRect", { x: 0.15, y: 1.0, w: 4.65, h: 4.3, fill: { color: "E8F4F8" }, rectRadius: 0.12, line: { color: C.teal, width: 2 } });
s.addText("PYLORIC STENOSIS", { x: 0.15, y: 1.0, w: 4.65, h: 0.48, fontSize: 13, bold: true, color: C.teal, fontFace: "Calibri", align: "center", valign: "middle" });
const pyloric = [
["Cause:", "Fibrosis from chronic ulcer scarring"],
["Symptoms:", "Persistent vomiting (non-bilious)"],
["Classic sign:", "Succussion splash"],
["Pattern:", "Projectile vomiting of old food"],
["Metabolic:", "Hypokalaemic hypochloraemic alkalosis"],
["Investigation:", "OGD + barium meal"],
["Treatment:", "Resuscitate → Endoscopic dilation"],
["Surgery:", "Pyloroplasty / gastrojejunostomy"]
];
pyloric.forEach(([label, val], i) => {
s.addText(label, { x: 0.28, y: 1.55 + i * 0.38, w: 1.5, h: 0.34, fontSize: 11, bold: true, color: C.teal, fontFace: "Calibri", valign: "middle" });
s.addText(val, { x: 1.82, y: 1.55 + i * 0.38, w: 2.85, h: 0.34, fontSize: 11, color: C.darkGray, fontFace: "Calibri", valign: "middle" });
});
// ZE Syndrome
s.addShape("roundRect", { x: 5.0, y: 1.0, w: 4.85, h: 4.3, fill: { color: "F9EBF8" }, rectRadius: 0.12, line: { color: C.purple, width: 2 } });
s.addText("ZOLLINGER-ELLISON SYNDROME", { x: 5.0, y: 1.0, w: 4.85, h: 0.48, fontSize: 12, bold: true, color: C.purple, fontFace: "Calibri", align: "center", valign: "middle" });
const ze = [
["Cause:", "Gastrinoma (pancreas/duodenum)"],
["Pathology:", "↑↑ gastrin → ↑↑ acid → multiple ulcers"],
["Symptoms:", "Severe/refractory/multiple PUD"],
["Diarrhoea:", "Acid inactivates pancreatic enzymes"],
["Diagnosis:", "Fasting serum gastrin (>1000 pg/mL)"],
["Secretin test:", "Paradoxical ↑ gastrin"],
["Imaging:", "CT/MRI/octreotide scan"],
["Rx:", "High-dose PPIs + tumour resection"]
];
ze.forEach(([label, val], i) => {
s.addText(label, { x: 5.12, y: 1.55 + i * 0.38, w: 1.6, h: 0.34, fontSize: 11, bold: true, color: C.purple, fontFace: "Calibri", valign: "middle" });
s.addText(val, { x: 6.76, y: 1.55 + i * 0.38, w: 2.95, h: 0.34, fontSize: 11, color: C.darkGray, fontFace: "Calibri", valign: "middle" });
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 18 — SURGICAL MANAGEMENT
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.gray);
addHeader(s, "Surgical Management of PUD", true, C.navy, C.white);
// Indications box
s.addShape("roundRect", { x: 0.15, y: 1.0, w: 9.7, h: 0.62, fill: { color: C.red }, rectRadius: 0.08 });
s.addText("INDICATIONS FOR SURGERY: Perforation | Uncontrolled Haemorrhage | Malignancy (GU) | Gastric Outlet Obstruction | Failed Medical Therapy", {
x: 0.25, y: 1.0, w: 9.5, h: 0.62, fontSize: 11.5, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle", wrap: true
});
// Operations columns
const ops = [
{
title: "For DUODENAL ULCER", col: C.teal,
items: [
"Omental patch repair (perforation)",
"Truncal vagotomy + drainage",
"Highly selective vagotomy (HSV)",
"Billroth II / Pólya gastrectomy",
"Vagotomy: reduces acid by ~50%",
"Heineke-Mikulicz pyloroplasty",
"Elective surgery now rare (<1%)"
]
},
{
title: "For GASTRIC ULCER", col: C.orange,
items: [
"Always excise ulcer for histology",
"Billroth I (distal gastrectomy)",
"Roux-en-Y for massive perforation",
"Wedge excision + primary closure",
"Subtotal gastrectomy if malignant",
"Cannot distinguish benign vs cancer",
"Elective: very rarely performed now"
]
}
];
ops.forEach((op, i) => {
s.addShape("roundRect", { x: 0.15 + i * 4.95, y: 1.7, w: 4.7, h: 3.55, fill: { color: "FFFFFF" }, rectRadius: 0.1, line: { color: op.col, width: 2 } });
s.addShape("roundRect", { x: 0.15 + i * 4.95, y: 1.7, w: 4.7, h: 0.5, fill: { color: op.col }, rectRadius: 0.1 });
s.addText(op.title, { x: 0.15 + i * 4.95, y: 1.7, w: 4.7, h: 0.5, fontSize: 12.5, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
op.items.forEach((item, j) => {
s.addShape("circle", { x: 0.28 + i * 4.95, y: 2.27 + j * 0.42, w: 0.18, h: 0.18, fill: { color: op.col } });
s.addText(item, { x: 0.5 + i * 4.95, y: 2.24 + j * 0.42, w: 4.2, h: 0.36, fontSize: 11, color: C.darkGray, fontFace: "Calibri", valign: "middle" });
});
});
// Post-op sequelae
s.addShape("roundRect", { x: 0.15, y: 5.2, w: 9.7, h: 0.28, fill: { color: C.navy }, rectRadius: 0.04 });
s.addText("Post-op Sequelae: Dumping syndrome | Diarrhoea | Bilious vomiting | Small stomach | Malignant transformation (0.5%/yr)", {
x: 0.2, y: 5.2, w: 9.6, h: 0.28, fontSize: 9.5, bold: false, color: C.white, fontFace: "Calibri", align: "center", valign: "middle"
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 19 — DUMPING SYNDROME
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.cream);
addHeader(s, "Post-Surgical Sequelae – Dumping Syndrome", true, C.teal, C.white);
// Two boxes
const dumpTypes = [
{
type: "EARLY DUMPING\n(30 min after meal)",
col: C.orange,
mech: "Rapid gastric emptying → Osmotic shift\n→ Jejunum hyperosmolar → Fluid shift from blood",
features: ["Vasomotor: flushing, palpitations, sweating", "GI: diarrhoea, nausea, cramping", "Onset: 15-30 min after meal", "Lasts 1-2 hours"],
x: 0.15
},
{
type: "LATE DUMPING\n(2-3 hrs after meal)",
col: C.teal,
mech: "Rapid glucose absorption → ↑↑ insulin\n→ Reactive hypoglycaemia",
features: ["Sweating, tremor, faintness", "Hunger, weakness, confusion", "Onset: 2-3 hours post meal", "Relieved by sugar intake"],
x: 5.1
}
];
dumpTypes.forEach((dt) => {
s.addShape("roundRect", { x: dt.x, y: 1.0, w: 4.75, h: 4.3, fill: { color: "FAFAFA" }, rectRadius: 0.12, line: { color: dt.col, width: 2 } });
s.addShape("roundRect", { x: dt.x, y: 1.0, w: 4.75, h: 0.52, fill: { color: dt.col }, rectRadius: 0.1 });
s.addText(dt.type, { x: dt.x, y: 1.0, w: 4.75, h: 0.52, fontSize: 12.5, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText("Mechanism:", { x: dt.x + 0.12, y: 1.57, w: 1.4, h: 0.3, fontSize: 11, bold: true, color: dt.col, fontFace: "Calibri" });
s.addText(dt.mech, { x: dt.x + 0.12, y: 1.87, w: 4.5, h: 0.72, fontSize: 10.5, color: C.darkGray, fontFace: "Calibri", wrap: true });
s.addText("Features:", { x: dt.x + 0.12, y: 2.65, w: 1.2, h: 0.3, fontSize: 11, bold: true, color: dt.col, fontFace: "Calibri" });
dt.features.forEach((f, j) => {
s.addText(`• ${f}`, { x: dt.x + 0.12, y: 2.98 + j * 0.3, w: 4.5, h: 0.28, fontSize: 11, color: C.darkGray, fontFace: "Calibri" });
});
});
// Management at bottom
s.addShape("roundRect", { x: 0.15, y: 5.35, w: 9.7, h: 0.22, fill: { color: C.navy }, rectRadius: 0.04 });
s.addText("Management: Small frequent meals | Low carb, high protein | Lie down after meals | Octreotide (severe) | Surgical revision (rare)", {
x: 0.2, y: 5.35, w: 9.6, h: 0.22, fontSize: 9, bold: false, color: C.white, fontFace: "Calibri", align: "center", valign: "middle"
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 20 — COMPLETE MANAGEMENT ALGORITHM
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.gray);
addHeader(s, "Complete Management Algorithm – PUD", true, C.navy, C.white);
// Flowchart
box(s, 3.7, 1.02, 2.6, 0.52, "Patient with Epigastric Pain", C.navy, C.white, 10.5, true);
s.addShape("downArrow", { x: 4.72, y: 1.57, w: 0.56, h: 0.28, fill: { color: C.orange } });
box(s, 3.4, 1.88, 3.2, 0.48, "Age < 55, no alarm features?", C.teal, C.white, 10.5, true);
// Branch left (Yes) and right (No)
s.addShape("leftArrow", { x: 2.05, y: 2.06, w: 1.32, h: 0.3, fill: { color: C.lime } });
s.addShape("rightArrow", { x: 6.63, y: 2.06, w: 1.32, h: 0.3, fill: { color: C.red } });
s.addText("YES", { x: 2.05, y: 1.96, w: 1.32, h: 0.22, fontSize: 9, bold: true, color: C.lime, fontFace: "Calibri", align: "center" });
s.addText("NO / ALARM", { x: 6.63, y: 1.96, w: 1.32, h: 0.22, fontSize: 9, bold: true, color: C.red, fontFace: "Calibri", align: "center" });
box(s, 0.15, 1.88, 1.85, 0.48, "Test & Treat\nH. pylori", C.lime, C.white, 10, true);
box(s, 8.0, 1.88, 1.85, 0.48, "Urgent OGD\n+ Biopsy", C.red, C.white, 10, true);
// From Test & Treat → down
s.addShape("downArrow", { x: 0.78, y: 2.4, w: 0.44, h: 0.28, fill: { color: C.lime } });
box(s, 0.15, 2.7, 1.85, 0.48, "Positive?\nEradicate", C.orange, C.white, 10, true);
s.addShape("downArrow", { x: 0.78, y: 3.22, w: 0.44, h: 0.28, fill: { color: C.orange } });
box(s, 0.15, 3.52, 1.85, 0.48, "Confirm cure\n(UBT 4-6 wk)", C.teal, C.white, 10, true);
// From OGD → PUD confirmed
s.addShape("downArrow", { x: 8.65, y: 2.4, w: 0.44, h: 0.28, fill: { color: C.red } });
box(s, 7.95, 2.7, 2.0, 0.48, "PUD confirmed\n+/- H. pylori", C.navy, C.white, 10, true);
s.addShape("downArrow", { x: 8.65, y: 3.22, w: 0.44, h: 0.28, fill: { color: C.navy } });
box(s, 7.95, 3.52, 2.0, 0.48, "PPI + Eradicate\n+ Stop NSAIDs", C.orange, C.white, 10, true);
// Centre bottom: Complications
s.addShape("downArrow", { x: 4.72, y: 2.4, w: 0.56, h: 0.28, fill: { color: C.teal } });
box(s, 3.4, 2.7, 3.2, 0.48, "Complications\nPresent?", C.red, C.white, 10.5, true);
s.addShape("downArrow", { x: 4.72, y: 3.22, w: 0.56, h: 0.28, fill: { color: C.red } });
const compBoxes = [
["Perforation\n→ Surgery", C.red, 2.75],
["Bleeding\n→ OGD Rx", C.orange, 4.0],
["Stenosis\n→ Dilate/Op", C.teal, 5.25],
["Malignancy\n→ Refer", C.purple, 6.5]
];
compBoxes.forEach(([txt, col, xp]) => {
box(s, xp, 3.52, 1.15, 0.55, txt, col, C.white, 9, true);
});
s.addShape("roundRect", { x: 0.15, y: 4.15, w: 9.7, h: 0.32, fill: { color: C.navy }, rectRadius: 0.04 });
s.addText("Alarm Features: Age >55, Dysphagia, Weight loss, Anaemia, Haematemesis, Palpable mass, Vomiting", {
x: 0.2, y: 4.15, w: 9.6, h: 0.32, fontSize: 10, bold: false, color: C.white, fontFace: "Calibri", align: "center", valign: "middle"
});
// NSAID prevention
s.addShape("roundRect", { x: 0.15, y: 4.52, w: 9.7, h: 0.52, fill: { color: "FFF3E0" }, rectRadius: 0.06, line: { color: C.orange, width: 1 } });
s.addText("⚠ NSAID Users: Add PPI co-prescription | Use COX-2 inhibitor if high risk | Consider H. pylori test before starting NSAIDs", {
x: 0.2, y: 4.52, w: 9.6, h: 0.52, fontSize: 10.5, color: C.darkGray, fontFace: "Calibri", align: "center", valign: "middle", wrap: true
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 21 — MCQ INTERACTIVE 1
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.navy);
addHeader(s, "Interactive MCQ — Test Yourself!", null, C.orange, C.white);
const mcqs = [
{
q: "Q1. Most common site of peptic ulcer perforation:",
opts: ["A. Lesser curve of stomach", "B. 1st part duodenum (anterior wall)", "C. Prepyloric", "D. 2nd part duodenum"],
ans: "B",
col: C.teal
},
{
q: "Q2. Drug of choice for H. pylori eradication:",
opts: ["A. H2 blockers + amoxicillin", "B. PPI + clarithromycin + amoxicillin", "C. Antacids alone", "D. Sucralfate + tetracycline"],
ans: "B",
col: C.orange
},
{
q: "Q3. Which test BEST confirms H. pylori eradication?",
opts: ["A. Serology IgG", "B. CLO test", "C. Urea Breath Test (UBT)", "D. Stool culture"],
ans: "C",
col: C.purple
},
{
q: "Q4. Metabolic abnormality in pyloric stenosis:",
opts: ["A. Hypokalaemic hyperchloraemic acidosis", "B. Hyperkalaemic alkalosis", "C. Hypokalaemic hypochloraemic alkalosis", "D. Normal electrolytes"],
ans: "C",
col: C.red
}
];
mcqs.forEach((mcq, i) => {
const yBase = 1.02 + i * 1.15;
s.addText(mcq.q, { x: 0.2, y: yBase, w: 9.6, h: 0.3, fontSize: 12, bold: true, color: C.orange, fontFace: "Calibri" });
mcq.opts.forEach((opt, j) => {
const isAns = opt.startsWith(mcq.ans);
s.addShape("roundRect", { x: 0.2 + (j % 2) * 4.85, y: yBase + 0.33 + Math.floor(j / 2) * 0.38, w: 4.65, h: 0.34, fill: { color: isAns ? "002800" : "0A2240" }, rectRadius: 0.05, line: { color: isAns ? C.lime : "1A7A8A", width: 1 } });
s.addText(opt, { x: 0.28 + (j % 2) * 4.85, y: yBase + 0.33 + Math.floor(j / 2) * 0.38, w: 4.5, h: 0.34, fontSize: 10.5, color: isAns ? C.lime : C.light, fontFace: "Calibri", valign: "middle" });
});
});
addFooter(s, "Answers highlighted in green — Discuss with faculty");
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 22 — SPECIAL SITUATIONS
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.cream);
addHeader(s, "Special Situations in PUD", true, C.teal, C.white);
const specials = [
{
title: "PUD in Elderly", col: C.orange, icon: "👴",
points: ["NSAIDs most common cause", "Atypical presentation", "Higher complication rate", "Fewer symptoms — 'silent' bleed", "Perforations often in females"]
},
{
title: "PUD in Pregnancy", col: C.purple, icon: "🤱",
points: ["H2 blockers preferred", "PPIs: use with caution", "Avoid clarithromycin", "Lifestyle modification first", "Metronidazole safe in 2nd/3rd trimester"]
},
{
title: "PUD + Anticoagulation", col: C.red, icon: "💊",
points: ["High risk of UGIB", "Reverse anticoagulation (bleed)", "Early OGD mandatory", "PPI co-prescription essential", "H. pylori test & treat before starting"]
},
{
title: "NSAID-induced PUD", col: C.teal, icon: "💉",
points: ["Inhibit COX-1 → ↓ PGE2 → ↓ mucus", "Use lowest effective dose", "Use COX-2 selective if needed", "Add PPI in high-risk patients", "H. pylori test before starting NSAIDs"]
}
];
specials.forEach((sp, i) => {
const xPos = 0.15 + (i % 2) * 4.9;
const yPos = 1.0 + Math.floor(i / 2) * 2.25;
s.addShape("roundRect", { x: xPos, y: yPos, w: 4.65, h: 2.15, fill: { color: "FFFFFF" }, rectRadius: 0.1, line: { color: sp.col, width: 2 } });
s.addShape("roundRect", { x: xPos, y: yPos, w: 4.65, h: 0.5, fill: { color: sp.col }, rectRadius: 0.1 });
s.addText(`${sp.icon} ${sp.title}`, { x: xPos, y: yPos, w: 4.65, h: 0.5, fontSize: 12.5, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
sp.points.forEach((pt, j) => {
s.addText(`• ${pt}`, { x: xPos + 0.12, y: yPos + 0.55 + j * 0.31, w: 4.4, h: 0.28, fontSize: 11, color: C.darkGray, fontFace: "Calibri" });
});
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 23 — PREVENTION & NSAID SAFETY
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.cream);
addHeader(s, "Prevention Strategies for PUD", true, C.lime, C.white);
// Primary prevention
s.addShape("roundRect", { x: 0.15, y: 1.0, w: 9.7, h: 0.52, fill: { color: C.lime }, rectRadius: 0.08 });
s.addText("PRIMARY PREVENTION", { x: 0.15, y: 1.0, w: 9.7, h: 0.52, fontSize: 14, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
const primPrev = [
["H. pylori Test & Treat", "For all PUD, dyspepsia <55 yrs without alarm features", C.teal],
["Minimize NSAIDs", "Use lowest effective dose for shortest duration", C.orange],
["PPI Co-prescription", "Mandatory in NSAID users with risk factors", C.red],
["Quit Smoking", "Doubles relapse rate; impairs healing", "5D4037"],
["Limit Alcohol", "Damages mucosal barrier; synergistic with NSAIDs", C.purple]
];
primPrev.forEach(([strat, detail, col], i) => {
s.addShape("roundRect", { x: 0.15, y: 1.58 + i * 0.5, w: 3.0, h: 0.44, fill: { color: col }, rectRadius: 0.06 });
s.addText(strat, { x: 0.15, y: 1.58 + i * 0.5, w: 3.0, h: 0.44, fontSize: 11.5, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(detail, { x: 3.2, y: 1.62 + i * 0.5, w: 6.6, h: 0.38, fontSize: 11, color: C.darkGray, fontFace: "Calibri", italic: false, valign: "middle" });
});
// NSAID risk stratification
s.addText("NSAID Risk Stratification:", { x: 0.15, y: 4.12, w: 5.0, h: 0.38, fontSize: 12, bold: true, color: C.navy, fontFace: "Calibri" });
s.addShape("roundRect", { x: 0.15, y: 4.5, w: 9.7, h: 0.88, fill: { color: "F8F9FA" }, rectRadius: 0.08, line: { color: "CCCCCC", width: 1 } });
const riskLevels = [
["LOW RISK\n(NSAID alone)", C.lime, "No co-prescription"],
["MODERATE RISK\n(Age >65 or H.pylori +ve)", C.yellow, "PPI co-prescription"],
["HIGH RISK\n(Prior PUD / anticoagulant)", C.red, "PPI + COX-2 inhibitor"]
];
riskLevels.forEach(([level, col, action], i) => {
box(s, 0.25 + i * 3.22, 4.55, 3.05, 0.76, level + "\n→ " + action, col, i === 1 ? C.darkGray : C.white, 10, true);
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 24 — CLOSING CASE DISCUSSION
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, "FFF8F0");
addHeader(s, "Closing Case Discussion – Apply Your Knowledge!", null, C.red, C.white);
// Case 2 box
s.addShape("roundRect", { x: 0.15, y: 0.95, w: 9.7, h: 2.3, fill: { color: C.navy }, rectRadius: 0.12 });
s.addText("CASE 2", { x: 0.25, y: 0.98, w: 1.8, h: 0.38, fontSize: 11, bold: true, color: C.orange, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(
"Sunita, 60-year-old female, on diclofenac for arthritis and aspirin for cardiac disease, presents with " +
"sudden-onset severe central abdominal pain, followed by shoulder tip pain. She is pale, tachycardic " +
"(HR 120), hypotensive (BP 90/60). Abdomen is rigid, not moving with respiration. CXR shows free air " +
"under right diaphragm.",
{
x: 0.25, y: 1.4, w: 9.4, h: 1.75,
fontSize: 13, color: C.white, fontFace: "Calibri", align: "left", valign: "top", wrap: true
}
);
// Discussion Questions
s.addText("Clinical Discussion (Group Activity — 10 mins):", { x: 0.15, y: 3.32, w: 9.0, h: 0.38, fontSize: 13.5, bold: true, color: C.navy, fontFace: "Calibri" });
const dqs = [
{ num: "Q1", q: "What is the diagnosis? What caused it?", hint: "Think: NSAIDs + aspirin combination risk", col: C.teal },
{ num: "Q2", q: "How would you resuscitate this patient?", hint: "ABC approach — fluids, catheter, NGT, analgesia", col: C.orange },
{ num: "Q3", q: "What operation would you perform and why?", hint: "Graham's patch vs excision — DU vs GU rule", col: C.red },
{ num: "Q4", q: "What post-op medical treatment is essential?", hint: "PPIs, H. pylori eradication, stop NSAIDs", col: C.purple }
];
dqs.forEach((dq, i) => {
const xPos = 0.15 + (i % 2) * 4.9;
const yPos = 3.75 + Math.floor(i / 2) * 0.75;
s.addShape("roundRect", { x: xPos, y: yPos, w: 4.65, h: 0.68, fill: { color: dq.col }, rectRadius: 0.08 });
s.addText(dq.num, { x: xPos + 0.07, y: yPos, w: 0.55, h: 0.68, fontSize: 13, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(dq.q, { x: xPos + 0.65, y: yPos + 0.02, w: 3.9, h: 0.38, fontSize: 11, bold: true, color: C.white, fontFace: "Calibri", valign: "top" });
s.addText(`💡 ${dq.hint}`, { x: xPos + 0.65, y: yPos + 0.4, w: 3.9, h: 0.26, fontSize: 9.5, color: "FFEAA7", fontFace: "Calibri", italic: true });
});
addFooter(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 25 — SUMMARY & TAKE-HOME MESSAGES
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
addSlideBg(s, C.navy);
addHeader(s, "Summary & Take-Home Messages", null, C.orange, C.white);
// Left column
s.addShape("roundRect", { x: 0.15, y: 0.96, w: 4.7, h: 4.52, fill: { color: "0A2240" }, rectRadius: 0.1 });
s.addText("KEY MESSAGES", { x: 0.15, y: 0.96, w: 4.7, h: 0.42, fontSize: 13, bold: true, color: C.orange, fontFace: "Calibri", align: "center", valign: "middle" });
const msgs = [
"No acid = no ulcer (PPIs cornerstone)",
"H. pylori + NSAIDs = >90% of PUD",
"Always biopsy ALL gastric ulcers",
"Triple therapy: PPI + 2 antibiotics",
"Confirm eradication with UBT",
"Free gas on CXR = perforation until proven otherwise",
"Forrest Ia/Ib = urgent endoscopy",
"Succussion splash = pyloric stenosis",
"Surgery now rare — reserved for complications",
"ZE syndrome: think with multiple/refractory ulcers"
];
msgs.forEach((msg, i) => {
s.addShape("circle", { x: 0.28, y: 1.44 + i * 0.38, w: 0.22, h: 0.22, fill: { color: C.orange } });
s.addText(`${i + 1}`, { x: 0.28, y: 1.44 + i * 0.38, w: 0.22, h: 0.22, fontSize: 8.5, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(msg, { x: 0.56, y: 1.42 + i * 0.38, w: 4.2, h: 0.34, fontSize: 11, color: C.light, fontFace: "Calibri", valign: "middle" });
});
// Right: Peer review checklist alignment
s.addShape("roundRect", { x: 5.0, y: 0.96, w: 4.85, h: 3.0, fill: { color: "0A2240" }, rectRadius: 0.1 });
s.addText("PEER REVIEW ALIGNMENT", { x: 5.0, y: 0.96, w: 4.85, h: 0.42, fontSize: 12, bold: true, color: C.teal, fontFace: "Calibri", align: "center", valign: "middle" });
const criteria = [
["Interest Arousal", "Opening case vignette", C.lime],
["Objectives Stated", "Slide 2 — structured", C.lime],
["Logical Sequence", "Basic → Advanced", C.lime],
["Relevant Content", "Bailey & Love based", C.lime],
["Examples Used", "Case 1 & Case 2", C.lime],
["Audio-Visual Aids", "Images + flowcharts", C.lime],
["Questions Asked", "MCQs + discussion", C.lime],
["Summary Provided", "This slide!", C.lime]
];
criteria.forEach(([crit, note, col], i) => {
s.addShape("roundRect", { x: 5.1, y: 1.42 + i * 0.3, w: 2.4, h: 0.26, fill: { color: "112244" }, rectRadius: 0.03 });
s.addText(crit, { x: 5.1, y: 1.42 + i * 0.3, w: 2.4, h: 0.26, fontSize: 9.5, color: C.light, fontFace: "Calibri", valign: "middle", margin: 4 });
s.addShape("roundRect", { x: 7.55, y: 1.42 + i * 0.3, w: 0.35, h: 0.26, fill: { color: col }, rectRadius: 0.04 });
s.addText("✓", { x: 7.55, y: 1.42 + i * 0.3, w: 0.35, h: 0.26, fontSize: 11, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(note, { x: 7.94, y: 1.42 + i * 0.3, w: 1.88, h: 0.26, fontSize: 9, color: C.light, fontFace: "Calibri", italic: true, valign: "middle" });
});
// Bailey & Love citation
s.addShape("roundRect", { x: 5.0, y: 4.02, w: 4.85, h: 1.44, fill: { color: "0A2240" }, rectRadius: 0.1 });
s.addText("REFERENCES & CITATION", { x: 5.0, y: 4.02, w: 4.85, h: 0.38, fontSize: 11, bold: true, color: C.orange, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(
"• Bailey & Love's Short Practice of Surgery, 28th Ed.\n Williams NS, O'Connell PR, McCaskie AW, 2023\n• Robbins & Kumar Basic Pathology\n• WHO H. pylori Guidelines 2022",
{ x: 5.1, y: 4.42, w: 4.65, h: 1.0, fontSize: 9.5, color: C.light, fontFace: "Calibri", italic: true, valign: "top", wrap: true }
);
// Thank you
s.addShape("roundRect", { x: 0.15, y: 5.22, w: 9.7, h: 0.32, fill: { color: C.orange }, rectRadius: 0.04 });
s.addText("Thank You! — Questions? Doubts? Discuss with your faculty 🎓", {
x: 0.2, y: 5.22, w: 9.6, h: 0.32, fontSize: 12, bold: true, color: C.navy, fontFace: "Calibri", align: "center", valign: "middle"
});
addFooter(s, "Bailey & Love's Short Practice of Surgery 28th Ed. | For Educational Use Only | MBBS Surgery");
}
// ─── SAVE ─────────────────────────────────────────────────────────────────
pres.writeFile({ fileName: "/home/daytona/workspace/peptic-ulcer-ppt/PUD_Bailey_Love_MBBS.pptx" })
.then(() => console.log("✅ Presentation saved successfully!"))
.catch(err => console.error("❌ Save error:", err));
cd /home/daytona/workspace/peptic-ulcer-ppt && node create_ppt.js 2>&1
ls -lh /home/daytona/workspace/peptic-ulcer-ppt/PUD_Bailey_Love_MBBS.pptx
~/peptic-ulcer-ppt/create_ppt.js
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/peptic-ulcer-ppt/create_ppt.js'
cd /home/daytona/workspace/peptic-ulcer-ppt && node create_ppt.js 2>&1
cd /home/daytona/workspace/peptic-ulcer-ppt && python3 -c " from pptx import Pre…
cd /home/daytona/workspace/peptic-ulcer-ppt && node -e " const pptxgen = require…
PUD Bailey Love MBBS
Presentation · PPTX
| # | Slide | Type |
|---|---|---|
| 1 | Title Slide | Cover |
| 2 | Learning Objectives + Session Structure (60 min) | Framework |
| 3 | Opening Case Vignette — Raju (35M, smoker, NSAID user) | Case 1 |
| 4 | Definition & Anatomy (common sites, key rules) | Content |
| 5 | Aetiology Flowchart (H. pylori, NSAIDs, ZE, stress) | Flowchart |
| 6 | Pathophysiology — Aggressive vs Defensive Balance | Diagram |
| 7 | H. pylori — Virulence factors, Diagnosis methods | Content |
| 8 | DU vs GU Comparison Table | Comparison |
| 9 | Clinical Features (symptoms + signs) | Content |
| 10 | Investigations Step-by-Step Flowchart | Flowchart |
| 11 | Real Endoscopy + Barium Meal Images (Bailey & Love Fig 67.10, 67.11) | Images |
| 12 | Medical Management Step-Up Flowchart | Flowchart |
| 13 | H. pylori Eradication Regimens (Triple + Quadruple) | Content |
| 14 | Complications Overview (4 big ones) | Diagram |
| 15 | Perforated PUD — Features, Management + CXR image (Fig 67.22) | Images |
| 16 | UGIB — Forrest Classification + Management Ladder | Content |
| 17 | Pyloric Stenosis + ZE Syndrome | Special topics |
| 18 | Surgical Management (Indications + Operations) | Content |
| 19 | Post-surgical Sequelae — Dumping Syndrome | Content |
| 20 | Complete Management Algorithm (full flowchart) | Flowchart |
| 21 | Interactive MCQs (4 questions with highlighted answers) | Interactive |
| 22 | Special Situations (Elderly, Pregnancy, Anticoagulation, NSAIDs) | Content |
| 23 | Prevention Strategies + NSAID Risk Stratification | Content |
| 24 | Closing Case Discussion — Sunita (60F, perforated PUD) | Case 2 |
| 25 | Summary + Take-Home Messages + Peer Review Checklist | Closure |
Can u make the slide template white background and only two colour tone
~/peptic-ulcer-ppt/create_ppt_v2.js
const pptxgen = require("pptxgenjs");
const { execSync } = require("child_process");
// ─── FETCH IMAGES ──────────────────────────────────────────────────────────
const imageUrls = [
"https://cdn.orris.care/cdss_images/9b8c9b80815ac3526d6c02271dd7a0ea8b3a0d054a5db153ca8b9827c1b8fb42.png",
"https://cdn.orris.care/cdss_images/675c6b1515e8f1b218a165f8bee0054477bcedf899e353e0883df93d04bf5587.png",
"https://cdn.orris.care/cdss_images/ec56874995d0dbd5dae7706865ecb332a07f6afd474a8fe534c6d384e4ed95bb.png"
];
let imgDuodenal = "", imgBarium = "", imgCXR = "";
try {
const raw = execSync(
`node /home/daytona/skills/shared/scripts/fetch_images.js "${imageUrls[0]}" "${imageUrls[1]}" "${imageUrls[2]}"`,
{ maxBuffer: 50 * 1024 * 1024 }
).toString();
const imgs = JSON.parse(raw);
imgDuodenal = imgs[0] && !imgs[0].error ? imgs[0].base64 : "";
imgBarium = imgs[1] && !imgs[1].error ? imgs[1].base64 : "";
imgCXR = imgs[2] && !imgs[2].error ? imgs[2].base64 : "";
} catch(e) { console.error("Image fetch error:", e.message); }
// ─── TWO-TONE PALETTE: NAVY + WHITE ────────────────────────────────────────
const N = "0D2B4E"; // Navy — primary accent
const W = "FFFFFF"; // White — background
const NL = "1A4A78"; // Navy light — secondary accent
const NT = "E8EEF5"; // Navy tint — very pale navy for alternate rows / fills
const NG = "6B8DB2"; // Navy grey — subdued text / borders
const TXT = "1A1A2E"; // Near-black text on white backgrounds
// ─── HELPERS ───────────────────────────────────────────────────────────────
const pres = new pptxgen();
pres.layout = "LAYOUT_16x9";
pres.author = "Dept of Surgery";
pres.title = "Peptic Ulcer Disease";
/** White background for every content slide */
function whiteBg(slide) {
slide.addShape("rect", { x: 0, y: 0, w: "100%", h: "100%", fill: { color: W } });
}
/**
* Standard slide header: full-width navy bar at top,
* with a thin accent underline
*/
function header(slide, title) {
// Navy header bar
slide.addShape("rect", { x: 0, y: 0, w: "100%", h: 0.78, fill: { color: N } });
// Thin bottom accent line
slide.addShape("rect", { x: 0, y: 0.78, w: "100%", h: 0.06, fill: { color: NL } });
slide.addText(title, {
x: 0.18, y: 0.06, w: 9.64, h: 0.68,
fontSize: 20, bold: true, color: W,
fontFace: "Calibri", align: "left", valign: "middle", margin: 0
});
}
/**
* Footer: slim navy bar at very bottom
*/
function footer(slide, note) {
note = note || "Source: Bailey & Love's Short Practice of Surgery, 28th Ed.";
slide.addShape("rect", { x: 0, y: 5.38, w: "100%", h: 0.24, fill: { color: N } });
slide.addText(note, {
x: 0.18, y: 5.38, w: 9.64, h: 0.24,
fontSize: 7.5, color: NT, fontFace: "Calibri",
italic: true, align: "left", valign: "middle"
});
}
/**
* Solid navy rounded box with white text
*/
function navyBox(slide, x, y, w, h, text, fontSize, bold, radius) {
radius = radius !== undefined ? radius : 0.07;
slide.addShape("roundRect", {
x, y, w, h,
fill: { color: N },
line: { color: N, width: 0 },
rectRadius: radius
});
slide.addText(text, {
x, y, w, h,
fontSize: fontSize || 11,
bold: bold !== undefined ? bold : true,
color: W, fontFace: "Calibri",
align: "center", valign: "middle", wrap: true
});
}
/**
* Outlined navy box (white fill, navy border + navy text)
*/
function outlineBox(slide, x, y, w, h, text, fontSize, bold) {
slide.addShape("roundRect", {
x, y, w, h,
fill: { color: W },
line: { color: N, width: 1.5 },
rectRadius: 0.07
});
slide.addText(text, {
x, y, w, h,
fontSize: fontSize || 11,
bold: bold !== undefined ? bold : false,
color: N, fontFace: "Calibri",
align: "center", valign: "middle", wrap: true
});
}
/**
* Tint box (very pale navy fill, navy text)
*/
function tintBox(slide, x, y, w, h, text, fontSize, bold) {
slide.addShape("roundRect", {
x, y, w, h,
fill: { color: NT },
line: { color: N, width: 1 },
rectRadius: 0.07
});
slide.addText(text, {
x, y, w, h,
fontSize: fontSize || 11,
bold: bold !== undefined ? bold : false,
color: N, fontFace: "Calibri",
align: "center", valign: "middle", wrap: true
});
}
/** Down arrow in navy */
function downArrow(slide, cx, y) {
slide.addShape("downArrow", { x: cx - 0.14, y, w: 0.28, h: 0.28, fill: { color: N } });
}
/** Right arrow in navy */
function rightArrow(slide, x, cy) {
slide.addShape("rightArrow", { x, y: cy - 0.12, w: 0.28, h: 0.24, fill: { color: N } });
}
/** Left arrow in navy */
function leftArrow(slide, x, cy) {
slide.addShape("leftArrow", { x, y: cy - 0.12, w: 0.28, h: 0.24, fill: { color: N } });
}
/** Section divider line */
function divider(slide, y) {
slide.addShape("rect", { x: 0.18, y, w: 9.64, h: 0.03, fill: { color: NT } });
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 1 — TITLE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
// Full white background
s.addShape("rect", { x: 0, y: 0, w: "100%", h: "100%", fill: { color: W } });
// Left navy panel (40% of width)
s.addShape("rect", { x: 0, y: 0, w: 4.2, h: "100%", fill: { color: N } });
// Thin accent stripe
s.addShape("rect", { x: 4.2, y: 0, w: 0.08, h: "100%", fill: { color: NL } });
// Left panel content
s.addText("PEPTIC\nULCER\nDISEASE", {
x: 0.25, y: 0.9, w: 3.7, h: 2.5,
fontSize: 38, bold: true, color: W,
fontFace: "Calibri", align: "left", valign: "middle", lineSpacingMultiple: 1.1
});
s.addShape("rect", { x: 0.25, y: 3.55, w: 3.5, h: 0.05, fill: { color: NL } });
s.addText("An Interactive Case-Based Session", {
x: 0.25, y: 3.68, w: 3.7, h: 0.42,
fontSize: 13, color: NT, fontFace: "Calibri", italic: true
});
s.addText("For MBBS Students | Surgery | 60 Minutes", {
x: 0.25, y: 4.15, w: 3.7, h: 0.35,
fontSize: 11, color: NG, fontFace: "Calibri"
});
s.addText("Bailey & Love, 28th Ed.", {
x: 0.25, y: 4.55, w: 3.7, h: 0.35,
fontSize: 11, color: NG, fontFace: "Calibri", italic: true
});
// Right panel — topics
s.addText("TOPICS COVERED", {
x: 4.55, y: 0.55, w: 5.2, h: 0.45,
fontSize: 13, bold: true, color: N, fontFace: "Calibri", charSpacing: 2
});
s.addShape("rect", { x: 4.55, y: 1.0, w: 5.2, h: 0.03, fill: { color: NT } });
const topics = [
"1. Anatomy & Pathophysiology",
"2. Aetiology & Risk Factors",
"3. Clinical Features",
"4. Investigations",
"5. Medical Management",
"6. Complications",
"7. Surgical Management",
"8. Case-Based Discussion"
];
topics.forEach((t, i) => {
s.addText(t, {
x: 4.55, y: 1.1 + i * 0.52, w: 5.2, h: 0.46,
fontSize: 13, color: TXT, fontFace: "Calibri", valign: "middle"
});
if (i < topics.length - 1)
s.addShape("rect", { x: 4.55, y: 1.56 + i * 0.52, w: 5.2, h: 0.015, fill: { color: NT } });
});
// Bottom strip
s.addShape("rect", { x: 0, y: 5.38, w: "100%", h: 0.24, fill: { color: N } });
s.addText("Interactive | Flowcharts | Images | MCQs | Case Discussion", {
x: 0.18, y: 5.38, w: 9.64, h: 0.24,
fontSize: 8.5, color: NT, fontFace: "Calibri", align: "center", valign: "middle"
});
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 2 — LEARNING OBJECTIVES + SESSION STRUCTURE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Learning Objectives & Session Structure");
// Left: objectives
s.addText("By end of session, you will be able to:", {
x: 0.18, y: 0.92, w: 4.7, h: 0.34,
fontSize: 11.5, bold: true, color: N, fontFace: "Calibri"
});
const objs = [
"Define peptic ulcer disease",
"Describe anatomy and common sites",
"List aetiology (H. pylori, NSAIDs, acid)",
"Identify clinical features and signs",
"Choose appropriate investigations",
"Plan medical management",
"Recognise and manage complications",
"Outline indications for surgery"
];
objs.forEach((o, i) => {
// Alternating tint row
s.addShape("rect", {
x: 0.18, y: 1.3 + i * 0.42, w: 4.7, h: 0.4,
fill: { color: i % 2 === 0 ? NT : W },
line: { color: NT, width: 0.5 }
});
// Number badge
s.addShape("roundRect", { x: 0.22, y: 1.34 + i * 0.42, w: 0.28, h: 0.28, fill: { color: N }, rectRadius: 0.04 });
s.addText(`${i + 1}`, { x: 0.22, y: 1.34 + i * 0.42, w: 0.28, h: 0.28, fontSize: 9, bold: true, color: W, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(o, { x: 0.56, y: 1.33 + i * 0.42, w: 4.25, h: 0.36, fontSize: 11.5, color: TXT, fontFace: "Calibri", valign: "middle" });
});
// Divider
s.addShape("rect", { x: 5.05, y: 0.9, w: 0.04, h: 4.4, fill: { color: NT } });
// Right: session structure
s.addText("Session Timeline (60 min)", {
x: 5.2, y: 0.92, w: 4.6, h: 0.34,
fontSize: 11.5, bold: true, color: N, fontFace: "Calibri"
});
const plan = [
["Case Vignette (Opening)", "5 min"],
["Definition & Anatomy", "5 min"],
["Aetiology & Pathophysiology", "8 min"],
["Clinical Features", "5 min"],
["Investigations", "5 min"],
["Medical Management", "8 min"],
["Complications & Surgery", "10 min"],
["Case Discussion & MCQs", "10 min"],
["Summary & Q&A", "4 min"]
];
plan.forEach(([item, time], i) => {
const isCase = item.includes("Case");
const fill = isCase ? N : (i % 2 === 0 ? NT : W);
const tc = isCase ? W : TXT;
s.addShape("rect", {
x: 5.2, y: 1.3 + i * 0.37, w: 4.6, h: 0.35,
fill: { color: fill }, line: { color: NT, width: 0.5 }
});
s.addText(item, { x: 5.28, y: 1.3 + i * 0.37, w: 3.7, h: 0.35, fontSize: 11, color: tc, fontFace: "Calibri", bold: isCase, valign: "middle" });
s.addText(time, { x: 9.0, y: 1.3 + i * 0.37, w: 0.78, h: 0.35, fontSize: 11, color: isCase ? NT : N, fontFace: "Calibri", bold: true, align: "center", valign: "middle" });
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 3 — OPENING CASE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Opening Case Vignette — Think Before You Read On!");
// Case box
s.addShape("roundRect", { x: 0.18, y: 0.92, w: 9.64, h: 2.05, fill: { color: N }, rectRadius: 0.1 });
s.addText("CASE 1", { x: 0.28, y: 0.96, w: 1.0, h: 0.34, fontSize: 10, bold: true, color: NT, fontFace: "Calibri", align: "center", valign: "middle" });
s.addShape("rect", { x: 1.35, y: 1.08, w: 0.03, h: 1.72, fill: { color: NL } });
s.addText(
"Raju, 35-year-old male, smoker, construction worker. 3-month history of episodic burning epigastric pain " +
"— worse at night, relieved by food and antacids. He takes diclofenac daily for chronic back pain.\n" +
"O/E: mild epigastric tenderness. No guarding. No mass palpable.",
{
x: 1.45, y: 0.96, w: 8.25, h: 1.94,
fontSize: 13, color: W, fontFace: "Calibri", valign: "middle", wrap: true
}
);
// Questions grid
s.addText("Interactive Questions — Discuss in pairs:", {
x: 0.18, y: 3.06, w: 9.0, h: 0.34,
fontSize: 12, bold: true, color: N, fontFace: "Calibri"
});
divider(s, 3.42);
const qs = [
["Q1", "What is your provisional diagnosis?"],
["Q2", "Which risk factors are present?"],
["Q3", "What investigations will you order?"],
["Q4", "What is your immediate management?"]
];
qs.forEach(([num, q], i) => {
const xp = 0.18 + (i % 2) * 4.91;
const yp = 3.5 + Math.floor(i / 2) * 0.85;
s.addShape("roundRect", { x: xp, y: yp, w: 4.72, h: 0.75, fill: { color: i % 2 === 0 ? N : W }, line: { color: N, width: 1.5 }, rectRadius: 0.08 });
s.addText(num, { x: xp + 0.1, y: yp, w: 0.55, h: 0.75, fontSize: 13, bold: true, color: i % 2 === 0 ? NT : N, fontFace: "Calibri", align: "center", valign: "middle" });
s.addShape("rect", { x: xp + 0.7, y: yp + 0.1, w: 0.03, h: 0.55, fill: { color: i % 2 === 0 ? NL : NT } });
s.addText(q, { x: xp + 0.8, y: yp, w: 3.82, h: 0.75, fontSize: 12, color: i % 2 === 0 ? W : N, fontFace: "Calibri", valign: "middle" });
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 4 — DEFINITION & ANATOMY
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Definition & Common Sites");
// Definition banner
s.addShape("roundRect", { x: 0.18, y: 0.92, w: 9.64, h: 0.72, fill: { color: NT }, line: { color: N, width: 1.5 }, rectRadius: 0.08 });
s.addText("DEFINITION:", { x: 0.3, y: 0.92, w: 1.35, h: 0.72, fontSize: 11.5, bold: true, color: N, fontFace: "Calibri", align: "center", valign: "middle" });
s.addShape("rect", { x: 1.7, y: 1.04, w: 0.03, h: 0.48, fill: { color: N } });
s.addText("A breach in the GI mucosa extending through the muscularis mucosae, exposed to acid-pepsin.", {
x: 1.82, y: 0.92, w: 7.9, h: 0.72,
fontSize: 12.5, color: N, fontFace: "Calibri", valign: "middle", bold: false
});
// Sites table
s.addText("Common Sites", { x: 0.18, y: 1.75, w: 4.7, h: 0.34, fontSize: 13, bold: true, color: N, fontFace: "Calibri" });
const sites = [
["1st part of duodenum", "Most common site"],
["Lesser curve of stomach", "Gastric ulcer"],
["Prepyloric / Pyloric channel", "Behaves like DU"],
["Post-gastric surgery stoma", "Stomal ulcer"],
["Meckel's diverticulum", "Ectopic gastric mucosa"]
];
// Header
s.addShape("rect", { x: 0.18, y: 2.12, w: 2.95, h: 0.32, fill: { color: N } });
s.addText("Site", { x: 0.18, y: 2.12, w: 2.95, h: 0.32, fontSize: 10.5, bold: true, color: W, fontFace: "Calibri", align: "center", valign: "middle" });
s.addShape("rect", { x: 3.15, y: 2.12, w: 1.73, h: 0.32, fill: { color: N } });
s.addText("Note", { x: 3.15, y: 2.12, w: 1.73, h: 0.32, fontSize: 10.5, bold: true, color: W, fontFace: "Calibri", align: "center", valign: "middle" });
sites.forEach(([site, note], i) => {
const bg = i % 2 === 0 ? NT : W;
s.addShape("rect", { x: 0.18, y: 2.46 + i * 0.34, w: 2.95, h: 0.32, fill: { color: bg }, line: { color: NT, width: 0.5 } });
s.addText(site, { x: 0.26, y: 2.46 + i * 0.34, w: 2.8, h: 0.32, fontSize: 11, color: TXT, fontFace: "Calibri", valign: "middle" });
s.addShape("rect", { x: 3.15, y: 2.46 + i * 0.34, w: 1.73, h: 0.32, fill: { color: bg }, line: { color: NT, width: 0.5 } });
s.addText(note, { x: 3.23, y: 2.46 + i * 0.34, w: 1.58, h: 0.32, fontSize: 11, color: N, fontFace: "Calibri", valign: "middle", italic: true });
});
// Right column: key rules
s.addText("Key Anatomical Rules", { x: 5.2, y: 1.75, w: 4.6, h: 0.34, fontSize: 13, bold: true, color: N, fontFace: "Calibri" });
divider(s, 2.11);
const rules = [
"No acid = no ulcer (Schwartz's law)",
"Ulcer forms at epithelial junctions",
"Anterior DU → tends to perforate",
"Posterior DU → tends to bleed (GDA erosion)",
"Kissing ulcers: anterior + posterior DU",
"ALL gastric ulcers must be biopsied",
"Giant DU — malignancy extremely rare"
];
rules.forEach((r, i) => {
const isWarn = r.includes("biopsy") || r.includes("perforate") || r.includes("bleed");
s.addShape("roundRect", {
x: 5.2, y: 2.18 + i * 0.42, w: 4.6, h: 0.38,
fill: { color: isWarn ? N : NT }, line: { color: N, width: 0.8 }, rectRadius: 0.05
});
s.addText(`${isWarn ? "▶" : "•"} ${r}`, {
x: 5.3, y: 2.18 + i * 0.42, w: 4.4, h: 0.38,
fontSize: 11, color: isWarn ? W : TXT, fontFace: "Calibri", bold: isWarn, valign: "middle"
});
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 5 — AETIOLOGY FLOWCHART
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Aetiology — Causes of Peptic Ulcer Disease");
// Central node
navyBox(s, 3.82, 2.22, 2.36, 0.72, "PEPTIC ULCER", 13, true, 0.1);
// Left causes (navy filled)
const leftC = [
["H. pylori Infection\n(80% DU, 60% GU)", 0.18, 0.96],
["NSAIDs / Aspirin\n(COX-1 inhibition → ↓PGE2)", 0.18, 2.0],
["Cigarette Smoking\n(↓ mucosal defence, ↑ relapse)", 0.18, 3.04],
["Steroids\n(Combined with NSAIDs risk)", 0.18, 4.08]
];
leftC.forEach(([txt, x, y]) => {
navyBox(s, x, y, 2.35, 0.68, txt, 10, true, 0.08);
rightArrow(s, 2.56, y + 0.34);
// Connecting line
s.addShape("rect", { x: 2.86, y: y + 0.32, w: 0.96, h: 0.04, fill: { color: N } });
});
// Right causes (outline)
const rightC = [
["Zollinger-Ellison Syndrome\n(Gastrinoma → ↑↑ gastrin)", 7.47, 0.96],
["Stress Ulcers\n(ICU, burns, Cushing's, Curling's)", 7.47, 2.0],
["Blood Group O\n(Genetic predisposition)", 7.47, 3.04],
["Alcohol / Bile Reflux\n(Minor contributory role)", 7.47, 4.08]
];
rightC.forEach(([txt, x, y]) => {
outlineBox(s, x, y, 2.35, 0.68, txt, 10, false);
leftArrow(s, 6.96, y + 0.34);
s.addShape("rect", { x: 6.17, y: y + 0.32, w: 0.78, h: 0.04, fill: { color: N } });
});
// Bottom note
s.addShape("roundRect", { x: 0.18, y: 4.85, w: 9.64, h: 0.42, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.06 });
s.addText("H. pylori + NSAIDs account for >90% of peptic ulcers | Smoking doubles relapse rate (Bailey & Love, Ch. 67)", {
x: 0.28, y: 4.85, w: 9.44, h: 0.42, fontSize: 10.5, bold: true, color: N, fontFace: "Calibri", align: "center", valign: "middle"
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 6 — PATHOPHYSIOLOGY
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Pathophysiology — Imbalance of Forces");
// Aggressive column
s.addShape("roundRect", { x: 0.18, y: 0.92, w: 4.0, h: 4.38, fill: { color: NT }, line: { color: N, width: 1.5 }, rectRadius: 0.1 });
navyBox(s, 0.18, 0.92, 4.0, 0.5, "AGGRESSIVE FACTORS", 12.5, true, 0.1);
const agg = [
"Hydrochloric acid (HCl)",
"Pepsin",
"H. pylori (urease, VacA, CagA)",
"NSAIDs (inhibit COX-1 → ↓ PGE2)",
"Bile reflux (duodenogastric)",
"Reactive oxygen species",
"Stress hormones (cortisol)"
];
agg.forEach((a, i) => {
s.addShape("rect", { x: 0.35, y: 1.52 + i * 0.37, w: 0.16, h: 0.26, fill: { color: N } });
s.addText(a, { x: 0.57, y: 1.5 + i * 0.37, w: 3.45, h: 0.32, fontSize: 11.5, color: TXT, fontFace: "Calibri", valign: "middle" });
});
// Centre balance
s.addShape("roundRect", { x: 4.28, y: 2.1, w: 1.44, h: 1.55, fill: { color: N }, rectRadius: 0.1 });
s.addText("IMBALANCE\n=\nULCER", { x: 4.28, y: 2.1, w: 1.44, h: 1.55, fontSize: 11.5, bold: true, color: W, fontFace: "Calibri", align: "center", valign: "middle" });
// Defensive column
s.addShape("roundRect", { x: 5.82, y: 0.92, w: 4.0, h: 4.38, fill: { color: NT }, line: { color: N, width: 1.5 }, rectRadius: 0.1 });
navyBox(s, 5.82, 0.92, 4.0, 0.5, "DEFENSIVE FACTORS", 12.5, true, 0.1);
const def = [
"Mucus-bicarbonate barrier",
"Prostaglandin E2 (PGE2)",
"Mucosal blood flow",
"Tight epithelial junctions",
"Epithelial restitution (repair)",
"Trefoil peptides",
"Duodenal alkaline secretion"
];
def.forEach((d, i) => {
s.addShape("roundRect", { x: 5.99, y: 1.52 + i * 0.37, w: 0.22, h: 0.26, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.04 });
s.addText("✓", { x: 5.99, y: 1.52 + i * 0.37, w: 0.22, h: 0.26, fontSize: 9, bold: true, color: N, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(d, { x: 6.27, y: 1.5 + i * 0.37, w: 3.45, h: 0.32, fontSize: 11.5, color: TXT, fontFace: "Calibri", valign: "middle" });
});
// H pylori mechanism strip
s.addShape("roundRect", { x: 0.18, y: 5.3, w: 9.64, h: 0.28, fill: { color: N }, rectRadius: 0.05 });
s.addText("H. pylori → Urease → NH3 → Epithelial toxicity + ↑ Gastrin → ↑↑ Acid → Ulcer", {
x: 0.28, y: 5.3, w: 9.44, h: 0.28, fontSize: 10, bold: true, color: W, fontFace: "Calibri", align: "center", valign: "middle"
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 7 — H. PYLORI
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "H. pylori — The Ulcer Pathogen");
// Top stat cards
const stats = [
["Gram-negative\nSpiral rod", "Morphology"],
["Urease positive\nRapid CLO test", "Key property"],
["Lives in\ngastric antrum", "Location"],
["WHO Class I\nCarcinogen", "Significance"],
[">50% world\npopulation", "Prevalence"]
];
stats.forEach(([val, label], i) => {
navyBox(s, 0.18 + i * 1.93, 0.92, 1.78, 0.88, val, 10.5, true, 0.08);
s.addText(label, { x: 0.18 + i * 1.93, y: 1.82, w: 1.78, h: 0.26, fontSize: 9, color: NG, fontFace: "Calibri", align: "center", italic: true });
});
// Virulence factors
s.addText("Virulence Factors:", { x: 0.18, y: 2.15, w: 4.7, h: 0.35, fontSize: 13, bold: true, color: N, fontFace: "Calibri" });
divider(s, 2.52);
const vf = [
"Urease — splits urea → NH3 + CO2 (local cytotoxicity)",
"VacA — vacuolating cytotoxin, epithelial injury",
"CagA — cag pathogenicity island, inflammation",
"BabA — adhesin, binds Lewis blood group antigens",
"OipA — outer inflammatory protein"
];
vf.forEach((v, i) => {
const bg = i % 2 === 0 ? NT : W;
s.addShape("rect", { x: 0.18, y: 2.58 + i * 0.38, w: 4.7, h: 0.36, fill: { color: bg }, line: { color: NT, width: 0.5 } });
s.addText(`• ${v}`, { x: 0.28, y: 2.58 + i * 0.38, w: 4.55, h: 0.36, fontSize: 11, color: TXT, fontFace: "Calibri", valign: "middle" });
});
// Diagnosis methods
s.addText("Diagnosis Methods:", { x: 5.2, y: 2.15, w: 4.6, h: 0.35, fontSize: 13, bold: true, color: N, fontFace: "Calibri" });
divider(s, 2.52);
const diag = [
["Urea Breath Test", "Non-invasive, 95% sensitivity", true],
["CLO test (biopsy)", "Invasive, rapid, cheap", true],
["Stool Antigen Test", "Non-invasive, confirms active infection", true],
["Serology IgG", "Cannot confirm active infection", false],
["Histology (biopsy)", "Gold standard", true],
["Culture (biopsy)", "For antibiotic sensitivity", false]
];
diag.forEach(([test, note, preferred], i) => {
s.addShape("roundRect", {
x: 5.2, y: 2.58 + i * 0.38, w: 4.6, h: 0.35,
fill: { color: preferred ? N : NT }, line: { color: N, width: 0.8 }, rectRadius: 0.04
});
s.addText(test, { x: 5.28, y: 2.58 + i * 0.38, w: 2.1, h: 0.35, fontSize: 11, bold: preferred, color: preferred ? W : TXT, fontFace: "Calibri", valign: "middle" });
s.addText(note, { x: 7.45, y: 2.58 + i * 0.38, w: 2.28, h: 0.35, fontSize: 10, color: preferred ? NT : NG, fontFace: "Calibri", italic: true, valign: "middle" });
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 8 — DU vs GU COMPARISON TABLE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Duodenal Ulcer vs Gastric Ulcer — Comparison");
const cols = ["Feature", "Duodenal Ulcer", "Gastric Ulcer"];
const cW = [2.55, 3.42, 3.42];
const cX = [0.18, 2.76, 6.21];
// Header row
cols.forEach((c, i) => {
navyBox(s, cX[i], 0.92, cW[i], 0.44, c, 12, true, 0);
});
const rows = [
["Incidence", "More common (4:1 over GU)", "Less common"],
["Age", "Younger — 30 to 50 yrs", "Older — 50 to 70 yrs"],
["Gender", "Male > Female (3:1)", "Male = Female"],
["Acid secretion", "Increased or normal", "Normal or reduced"],
["H. pylori", "~80% of cases", "~60% of cases"],
["Malignancy risk", "Virtually never", "Must always exclude!"],
["Pain pattern", "Night pain, food relieves", "Food may worsen"],
["Weight", "Normal or weight gain", "Weight loss common"],
["Perforation", "Anterior wall — common", "Rare"],
["Bleeding", "Posterior (erodes GDA)", "Lesser curve vessels"]
];
rows.forEach((row, r) => {
const bg = r % 2 === 0 ? NT : W;
row.forEach((cell, c) => {
s.addShape("rect", { x: cX[c], y: 1.38 + r * 0.36, w: cW[c], h: 0.36, fill: { color: bg }, line: { color: NT, width: 0.5 } });
s.addText(cell, {
x: cX[c] + 0.08, y: 1.38 + r * 0.36, w: cW[c] - 0.12, h: 0.36,
fontSize: c === 0 ? 11 : 11, bold: c === 0,
color: c === 0 ? N : (cell.includes("!") ? N : TXT),
fontFace: "Calibri", valign: "middle"
});
});
});
// Warning footer
s.addShape("roundRect", { x: 0.18, y: 5.08, w: 9.64, h: 0.3, fill: { color: N }, rectRadius: 0.05 });
s.addText("▶ All gastric ulcers must be biopsied to exclude malignancy (Bailey & Love principle)", {
x: 0.28, y: 5.08, w: 9.44, h: 0.3, fontSize: 10.5, bold: true, color: W, fontFace: "Calibri", align: "center", valign: "middle"
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 9 — CLINICAL FEATURES
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Clinical Features of Peptic Ulcer Disease");
// Three symptom cards
const cards = [
{
title: "PAIN", icon: "▶",
items: ["Epigastric burning or gnawing", "May radiate to back", "Episodic — weeks/months pattern", "Night waking (classically DU)"]
},
{
title: "RELIEF", icon: "▶",
items: ["Food relieves (typical DU)", "Antacids give temporary relief", "Spontaneous healing & recurrence", "Periodicity = hallmark of PUD"]
},
{
title: "OTHER", icon: "▶",
items: ["Nausea, occasional vomiting", "Weight loss (GU) or gain (DU)", "Anaemia (chronic blood loss)", "Projectile vomiting → stenosis"]
}
];
cards.forEach((card, i) => {
navyBox(s, 0.18 + i * 3.25, 0.92, 3.1, 0.42, card.title, 13, true, 0.08);
s.addShape("roundRect", { x: 0.18 + i * 3.25, y: 1.36, w: 3.1, h: 1.75, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.08 });
card.items.forEach((item, j) => {
s.addText(`• ${item}`, { x: 0.28 + i * 3.25, y: 1.42 + j * 0.4, w: 2.9, h: 0.38, fontSize: 11.5, color: TXT, fontFace: "Calibri", valign: "top" });
});
});
// Signs section
s.addText("Clinical Signs:", { x: 0.18, y: 3.2, w: 3.0, h: 0.34, fontSize: 13, bold: true, color: N, fontFace: "Calibri" });
divider(s, 3.56);
const signs = [
{ text: "Mild epigastric tenderness — uncomplicated PUD", warn: false },
{ text: "Succussion splash → gastric outlet obstruction", warn: true },
{ text: "Board-like rigidity, absent bowel sounds → perforation", warn: true },
{ text: "PR blood / tarry stool (melaena) → GI haemorrhage", warn: true },
{ text: "Palpable epigastric mass → malignancy — urgent OGD", warn: true }
];
signs.forEach((sign, i) => {
s.addShape("roundRect", {
x: 0.18, y: 3.62 + i * 0.36, w: 9.64, h: 0.32,
fill: { color: sign.warn ? N : NT }, line: { color: N, width: 0.8 }, rectRadius: 0.05
});
s.addText(`${sign.warn ? "▶" : "•"} ${sign.text}`, {
x: 0.28, y: 3.62 + i * 0.36, w: 9.44, h: 0.32,
fontSize: 11, color: sign.warn ? W : TXT, fontFace: "Calibri", bold: sign.warn, valign: "middle"
});
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 10 — INVESTIGATIONS FLOWCHART
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Investigations — Stepwise Approach");
// Flowchart top-to-bottom
navyBox(s, 3.52, 0.96, 3.0, 0.52, "Suspected PUD\n(Symptoms + Risk Factors)", 10.5, true, 0.08);
downArrow(s, 5.02, 1.51);
tintBox(s, 3.2, 1.82, 3.6, 0.48, "Age <55, no alarm features?", 11, false);
// Branch labels
s.addText("YES", { x: 1.95, y: 1.86, w: 1.2, h: 0.22, fontSize: 9.5, bold: true, color: N, fontFace: "Calibri", align: "center" });
s.addText("NO / ALARM FEATURES", { x: 6.82, y: 1.82, w: 2.2, h: 0.25, fontSize: 9, bold: true, color: N, fontFace: "Calibri", align: "center" });
leftArrow(s, 1.7, 2.06);
s.addShape("rect", { x: 1.98, y: 2.04, w: 1.18, h: 0.04, fill: { color: N } });
rightArrow(s, 6.82, 2.06);
s.addShape("rect", { x: 6.82, y: 2.04, w: 1.16, h: 0.04, fill: { color: N } });
navyBox(s, 0.18, 1.82, 1.48, 0.48, "Test &\nTreat H. pylori", 10, true, 0.08);
outlineBox(s, 8.02, 1.82, 1.8, 0.48, "Urgent OGD\n+ Biopsy", 10, false);
// OGD pathway
downArrow(s, 5.02, 2.34);
navyBox(s, 3.2, 2.65, 3.6, 0.48, "OGD (Gold Standard)\n+ Biopsy if gastric ulcer", 10.5, true, 0.08);
downArrow(s, 5.02, 3.16);
tintBox(s, 3.2, 3.48, 3.6, 0.48, "H. pylori Testing\n(CLO / Histology on biopsy)", 10.5, false);
// Branches from H pylori
s.addText("+ve", { x: 1.82, y: 3.62, w: 1.34, h: 0.22, fontSize: 9.5, bold: true, color: N, fontFace: "Calibri", align: "center" });
s.addText("−ve", { x: 6.86, y: 3.62, w: 1.2, h: 0.22, fontSize: 9.5, bold: true, color: N, fontFace: "Calibri", align: "center" });
leftArrow(s, 1.74, 3.72);
s.addShape("rect", { x: 2.02, y: 3.7, w: 1.14, h: 0.04, fill: { color: N } });
rightArrow(s, 6.86, 3.72);
s.addShape("rect", { x: 6.82, y: 3.7, w: 1.16, h: 0.04, fill: { color: N } });
navyBox(s, 0.18, 3.48, 1.52, 0.48, "Eradicate\nH. pylori", 10, true, 0.08);
tintBox(s, 8.02, 3.48, 1.8, 0.48, "Review\ncause", 10, false);
// Additional tests strip
const tests = ["FBC + LFT", "Erect CXR (free gas)", "CT Abdomen", "Serum Amylase", "Fasting Gastrin (ZE)"];
s.addText("Additional Tests:", { x: 0.18, y: 4.12, w: 2.0, h: 0.3, fontSize: 11, bold: true, color: N, fontFace: "Calibri" });
tests.forEach((t, i) => {
navyBox(s, 0.18 + i * 1.92, 4.46, 1.82, 0.34, t, 9.5, true, 0.06);
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 11 — ENDOSCOPY & RADIOLOGY IMAGES
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Endoscopic & Radiological Appearance");
// Left image
if (imgDuodenal) {
s.addImage({ data: imgDuodenal, x: 0.18, y: 0.92, w: 4.7, h: 3.62 });
} else {
s.addShape("rect", { x: 0.18, y: 0.92, w: 4.7, h: 3.62, fill: { color: NT } });
s.addText("Duodenal Ulcer — OGD\n[Fig 67.10 Bailey & Love]", { x: 0.18, y: 0.92, w: 4.7, h: 3.62, fontSize: 13, color: N, fontFace: "Calibri", align: "center", valign: "middle", italic: true });
}
navyBox(s, 0.18, 4.56, 4.7, 0.44, "Fig 67.10 — Duodenal ulcer at gastroduodenoscopy\n(Courtesy Dr G.N.J. Tytgat, Amsterdam)", 9, false, 0.06);
// Right image
if (imgBarium) {
s.addImage({ data: imgBarium, x: 5.12, y: 0.92, w: 4.7, h: 3.62 });
} else {
s.addShape("rect", { x: 5.12, y: 0.92, w: 4.7, h: 3.62, fill: { color: NT } });
s.addText("Barium Meal — DU\n[Fig 67.11 Bailey & Love]", { x: 5.12, y: 0.92, w: 4.7, h: 3.62, fontSize: 13, color: N, fontFace: "Calibri", align: "center", valign: "middle", italic: true });
}
navyBox(s, 5.12, 4.56, 4.7, 0.44, "Fig 67.11 — Duodenal ulcer on barium meal examination\n(Bailey & Love 28th Ed.)", 9, false, 0.06);
footer(s, "Source: Bailey & Love's Short Practice of Surgery, 28th Ed. — Fig 67.10 & 67.11");
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 12 — MEDICAL MANAGEMENT STEP-UP
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Medical Management — Step-Up Approach");
const steps = [
{
num: "1", title: "Lifestyle",
items: ["Stop NSAIDs / aspirin", "Quit smoking and alcohol", "Avoid spicy food", "Reduce stress"]
},
{
num: "2", title: "Acid Suppression (PPI)",
items: ["Omeprazole 20–40 mg OD", "Lansoprazole 30 mg OD", "Pantoprazole 40 mg OD", "Duration: 4–8 weeks"]
},
{
num: "3", title: "H. pylori Eradication",
items: ["Triple therapy 7–14 days", "PPI + Amoxicillin + Clarithromycin", "Confirm with UBT ≥4 weeks post Rx", "Quadruple if 1st line fails"]
},
{
num: "4", title: "Follow-Up OGD (GU only)",
items: ["Repeat OGD at 8 weeks", "Confirm ulcer healing", "Re-biopsy non-healing ulcer", "Exclude malignancy"]
}
];
steps.forEach((step, i) => {
const x = 0.18 + i * 2.43;
// Column header (navy)
navyBox(s, x, 0.92, 2.28, 0.48, `Step ${step.num}`, 12, true, 0.08);
// Step title (tint)
tintBox(s, x, 1.42, 2.28, 0.44, step.title, 11.5, true);
// Items
s.addShape("roundRect", { x, y: 1.88, w: 2.28, h: 3.3, fill: { color: W }, line: { color: N, width: 1 }, rectRadius: 0.07 });
step.items.forEach((item, j) => {
s.addText(`• ${item}`, { x: x + 0.1, y: 1.96 + j * 0.65, w: 2.1, h: 0.62, fontSize: 11, color: TXT, fontFace: "Calibri", valign: "top", wrap: true });
});
// Arrow between steps
if (i < 3) rightArrow(s, x + 2.3, 2.56);
});
// Triple therapy note
s.addShape("roundRect", { x: 0.18, y: 5.28, w: 9.64, h: 0.28, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.05 });
s.addText("Triple Therapy eradication rate ~80–90% | Confirm cure with Urea Breath Test ≥4 weeks after stopping PPI & antibiotics", {
x: 0.28, y: 5.28, w: 9.44, h: 0.28, fontSize: 9.5, bold: true, color: N, fontFace: "Calibri", align: "center", valign: "middle"
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 13 — H. PYLORI ERADICATION REGIMENS
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "H. pylori Eradication Therapy");
// Triple therapy
navyBox(s, 0.18, 0.92, 4.65, 0.44, "TRIPLE THERAPY — First Line", 12.5, true, 0.08);
s.addShape("roundRect", { x: 0.18, y: 1.38, w: 4.65, h: 3.78, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.08 });
const triple = [
["PPI (standard dose)", "BD — any PPI"],
["+ Amoxicillin 1g", "BD"],
["+ Clarithromycin 500mg", "BD"],
["OR (penicillin allergy):", "Use Metronidazole 400mg BD"],
["Duration:", "7–14 days"],
["Eradication rate:", "~80–90%"],
["Confirm cure:", "UBT ≥4 weeks post-Rx"]
];
triple.forEach(([label, val], i) => {
const isPlus = label.startsWith("+");
s.addShape("roundRect", { x: 0.28, y: 1.46 + i * 0.48, w: 2.0, h: 0.4, fill: { color: isPlus ? N : NL }, rectRadius: 0.04 });
s.addText(label, { x: 0.28, y: 1.46 + i * 0.48, w: 2.0, h: 0.4, fontSize: 10.5, bold: true, color: W, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(val, { x: 2.34, y: 1.48 + i * 0.48, w: 2.38, h: 0.38, fontSize: 11, color: TXT, fontFace: "Calibri", valign: "middle" });
});
// Quadruple therapy
navyBox(s, 5.0, 0.92, 4.82, 0.44, "QUADRUPLE THERAPY — Second Line", 12, true, 0.08);
s.addShape("roundRect", { x: 5.0, y: 1.38, w: 4.82, h: 1.92, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.08 });
const quad = [
["PPI", "BD"],
["+ Bismuth subcitrate", "QID"],
["+ Tetracycline 500mg", "QID"],
["+ Metronidazole 400mg", "TID — 10 to 14 days"]
];
quad.forEach(([label, val], i) => {
s.addShape("roundRect", { x: 5.1, y: 1.46 + i * 0.42, w: 2.1, h: 0.36, fill: { color: N }, rectRadius: 0.04 });
s.addText(label, { x: 5.1, y: 1.46 + i * 0.42, w: 2.1, h: 0.36, fontSize: 10.5, bold: true, color: W, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(val, { x: 7.26, y: 1.48 + i * 0.42, w: 2.46, h: 0.34, fontSize: 11, color: TXT, fontFace: "Calibri", valign: "middle" });
});
// Pitfalls
navyBox(s, 5.0, 3.38, 4.82, 0.4, "Common Pitfalls — Avoid These!", 12, true, 0.08);
s.addShape("roundRect", { x: 5.0, y: 3.8, w: 4.82, h: 1.5, fill: { color: W }, line: { color: N, width: 1.5 }, rectRadius: 0.08 });
const pitfalls = [
"Stop PPI 2 weeks before UBT (prevents false negative)",
"Complete the full antibiotic course",
"Clarithromycin resistance rising globally",
"Test & Treat for dyspepsia in patients <55 years",
"Always confirm eradication after treatment"
];
pitfalls.forEach((p, i) => {
s.addText(`▶ ${p}`, { x: 5.1, y: 3.86 + i * 0.28, w: 4.62, h: 0.26, fontSize: 10.5, color: N, fontFace: "Calibri", bold: i === 0, valign: "middle" });
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 14 — COMPLICATIONS OVERVIEW
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Complications of Peptic Ulcer Disease");
// Central label
navyBox(s, 3.82, 2.25, 2.36, 0.72, "PEPTIC ULCER\nCOMPLICATIONS", 12, true, 0.1);
// Four corners — alternating navy / outline
const comps = [
{ name: "PERFORATION\n(Most dangerous)", x: 0.18, y: 0.98, navy: true },
{ name: "HAEMORRHAGE\n(Most common)", x: 7.64, y: 0.98, navy: false },
{ name: "PYLORIC STENOSIS\n(Gastric outlet obstruction)", x: 0.18, y: 3.62, navy: false },
{ name: "MALIGNANCY\n(Gastric ulcer — biopsy all)", x: 7.64, y: 3.62, navy: true }
];
comps.forEach((c) => {
if (c.navy) navyBox(s, c.x, c.y, 2.35, 1.0, c.name, 12, true, 0.1);
else outlineBox(s, c.x, c.y, 2.35, 1.0, c.name, 12, true);
// Lines to centre
s.addShape("rect", { x: c.x + 2.35, y: c.y + 0.46, w: 1.29, h: 0.04, fill: { color: N } });
});
// Key facts below
const facts = [
["Perforation", "Sudden severe pain, board-like rigidity, free gas CXR in >50%"],
["Haemorrhage", "Haematemesis / melaena, Forrest classification guides treatment"],
["Pyloric Stenosis", "Succussion splash, hypokalaemic hypochloraemic alkalosis"],
["Malignancy", "GU only — always biopsy to exclude; cancer can mimic benign ulcer"]
];
facts.forEach(([comp, detail], i) => {
s.addShape("rect", { x: 0.18, y: 4.75 + i * 0, w: 0, h: 0 }); // spacer
});
s.addShape("roundRect", { x: 0.18, y: 4.72, w: 9.64, h: 0.68, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.08 });
facts.forEach(([comp, detail], i) => {
s.addText(`${comp}: `, { x: 0.28 + i * 2.41, y: 4.76, w: 1.0, h: 0.28, fontSize: 9.5, bold: true, color: N, fontFace: "Calibri" });
s.addText(detail, { x: 0.28 + i * 2.41, y: 5.04, w: 2.28, h: 0.28, fontSize: 8.5, color: TXT, fontFace: "Calibri", wrap: true });
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 15 — PERFORATED PEPTIC ULCER + CXR IMAGE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Complication 1 — Perforated Peptic Ulcer");
// Clinical features (left)
navyBox(s, 0.18, 0.92, 4.65, 0.42, "Clinical Features", 12, true, 0.07);
s.addShape("roundRect", { x: 0.18, y: 1.36, w: 4.65, h: 2.25, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.08 });
const pf = [
"Sudden severe epigastric pain",
"Board-like rigidity of abdomen",
"Referred right shoulder tip pain",
"Shock: tachycardia, hypotension",
"Abdomen still — no respiratory movement",
"Fever — hours after perforation"
];
pf.forEach((p, i) => {
s.addText(`• ${p}`, { x: 0.3, y: 1.42 + i * 0.35, w: 4.45, h: 0.32, fontSize: 11.5, color: TXT, fontFace: "Calibri", valign: "middle" });
});
// Management (right)
navyBox(s, 5.0, 0.92, 4.82, 0.42, "Management", 12, true, 0.07);
s.addShape("roundRect", { x: 5.0, y: 1.36, w: 4.82, h: 2.25, fill: { color: W }, line: { color: N, width: 1 }, rectRadius: 0.08 });
const pm = [
"1. Resuscitate — IV fluids, analgesia",
"2. NGT + urinary catheter",
"3. Erect CXR → free gas?",
"4. CT abdomen (most accurate)",
"5. Serum amylase (rule out pancreatitis)",
"6. Surgery: laparotomy or laparoscopy"
];
pm.forEach((p, i) => {
s.addText(p, { x: 5.1, y: 1.42 + i * 0.35, w: 4.62, h: 0.32, fontSize: 11.5, color: TXT, fontFace: "Calibri", valign: "middle", bold: i === 5 });
});
// CXR Image
if (imgCXR) {
s.addImage({ data: imgCXR, x: 0.18, y: 3.68, w: 3.8, h: 1.72 });
} else {
s.addShape("rect", { x: 0.18, y: 3.68, w: 3.8, h: 1.72, fill: { color: NT } });
s.addText("Erect CXR\nFree Air Under Diaphragm\n[Fig 67.22 — Bailey & Love]", { x: 0.18, y: 3.68, w: 3.8, h: 1.72, fontSize: 12, color: N, fontFace: "Calibri", align: "center", valign: "middle", italic: true });
}
s.addText("Fig 67.22: Free air under right diaphragm — perforated DU (Bailey & Love)", { x: 0.18, y: 5.4, w: 3.8, h: 0.2, fontSize: 7.5, color: NG, fontFace: "Calibri", italic: true, align: "center" });
// Surgical options
navyBox(s, 4.1, 3.68, 5.72, 0.38, "Surgical Options", 11.5, true, 0.07);
const sops = [
"Graham's omental patch repair — standard for DU",
"Excise + close — gastric ulcer (histology mandatory)",
"Laparoscopic repair if expertise available",
"Roux-en-Y gastrectomy — massive perforation"
];
sops.forEach((op, i) => {
s.addShape("roundRect", { x: 4.1, y: 4.1 + i * 0.34, w: 5.72, h: 0.3, fill: { color: i % 2 === 0 ? NT : W }, line: { color: NT, width: 0.5 }, rectRadius: 0.04 });
s.addText(`• ${op}`, { x: 4.2, y: 4.1 + i * 0.34, w: 5.55, h: 0.3, fontSize: 11, color: TXT, fontFace: "Calibri", valign: "middle" });
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 16 — GI HAEMORRHAGE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Complication 2 — Upper GI Haemorrhage");
// Key stats
s.addShape("roundRect", { x: 0.18, y: 0.92, w: 9.64, h: 0.42, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.06 });
s.addText("Incidence >100/100,000/yr | Mortality 10–14% | Incidence rises with age | Strongly associated with NSAID use", {
x: 0.28, y: 0.92, w: 9.44, h: 0.42, fontSize: 11, bold: true, color: N, fontFace: "Calibri", align: "center", valign: "middle"
});
// Forrest classification
navyBox(s, 0.18, 1.42, 5.05, 0.4, "Forrest Classification (Endoscopic)", 12, true, 0.07);
const fHeader = ["Class", "Description", "Re-bleed Risk"];
const fCols = [0.18, 1.45, 3.25];
const fWidths = [1.22, 1.78, 1.95];
fHeader.forEach((h, i) => {
tintBox(s, fCols[i], 1.84, fWidths[i], 0.3, h, 10, true);
});
const forrest = [
["Ia", "Spurting arterial bleed", "55%", true],
["Ib", "Oozing bleed", "55%", true],
["IIa", "Non-bleeding visible vessel", "43%", true],
["IIb", "Adherent clot", "22%", false],
["IIc", "Haematin stained base", "10%", false],
["III", "Clean ulcer base", "5%", false]
];
forrest.forEach(([cls, desc, risk, endoscope], i) => {
const bg = endoscope ? N : (i % 2 === 0 ? NT : W);
const tc = endoscope ? W : TXT;
[0, 1, 2].forEach((ci) => {
const vals = [cls, desc, risk];
s.addShape("rect", { x: fCols[ci], y: 2.16 + i * 0.32, w: fWidths[ci], h: 0.3, fill: { color: bg }, line: { color: NT, width: 0.5 } });
s.addText(vals[ci], { x: fCols[ci] + 0.06, y: 2.16 + i * 0.32, w: fWidths[ci] - 0.1, h: 0.3, fontSize: 11, color: tc, fontFace: "Calibri", bold: ci === 0 && endoscope, valign: "middle" });
});
});
s.addText("Ia–IIa = Endoscopic therapy indicated", { x: 0.18, y: 4.1, w: 5.05, h: 0.26, fontSize: 9.5, color: N, bold: true, fontFace: "Calibri", italic: true });
// Management ladder
navyBox(s, 5.35, 1.42, 4.47, 0.4, "Management Ladder", 12, true, 0.07);
const mgmt = [
["Resuscitation", "IV access, fluids, blood products"],
["IV PPI infusion", "High dose omeprazole 80mg bolus"],
["Urgent OGD", "Within 24 hrs (12 hrs if unstable)"],
["Endoscopic Rx", "Adrenaline injection + clips/heater"],
["Interventional Radiology", "If endoscopy fails"],
["Surgery", "Underrunning / gastrectomy (last resort)"]
];
mgmt.forEach(([step, detail], i) => {
navyBox(s, 5.35, 1.84 + i * 0.55, 1.78, 0.46, step, 10, true, 0.05);
s.addText(detail, { x: 7.18, y: 1.88 + i * 0.55, w: 2.62, h: 0.4, fontSize: 10.5, color: TXT, fontFace: "Calibri", valign: "middle", italic: true });
if (i < 5) downArrow(s, 6.24, 2.32 + i * 0.55);
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 17 — PYLORIC STENOSIS & ZE SYNDROME
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Pyloric Stenosis & Zollinger-Ellison Syndrome");
// Pyloric stenosis
navyBox(s, 0.18, 0.92, 4.65, 0.42, "Pyloric Stenosis", 12.5, true, 0.08);
s.addShape("roundRect", { x: 0.18, y: 1.36, w: 4.65, h: 3.96, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.08 });
const pyloric = [
["Cause", "Fibrosis from chronic ulcer scarring"],
["Symptoms", "Persistent non-bilious vomiting"],
["Classic sign", "Succussion splash"],
["Pattern", "Projectile vomiting of old food"],
["Metabolic", "Hypokalaemic hypochloraemic alkalosis"],
["Investigation", "OGD + barium meal"],
["Treatment", "Resuscitate → endoscopic dilation"],
["Surgery", "Pyloroplasty or gastrojejunostomy"]
];
pyloric.forEach(([label, val], i) => {
const bg = i % 2 === 0 ? W : NT;
s.addShape("rect", { x: 0.28, y: 1.44 + i * 0.44, w: 4.45, h: 0.42, fill: { color: bg }, line: { color: NT, width: 0.4 } });
s.addText(label + ":", { x: 0.36, y: 1.44 + i * 0.44, w: 1.42, h: 0.42, fontSize: 11, bold: true, color: N, fontFace: "Calibri", valign: "middle" });
s.addText(val, { x: 1.84, y: 1.44 + i * 0.44, w: 2.8, h: 0.42, fontSize: 11, color: TXT, fontFace: "Calibri", valign: "middle" });
});
// ZE syndrome
navyBox(s, 5.0, 0.92, 4.82, 0.42, "Zollinger-Ellison Syndrome", 12.5, true, 0.08);
s.addShape("roundRect", { x: 5.0, y: 1.36, w: 4.82, h: 3.96, fill: { color: W }, line: { color: N, width: 1 }, rectRadius: 0.08 });
const ze = [
["Cause", "Gastrinoma (pancreas / duodenum)"],
["Pathology", "↑↑ Gastrin → ↑↑ Acid → multiple ulcers"],
["Symptoms", "Refractory / multiple / unusual PUD"],
["Diarrhoea", "Acid inactivates pancreatic enzymes"],
["Diagnosis", "Fasting gastrin >1000 pg/mL"],
["Secretin test", "Paradoxical rise in gastrin"],
["Imaging", "CT / MRI / Octreotide scan"],
["Treatment", "High-dose PPI + tumour resection"]
];
ze.forEach(([label, val], i) => {
const bg = i % 2 === 0 ? NT : W;
s.addShape("rect", { x: 5.1, y: 1.44 + i * 0.44, w: 4.62, h: 0.42, fill: { color: bg }, line: { color: NT, width: 0.4 } });
s.addText(label + ":", { x: 5.18, y: 1.44 + i * 0.44, w: 1.55, h: 0.42, fontSize: 11, bold: true, color: N, fontFace: "Calibri", valign: "middle" });
s.addText(val, { x: 6.78, y: 1.44 + i * 0.44, w: 2.85, h: 0.42, fontSize: 11, color: TXT, fontFace: "Calibri", valign: "middle" });
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 18 — SURGICAL MANAGEMENT
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Surgical Management of PUD");
// Indications
navyBox(s, 0.18, 0.92, 9.64, 0.5, "Indications for Surgery: Perforation | Uncontrolled Haemorrhage | Malignancy (GU) | Gastric Outlet Obstruction | Failed Medical Therapy", 11.5, true, 0.08);
// DU operations
navyBox(s, 0.18, 1.5, 4.65, 0.42, "Operations for Duodenal Ulcer", 12, true, 0.07);
s.addShape("roundRect", { x: 0.18, y: 1.94, w: 4.65, h: 3.22, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.08 });
const duOps = [
"Omental patch repair — perforation (Graham's)",
"Truncal vagotomy + drainage (pyloroplasty)",
"Highly selective vagotomy (HSV) — least side effects",
"Billroth II / Pólya — complex/emergency only",
"Vagotomy: reduces acid output by ~50%",
"Heineke–Mikulicz pyloroplasty — drainage",
"Elective surgery now performed in <1% cases"
];
duOps.forEach((op, i) => {
s.addText(`• ${op}`, { x: 0.3, y: 2.0 + i * 0.44, w: 4.42, h: 0.4, fontSize: 11, color: TXT, fontFace: "Calibri", valign: "middle", wrap: true });
});
// GU operations
navyBox(s, 5.0, 1.5, 4.82, 0.42, "Operations for Gastric Ulcer", 12, true, 0.07);
s.addShape("roundRect", { x: 5.0, y: 1.94, w: 4.82, h: 3.22, fill: { color: W }, line: { color: N, width: 1 }, rectRadius: 0.08 });
const guOps = [
"Always excise ulcer — histology mandatory",
"Billroth I gastrectomy — standard",
"Roux-en-Y reconstruction — massive perf",
"Wedge excision for small accessible ulcers",
"Subtotal gastrectomy if malignant",
"Cannot distinguish benign vs cancer pre-op",
"Post-op: PPIs + H. pylori eradication"
];
guOps.forEach((op, i) => {
s.addText(`• ${op}`, { x: 5.1, y: 2.0 + i * 0.44, w: 4.62, h: 0.4, fontSize: 11, color: TXT, fontFace: "Calibri", valign: "middle", wrap: true });
});
// Sequelae note
s.addShape("roundRect", { x: 0.18, y: 5.22, w: 9.64, h: 0.3, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.05 });
s.addText("Post-op sequelae: Dumping syndrome | Diarrhoea | Bilious vomiting | Small stomach | Malignant transformation 0.5%/yr", {
x: 0.28, y: 5.22, w: 9.44, h: 0.3, fontSize: 9.5, color: N, fontFace: "Calibri", align: "center", valign: "middle"
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 19 — DUMPING SYNDROME
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Post-surgical Complication — Dumping Syndrome");
const types = [
{
title: "EARLY DUMPING (30 min after meal)",
mech: "Rapid gastric emptying → Osmotic shift in jejunum → Fluid drawn from bloodstream → Hypovolaemia",
features: ["Flushing, palpitations, sweating (vasomotor)", "Diarrhoea, nausea, cramping (GI)", "Onset: 15–30 min after eating", "Lasts 1–2 hours"],
x: 0.18, navy: true
},
{
title: "LATE DUMPING (2–3 hrs after meal)",
mech: "Rapid glucose absorption → ↑↑ insulin release → Reactive hypoglycaemia",
features: ["Sweating, tremor, faintness", "Hunger, weakness, confusion", "Onset: 2–3 hours post meal", "Relieved by sugar intake"],
x: 5.1, navy: false
}
];
types.forEach((t) => {
if (t.navy) navyBox(s, t.x, 0.92, 4.72, 0.44, t.title, 12, true, 0.08);
else outlineBox(s, t.x, 0.92, 4.72, 0.44, t.title, 12, true);
// Mechanism box
s.addShape("roundRect", { x: t.x, y: 1.38, w: 4.72, h: 0.78, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.07 });
s.addText("Mechanism:", { x: t.x + 0.1, y: 1.42, w: 1.35, h: 0.24, fontSize: 11, bold: true, color: N, fontFace: "Calibri" });
s.addText(t.mech, { x: t.x + 0.1, y: 1.66, w: 4.52, h: 0.48, fontSize: 10.5, color: TXT, fontFace: "Calibri", valign: "top", wrap: true });
// Features
s.addText("Clinical features:", { x: t.x + 0.1, y: 2.22, w: 2.5, h: 0.3, fontSize: 11, bold: true, color: N, fontFace: "Calibri" });
t.features.forEach((f, i) => {
s.addShape("roundRect", { x: t.x, y: 2.56 + i * 0.42, w: 4.72, h: 0.38, fill: { color: i % 2 === 0 ? NT : W }, line: { color: NT, width: 0.5 }, rectRadius: 0.04 });
s.addText(`• ${f}`, { x: t.x + 0.1, y: 2.56 + i * 0.42, w: 4.55, h: 0.38, fontSize: 11.5, color: TXT, fontFace: "Calibri", valign: "middle" });
});
});
// Management
navyBox(s, 0.18, 4.28, 9.64, 0.42, "Management: Small frequent meals | Low carb, high protein diet | Lie down after meals | Octreotide (severe cases) | Surgical revision (rare)", 11, true, 0.07);
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 20 — COMPLETE MANAGEMENT ALGORITHM
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Complete Management Algorithm — PUD");
navyBox(s, 3.6, 0.92, 2.8, 0.48, "Epigastric Pain / Dyspepsia", 10.5, true, 0.08);
downArrow(s, 5.0, 1.43);
tintBox(s, 3.28, 1.74, 3.44, 0.46, "Age <55, no alarm features?", 10.5, false);
s.addText("YES", { x: 1.9, y: 1.78, w: 1.32, h: 0.2, fontSize: 9.5, bold: true, color: N, fontFace: "Calibri", align: "center" });
s.addText("NO / ALARM", { x: 6.82, y: 1.74, w: 2.0, h: 0.24, fontSize: 9, bold: true, color: N, fontFace: "Calibri", align: "center" });
leftArrow(s, 1.68, 1.97);
s.addShape("rect", { x: 1.96, y: 1.95, w: 1.28, h: 0.04, fill: { color: N } });
rightArrow(s, 6.82, 1.97);
s.addShape("rect", { x: 6.82, y: 1.95, w: 1.2, h: 0.04, fill: { color: N } });
navyBox(s, 0.18, 1.74, 1.46, 0.46, "Test &\nTreat H.pylori", 9.5, true, 0.07);
outlineBox(s, 8.06, 1.74, 1.76, 0.46, "Urgent OGD\n+ Biopsy", 9.5, false);
downArrow(s, 5.0, 2.23);
navyBox(s, 3.28, 2.54, 3.44, 0.46, "OGD + H. pylori test", 10.5, true, 0.08);
downArrow(s, 5.0, 3.03);
tintBox(s, 3.28, 3.34, 3.44, 0.46, "PUD confirmed?", 10.5, false);
// Branches
s.addText("YES", { x: 1.9, y: 3.38, w: 1.32, h: 0.2, fontSize: 9.5, bold: true, color: N, fontFace: "Calibri", align: "center" });
leftArrow(s, 1.68, 3.57);
s.addShape("rect", { x: 1.96, y: 3.55, w: 1.28, h: 0.04, fill: { color: N } });
navyBox(s, 0.18, 3.34, 1.46, 0.46, "PPI +\nEradicate", 9.5, true, 0.07);
downArrow(s, 5.0, 3.83);
tintBox(s, 3.28, 4.14, 3.44, 0.46, "Complication?", 10.5, false);
// 4 complication branches
const compB = [
["Perf.\n→ Surgery", 2.6],
["Bleed\n→ OGD", 3.8],
["Stenosis\n→ Dilate", 5.0],
["Malig.\n→ Refer", 6.2]
];
compB.forEach(([txt, xp]) => {
downArrow(s, xp, 4.63);
navyBox(s, xp - 0.6, 4.94, 1.16, 0.54, txt, 9.5, true, 0.06);
});
// Alarm features note
s.addShape("roundRect", { x: 0.18, y: 5.3, w: 9.64, h: 0.28, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.04 });
s.addText("Alarm Features: Age >55 | Dysphagia | Weight loss | Anaemia | Haematemesis | Palpable mass | Persistent vomiting", {
x: 0.28, y: 5.3, w: 9.44, h: 0.28, fontSize: 9.5, bold: true, color: N, fontFace: "Calibri", align: "center", valign: "middle"
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 21 — MCQ INTERACTIVE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Interactive MCQs — Test Yourself!");
const mcqs = [
{
q: "Q1. Most common site of peptic ulcer perforation?",
opts: ["A. Lesser curve of stomach", "B. 1st part duodenum — anterior wall", "C. Prepyloric region", "D. 2nd part duodenum"],
ans: 1
},
{
q: "Q2. First-line H. pylori eradication therapy?",
opts: ["A. H2 blockers + amoxicillin", "B. PPI + clarithromycin + amoxicillin", "C. Antacids alone", "D. Sucralfate + tetracycline"],
ans: 1
},
{
q: "Q3. Best test to confirm H. pylori eradication?",
opts: ["A. Serology IgG", "B. CLO test on biopsy", "C. Urea Breath Test (UBT)", "D. Stool culture"],
ans: 2
},
{
q: "Q4. Metabolic abnormality in pyloric stenosis?",
opts: ["A. Hypokalaemic hyperchloraemic acidosis", "B. Hyperkalaemic alkalosis", "C. Hypokalaemic hypochloraemic alkalosis", "D. Normal electrolytes"],
ans: 2
}
];
mcqs.forEach((mcq, qi) => {
const yBase = 0.9 + qi * 1.16;
s.addShape("roundRect", { x: 0.18, y: yBase, w: 9.64, h: 1.1, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.08 });
s.addText(mcq.q, { x: 0.3, y: yBase + 0.04, w: 9.4, h: 0.3, fontSize: 11.5, bold: true, color: N, fontFace: "Calibri" });
mcq.opts.forEach((opt, oi) => {
const isAns = oi === mcq.ans;
const xp = 0.28 + (oi % 2) * 4.82;
const yp = yBase + 0.38 + Math.floor(oi / 2) * 0.34;
s.addShape("roundRect", {
x: xp, y: yp, w: 4.65, h: 0.3,
fill: { color: isAns ? N : W },
line: { color: N, width: 1 },
rectRadius: 0.04
});
s.addText(opt + (isAns ? " ✓" : ""), {
x: xp + 0.08, y: yp, w: 4.5, h: 0.3,
fontSize: 10.5, color: isAns ? W : TXT, fontFace: "Calibri",
bold: isAns, valign: "middle"
});
});
});
footer(s, "Correct answers highlighted in Navy — discuss reasoning with faculty");
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 22 — SPECIAL SITUATIONS
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Special Situations in PUD");
const specials = [
{
title: "PUD in Elderly",
items: ["NSAIDs most common cause", "Atypical / silent presentation", "Higher complication rate", "Perforations often in elderly females", "Steroids mask peritonism"]
},
{
title: "PUD in Pregnancy",
items: ["H2 blockers preferred", "PPIs: use with caution (2nd/3rd trim)", "Avoid clarithromycin", "Lifestyle modification first", "Metronidazole safe after 1st trimester"]
},
{
title: "PUD + Anticoagulation",
items: ["High risk of UGIB", "Reverse anticoagulation if major bleed", "Early OGD mandatory", "PPI co-prescription essential", "H. pylori test & treat before starting"]
},
{
title: "NSAID-induced PUD",
items: ["COX-1 inhibition → ↓ PGE2 → ↓ mucus", "Use lowest effective NSAID dose", "COX-2 selective if high GI risk", "Mandatory PPI co-prescription", "H. pylori test before starting NSAIDs"]
}
];
specials.forEach((sp, i) => {
const xp = 0.18 + (i % 2) * 4.91;
const yp = 0.92 + Math.floor(i / 2) * 2.32;
const useNavy = i % 2 === 0;
if (useNavy) navyBox(s, xp, yp, 4.72, 0.42, sp.title, 12.5, true, 0.08);
else outlineBox(s, xp, yp, 4.72, 0.42, sp.title, 12.5, true);
s.addShape("roundRect", { x: xp, y: yp + 0.44, w: 4.72, h: 1.78, fill: { color: NT }, line: { color: N, width: 1 }, rectRadius: 0.08 });
sp.items.forEach((item, j) => {
s.addText(`• ${item}`, { x: xp + 0.12, y: yp + 0.5 + j * 0.33, w: 4.5, h: 0.3, fontSize: 11, color: TXT, fontFace: "Calibri" });
});
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 23 — PREVENTION
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Prevention Strategies for PUD");
navyBox(s, 0.18, 0.92, 9.64, 0.42, "PRIMARY PREVENTION", 13, true, 0.07);
const prev = [
["H. pylori Test & Treat", "For all patients with dyspepsia or PUD", "Mandatory"],
["Minimise NSAIDs", "Lowest effective dose for shortest duration", "Essential"],
["PPI Co-prescription", "Mandatory for high-risk NSAID users", "Essential"],
["Quit Smoking", "Doubles PUD relapse rate; impairs healing", "Strongly advised"],
["Limit Alcohol", "Damages mucosal barrier, synergistic with NSAIDs", "Advised"]
];
// Table header
s.addShape("rect", { x: 0.18, y: 1.38, w: 3.0, h: 0.32, fill: { color: NL } });
s.addText("Strategy", { x: 0.18, y: 1.38, w: 3.0, h: 0.32, fontSize: 10.5, bold: true, color: W, fontFace: "Calibri", align: "center", valign: "middle" });
s.addShape("rect", { x: 3.22, y: 1.38, w: 4.95, h: 0.32, fill: { color: NL } });
s.addText("Action", { x: 3.22, y: 1.38, w: 4.95, h: 0.32, fontSize: 10.5, bold: true, color: W, fontFace: "Calibri", align: "center", valign: "middle" });
s.addShape("rect", { x: 8.2, y: 1.38, w: 1.62, h: 0.32, fill: { color: NL } });
s.addText("Priority", { x: 8.2, y: 1.38, w: 1.62, h: 0.32, fontSize: 10.5, bold: true, color: W, fontFace: "Calibri", align: "center", valign: "middle" });
prev.forEach(([strat, action, prio], i) => {
const bg = i % 2 === 0 ? NT : W;
const isEss = prio === "Mandatory" || prio === "Essential";
s.addShape("rect", { x: 0.18, y: 1.72 + i * 0.38, w: 3.0, h: 0.36, fill: { color: bg }, line: { color: NT, width: 0.5 } });
s.addText(strat, { x: 0.28, y: 1.72 + i * 0.38, w: 2.84, h: 0.36, fontSize: 11.5, bold: true, color: N, fontFace: "Calibri", valign: "middle" });
s.addShape("rect", { x: 3.22, y: 1.72 + i * 0.38, w: 4.95, h: 0.36, fill: { color: bg }, line: { color: NT, width: 0.5 } });
s.addText(action, { x: 3.32, y: 1.72 + i * 0.38, w: 4.78, h: 0.36, fontSize: 11, color: TXT, fontFace: "Calibri", valign: "middle" });
s.addShape("rect", { x: 8.2, y: 1.72 + i * 0.38, w: 1.62, h: 0.36, fill: { color: isEss ? N : NT }, line: { color: NT, width: 0.5 } });
s.addText(prio, { x: 8.2, y: 1.72 + i * 0.38, w: 1.62, h: 0.36, fontSize: 10, bold: isEss, color: isEss ? W : N, fontFace: "Calibri", align: "center", valign: "middle" });
});
// NSAID risk stratification
s.addText("NSAID Risk Stratification:", { x: 0.18, y: 3.72, w: 4.0, h: 0.34, fontSize: 12.5, bold: true, color: N, fontFace: "Calibri" });
divider(s, 4.08);
const risk = [
["LOW RISK\nNSAID alone", "No co-prescription needed", false],
["MODERATE RISK\nAge >65 or H. pylori positive", "PPI co-prescription", true],
["HIGH RISK\nPrior PUD or anticoagulant", "PPI + COX-2 selective", true]
];
risk.forEach(([level, action, navy], i) => {
if (navy) navyBox(s, 0.18 + i * 3.25, 4.14, 3.1, 0.9, `${level}\n→ ${action}`, 10.5, true, 0.08);
else outlineBox(s, 0.18 + i * 3.25, 4.14, 3.1, 0.9, `${level}\n→ ${action}`, 10.5, false);
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 24 — CLOSING CASE DISCUSSION
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Closing Case Discussion — Apply Your Knowledge!");
// Case box
s.addShape("roundRect", { x: 0.18, y: 0.92, w: 9.64, h: 2.15, fill: { color: N }, rectRadius: 0.1 });
s.addText("CASE 2", { x: 0.28, y: 0.96, w: 1.0, h: 0.34, fontSize: 10, bold: true, color: NT, fontFace: "Calibri", align: "center" });
s.addShape("rect", { x: 1.35, y: 1.08, w: 0.04, h: 1.82, fill: { color: NL } });
s.addText(
"Sunita, 60-year-old female, on diclofenac for arthritis and aspirin for cardiac disease. Sudden-onset " +
"severe central abdominal pain followed by right shoulder tip pain. Pale, tachycardic (HR 120), " +
"hypotensive (BP 90/60 mmHg). Abdomen rigid, not moving with respiration. Erect CXR shows free " +
"gas under the right hemidiaphragm.",
{
x: 1.48, y: 0.96, w: 8.22, h: 2.02,
fontSize: 12.5, color: W, fontFace: "Calibri", valign: "middle", wrap: true
}
);
// Discussion questions
s.addText("Group Discussion (10 minutes):", {
x: 0.18, y: 3.16, w: 9.64, h: 0.34, fontSize: 12.5, bold: true, color: N, fontFace: "Calibri"
});
divider(s, 3.52);
const dqs = [
{ num: "Q1", q: "What is the diagnosis and causative factors?", hint: "NSAIDs + aspirin → NSAID-induced perforation" },
{ num: "Q2", q: "How do you resuscitate this patient?", hint: "IV access, fluids, analgesia, NGT, catheter, OT" },
{ num: "Q3", q: "What operation would you perform and why?", hint: "Graham's patch (DU) — do not forget peritoneal toilet" },
{ num: "Q4", q: "What post-op medical management is essential?", hint: "IV PPI → oral PPI + H. pylori eradication + stop NSAIDs" }
];
dqs.forEach((dq, i) => {
const xp = 0.18 + (i % 2) * 4.91;
const yp = 3.6 + Math.floor(i / 2) * 0.85;
const useNavy = i % 2 === 0;
s.addShape("roundRect", { x: xp, y: yp, w: 4.72, h: 0.76, fill: { color: useNavy ? N : W }, line: { color: N, width: 1.5 }, rectRadius: 0.08 });
s.addText(dq.num, { x: xp + 0.1, y: yp, w: 0.52, h: 0.76, fontSize: 13, bold: true, color: useNavy ? NT : N, fontFace: "Calibri", align: "center", valign: "middle" });
s.addShape("rect", { x: xp + 0.68, y: yp + 0.1, w: 0.04, h: 0.56, fill: { color: useNavy ? NL : NT } });
s.addText(dq.q, { x: xp + 0.8, y: yp + 0.04, w: 3.82, h: 0.4, fontSize: 11.5, color: useNavy ? W : N, fontFace: "Calibri", bold: true, valign: "bottom" });
s.addText(`Hint: ${dq.hint}`, { x: xp + 0.8, y: yp + 0.46, w: 3.82, h: 0.28, fontSize: 9.5, color: useNavy ? NT : NG, fontFace: "Calibri", italic: true });
});
footer(s);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 25 — SUMMARY & TAKE-HOME MESSAGES
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
header(s, "Summary & Take-Home Messages");
// 10 key messages (left + right columns)
const msgs = [
"No acid = no ulcer — PPIs are cornerstone of treatment",
"H. pylori + NSAIDs account for >90% of all PUD",
"Always biopsy ALL gastric ulcers — exclude malignancy",
"Triple therapy: PPI + clarithromycin + amoxicillin (7–14 days)",
"Confirm eradication with Urea Breath Test ≥4 weeks post-Rx",
"Free gas on erect CXR = perforation until proven otherwise",
"Forrest Ia / Ib = urgent endoscopic haemostasis",
"Succussion splash = gastric outlet obstruction",
"Surgery now reserved for complications only",
"ZE syndrome: suspect with multiple, refractory, unusual ulcers"
];
msgs.forEach((msg, i) => {
const col = i < 5 ? 0 : 1;
const xp = 0.18 + col * 4.91;
const yp = 0.96 + (i % 5) * 0.46;
s.addShape("roundRect", { x: xp, y: yp, w: 4.72, h: 0.4, fill: { color: i % 2 === 0 ? N : NT }, line: { color: N, width: 1 }, rectRadius: 0.06 });
s.addShape("roundRect", { x: xp + 0.06, y: yp + 0.06, w: 0.28, h: 0.28, fill: { color: i % 2 === 0 ? NL : N }, rectRadius: 0.04 });
s.addText(`${i + 1}`, { x: xp + 0.06, y: yp + 0.06, w: 0.28, h: 0.28, fontSize: 9, bold: true, color: W, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(msg, { x: xp + 0.42, y: yp, w: 4.22, h: 0.4, fontSize: 10.5, color: i % 2 === 0 ? W : TXT, fontFace: "Calibri", valign: "middle", wrap: true });
});
// Peer review checklist
navyBox(s, 0.18, 3.3, 9.64, 0.38, "PEER REVIEW CHECKLIST ALIGNMENT (Ramaiah Medical College Format)", 11, true, 0.07);
const criteria = [
"Interest arousal — Opening case vignette (Slide 3)",
"Objectives stated — Slide 2 with structured timeline",
"Logical sequence — Basic to advanced flow",
"Relevant content — Bailey & Love 28th Ed. directly cited",
"Examples used — 2 patient cases + endoscopy images",
"Audio-visual aids — 3 real textbook images + 6 flowcharts",
"Questions asked — 4 MCQs + group case discussion",
"Summary provided — This slide with key messages"
];
criteria.forEach((c, i) => {
const xp = 0.18 + (i % 2 === 0 ? 0 : 4.91);
const yp = 3.74 + Math.floor(i / 2) * 0.33;
s.addShape("roundRect", { x: xp, y: yp, w: 4.72, h: 0.3, fill: { color: NT }, line: { color: N, width: 0.8 }, rectRadius: 0.04 });
s.addShape("roundRect", { x: xp + 0.05, y: yp + 0.04, w: 0.22, h: 0.22, fill: { color: N }, rectRadius: 0.04 });
s.addText("✓", { x: xp + 0.05, y: yp + 0.04, w: 0.22, h: 0.22, fontSize: 9, bold: true, color: W, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(c, { x: xp + 0.32, y: yp, w: 4.32, h: 0.3, fontSize: 9.5, color: TXT, fontFace: "Calibri", valign: "middle" });
});
// Thank you
s.addShape("roundRect", { x: 0.18, y: 5.08, w: 9.64, h: 0.42, fill: { color: N }, rectRadius: 0.07 });
s.addText("Thank You! | Questions & Discussion | Bailey & Love, 28th Ed. | For Educational Use Only", {
x: 0.28, y: 5.08, w: 9.44, h: 0.42, fontSize: 12, bold: true, color: W, fontFace: "Calibri", align: "center", valign: "middle"
});
footer(s, "Bailey & Love's Short Practice of Surgery, 28th Ed. | Dept of Surgery | MBBS Undergraduate Teaching");
}
// ─── SAVE ──────────────────────────────────────────────────────────────────
pres.writeFile({ fileName: "/home/daytona/workspace/peptic-ulcer-ppt/PUD_NavyWhite_MBBS.pptx" })
.then(() => console.log("✅ Saved: PUD_NavyWhite_MBBS.pptx"))
.catch(err => console.error("❌ Error:", err));
cd /home/daytona/workspace/peptic-ulcer-ppt && node create_ppt_v2.js 2>&1
ls -lh /home/daytona/workspace/peptic-ulcer-ppt/PUD_NavyWhite_MBBS.pptx && node …
PUD NavyWhite MBBS
Presentation · PPTX
| Element | Treatment |
|---|---|
| All slide backgrounds | Pure white |
| Headers / title bars | Solid navy |
| Primary content boxes | Navy (white text) |
| Secondary / alternating rows | Very pale navy tint (#E8EEF5) |
| Outline boxes (for contrast) | White fill, navy border + navy text |
| All body text | Near-black on white, navy on tint |
| Accent lines / dividers | Pale navy tint |
| Footer bars | Navy |
| Arrows (flowcharts) | Navy |
the ppt u hared has the peer review points which shouldnt not mention in ppt but the ppt should follow the peer riew checklist the headings should be 32 size subheading 28 and body teext 24 and dont need to add references in all the slides can u correct it and give me the new slides
~/peptic-ulcer-ppt/create_ppt_v3.js
const pptxgen = require("pptxgenjs");
const { execSync } = require("child_process");
// ─── FETCH IMAGES ──────────────────────────────────────────────────────────
const imageUrls = [
"https://cdn.orris.care/cdss_images/9b8c9b80815ac3526d6c02271dd7a0ea8b3a0d054a5db153ca8b9827c1b8fb42.png",
"https://cdn.orris.care/cdss_images/675c6b1515e8f1b218a165f8bee0054477bcedf899e353e0883df93d04bf5587.png",
"https://cdn.orris.care/cdss_images/ec56874995d0dbd5dae7706865ecb332a07f6afd474a8fe534c6d384e4ed95bb.png"
];
let imgDuodenal = "", imgBarium = "", imgCXR = "";
try {
const raw = execSync(
`node /home/daytona/skills/shared/scripts/fetch_images.js "${imageUrls[0]}" "${imageUrls[1]}" "${imageUrls[2]}"`,
{ maxBuffer: 50 * 1024 * 1024 }
).toString();
const imgs = JSON.parse(raw);
imgDuodenal = imgs[0] && !imgs[0].error ? imgs[0].base64 : "";
imgBarium = imgs[1] && !imgs[1].error ? imgs[1].base64 : "";
imgCXR = imgs[2] && !imgs[2].error ? imgs[2].base64 : "";
} catch(e) { console.error("Image fetch:", e.message); }
// ─── PALETTE (Navy + White only) ──────────────────────────────────────────
const N = "0D2B4E"; // Navy
const NL = "1A4A78"; // Navy light
const NT = "E8EEF5"; // Navy tint (pale)
const NG = "6B8DB2"; // Navy grey
const W = "FFFFFF"; // White
const TXT = "1A1A2E"; // Near-black for body text
// ─── FONT SIZE CONSTANTS ──────────────────────────────────────────────────
const FS_HEAD = 32; // Slide heading (header bar title)
const FS_SUB = 28; // Subheading inside slides
const FS_BODY = 24; // Body text / bullet points
const FS_FOOT = 9; // Footer only (small)
// ─── PRESENTATION SETUP ───────────────────────────────────────────────────
const pres = new pptxgen();
pres.layout = "LAYOUT_16x9";
pres.author = "Dept of Surgery";
pres.title = "Peptic Ulcer Disease";
// ─── SHARED HELPERS ───────────────────────────────────────────────────────
function whiteBg(s) {
s.addShape("rect", { x:0, y:0, w:"100%", h:"100%", fill:{color:W} });
}
// Header bar: navy, heading text 32pt
function hdr(s, title) {
s.addShape("rect", { x:0, y:0, w:"100%", h:0.9, fill:{color:N} });
s.addShape("rect", { x:0, y:0.9, w:"100%", h:0.06, fill:{color:NL} });
s.addText(title, {
x:0.2, y:0, w:9.6, h:0.9,
fontSize:FS_HEAD, bold:true, color:W, fontFace:"Calibri",
align:"left", valign:"middle", margin:0
});
}
// Slim footer: slide number + clean department label, no sources on every slide
function ftr(s, slideNum) {
s.addShape("rect", { x:0, y:5.42, w:"100%", h:0.2, fill:{color:N} });
s.addText(`Peptic Ulcer Disease | Dept of Surgery | ${slideNum}/25`, {
x:0.2, y:5.42, w:9.6, h:0.2,
fontSize:FS_FOOT, color:NT, fontFace:"Calibri",
italic:false, align:"right", valign:"middle"
});
}
// Navy filled rounded box, white text
function navyBox(s, x, y, w, h, text, fs, bold, r) {
r = r !== undefined ? r : 0.07;
s.addShape("roundRect", { x,y,w,h, fill:{color:N}, line:{color:N,width:0}, rectRadius:r });
s.addText(text, { x,y,w,h, fontSize:fs||FS_BODY, bold:bold!==false, color:W, fontFace:"Calibri", align:"center", valign:"middle", wrap:true });
}
// White fill, navy border + navy text
function outBox(s, x, y, w, h, text, fs, bold) {
s.addShape("roundRect", { x,y,w,h, fill:{color:W}, line:{color:N,width:1.5}, rectRadius:0.07 });
s.addText(text, { x,y,w,h, fontSize:fs||FS_BODY, bold:bold||false, color:N, fontFace:"Calibri", align:"center", valign:"middle", wrap:true });
}
// Pale-navy tint box, navy text
function tintBox(s, x, y, w, h, text, fs, bold) {
s.addShape("roundRect", { x,y,w,h, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.07 });
s.addText(text, { x,y,w,h, fontSize:fs||FS_BODY, bold:bold||false, color:N, fontFace:"Calibri", align:"center", valign:"middle", wrap:true });
}
function dArr(s, cx, y) { // down arrow
s.addShape("downArrow", { x:cx-0.14, y, w:0.28, h:0.3, fill:{color:N} });
}
function rArr(s, x, cy) { // right arrow
s.addShape("rightArrow", { x, y:cy-0.12, w:0.3, h:0.24, fill:{color:N} });
}
function lArr(s, x, cy) { // left arrow
s.addShape("leftArrow", { x, y:cy-0.12, w:0.3, h:0.24, fill:{color:N} });
}
function div(s, y) { // thin divider line
s.addShape("rect", { x:0.2, y, w:9.6, h:0.03, fill:{color:NT} });
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 1 — TITLE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
s.addShape("rect", { x:0, y:0, w:"100%", h:"100%", fill:{color:W} });
// Left navy panel
s.addShape("rect", { x:0, y:0, w:4.3, h:"100%", fill:{color:N} });
s.addShape("rect", { x:4.3, y:0, w:0.08, h:"100%", fill:{color:NL} });
s.addText("PEPTIC\nULCER\nDISEASE", {
x:0.25, y:0.85, w:3.8, h:2.7,
fontSize:42, bold:true, color:W, fontFace:"Calibri",
align:"left", valign:"middle", lineSpacingMultiple:1.1
});
s.addShape("rect", { x:0.25, y:3.7, w:3.6, h:0.05, fill:{color:NL} });
s.addText("Interactive Case-Based Session", {
x:0.25, y:3.82, w:3.8, h:0.42,
fontSize:18, color:NT, fontFace:"Calibri", italic:true
});
s.addText("MBBS | Surgery | 60 Minutes", {
x:0.25, y:4.3, w:3.8, h:0.35,
fontSize:16, color:NG, fontFace:"Calibri"
});
// Right panel — topics
s.addText("TOPICS COVERED", {
x:4.65, y:0.45, w:5.1, h:0.44,
fontSize:20, bold:true, color:N, fontFace:"Calibri", charSpacing:2
});
div(s, 0.92);
const topics = [
"1. Anatomy & Common Sites",
"2. Aetiology & Risk Factors",
"3. Pathophysiology",
"4. Clinical Features",
"5. Investigations",
"6. Medical Management",
"7. Complications",
"8. Surgical Management",
"9. Case-Based Discussion"
];
topics.forEach((t, i) => {
s.addText(t, {
x:4.65, y:1.0 + i*0.48, w:5.1, h:0.44,
fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle"
});
if (i < topics.length-1)
s.addShape("rect", { x:4.65, y:1.44 + i*0.48, w:5.1, h:0.015, fill:{color:NT} });
});
ftr(s, 1);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 2 — SESSION OVERVIEW & OBJECTIVES
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Session Overview");
// Left: objectives list
s.addText("What you will learn:", {
x:0.2, y:1.05, w:4.7, h:0.38,
fontSize:FS_SUB, bold:true, color:N, fontFace:"Calibri"
});
const objs = [
"Define peptic ulcer disease",
"Describe anatomy & common sites",
"List aetiology — H. pylori, NSAIDs",
"Identify clinical features & signs",
"Choose appropriate investigations",
"Plan medical management (PPIs)",
"Recognise & manage complications",
"Outline indications for surgery"
];
objs.forEach((o, i) => {
s.addShape("rect", {
x:0.2, y:1.48 + i*0.46, w:4.7, h:0.43,
fill:{color: i%2===0 ? NT : W}, line:{color:NT, width:0.5}
});
s.addShape("roundRect", { x:0.26, y:1.53+i*0.46, w:0.3, h:0.3, fill:{color:N}, rectRadius:0.04 });
s.addText(`${i+1}`, { x:0.26, y:1.53+i*0.46, w:0.3, h:0.3, fontSize:11, bold:true, color:W, fontFace:"Calibri", align:"center", valign:"middle" });
s.addText(o, { x:0.62, y:1.5+i*0.46, w:4.22, h:0.4, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle" });
});
// Right: session timeline
s.addShape("rect", { x:5.1, y:1.0, w:0.04, h:4.35, fill:{color:NT} });
s.addText("Session Timeline (60 min)", {
x:5.25, y:1.05, w:4.55, h:0.38,
fontSize:FS_SUB, bold:true, color:N, fontFace:"Calibri"
});
const plan = [
["Case Vignette (Opening)", "5 min", true],
["Anatomy & Pathophysiology","8 min", false],
["Clinical Features", "5 min", false],
["Investigations", "5 min", false],
["Medical Management", "8 min", false],
["Complications & Surgery", "10 min",false],
["Case Discussion & MCQs", "10 min",true],
["Summary & Q&A", "4 min", false]
];
plan.forEach(([item, time, isCase], i) => {
const bg = isCase ? N : (i%2===0 ? NT : W);
const tc = isCase ? W : TXT;
s.addShape("rect", { x:5.25, y:1.48+i*0.41, w:4.55, h:0.39, fill:{color:bg}, line:{color:NT, width:0.5} });
s.addText(item, { x:5.33, y:1.48+i*0.41, w:3.65, h:0.39, fontSize:FS_BODY, color:tc, fontFace:"Calibri", bold:isCase, valign:"middle" });
s.addText(time, { x:9.0, y:1.48+i*0.41, w:0.78, h:0.39, fontSize:FS_BODY, color:isCase?NT:N, fontFace:"Calibri", bold:true, align:"center", valign:"middle" });
});
ftr(s, 2);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 3 — OPENING CASE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Opening Case");
navyBox(s, 0.2, 1.0, 9.6, 2.2,
"Raju, 35-year-old male, smoker, construction worker.\n" +
"3-month history of episodic burning epigastric pain — worse at night, relieved by food and antacids.\n" +
"Takes diclofenac daily for chronic back pain.\n" +
"O/E: mild epigastric tenderness. No guarding. No palpable mass.",
FS_BODY, false, 0.1);
s.addText("Discuss in pairs:", {
x:0.2, y:3.3, w:4.0, h:0.38,
fontSize:FS_SUB, bold:true, color:N, fontFace:"Calibri"
});
div(s, 3.7);
const qs = [
["Q1", "What is your provisional diagnosis?"],
["Q2", "Which risk factors are present?"],
["Q3", "What investigations will you order?"],
["Q4", "What is your immediate management?"]
];
qs.forEach(([num, q], i) => {
const xp = 0.2 + (i%2)*4.92;
const yp = 3.78 + Math.floor(i/2)*0.85;
const navy = i%2===0;
s.addShape("roundRect", { x:xp, y:yp, w:4.72, h:0.76, fill:{color:navy?N:W}, line:{color:N,width:1.5}, rectRadius:0.08 });
s.addText(num, { x:xp+0.1, y:yp, w:0.55, h:0.76, fontSize:FS_SUB, bold:true, color:navy?NT:N, fontFace:"Calibri", align:"center", valign:"middle" });
s.addShape("rect", { x:xp+0.72, y:yp+0.1, w:0.04, h:0.56, fill:{color:navy?NL:NT} });
s.addText(q, { x:xp+0.84, y:yp, w:3.76, h:0.76, fontSize:FS_BODY, color:navy?W:N, fontFace:"Calibri", valign:"middle" });
});
ftr(s, 3);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 4 — DEFINITION & COMMON SITES
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Definition & Common Sites");
// Definition banner
s.addShape("roundRect", { x:0.2, y:1.0, w:9.6, h:0.78, fill:{color:NT}, line:{color:N,width:1.5}, rectRadius:0.08 });
s.addText("Definition:", { x:0.32, y:1.0, w:1.6, h:0.78, fontSize:FS_SUB, bold:true, color:N, fontFace:"Calibri", valign:"middle" });
s.addShape("rect", { x:1.98, y:1.14, w:0.04, h:0.5, fill:{color:N} });
s.addText("A breach in GI mucosa extending through muscularis mucosae, exposed to acid-pepsin.", {
x:2.1, y:1.0, w:7.6, h:0.78, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle"
});
// Sites table
s.addText("Common Sites", {
x:0.2, y:1.88, w:4.7, h:0.38,
fontSize:FS_SUB, bold:true, color:N, fontFace:"Calibri"
});
const sHdr = ["Site", "Note"];
const sX = [0.2, 3.2];
const sW = [2.95, 1.65];
sHdr.forEach((h, i) => navyBox(s, sX[i], 2.3, sW[i], 0.36, h, 14, true, 0));
const sites = [
["1st part of duodenum", "Most common"],
["Lesser curve of stomach", "Gastric ulcer"],
["Prepyloric / Pyloric channel", "Behaves like DU"],
["Post-surgical stoma", "Stomal ulcer"],
["Meckel's diverticulum", "Ectopic mucosa"]
];
sites.forEach(([site, note], i) => {
const bg = i%2===0 ? NT : W;
s.addShape("rect", { x:0.2, y:2.68+i*0.36, w:2.95, h:0.34, fill:{color:bg}, line:{color:NT,width:0.5} });
s.addText(site, { x:0.3, y:2.68+i*0.36, w:2.8, h:0.34, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle" });
s.addShape("rect", { x:3.2, y:2.68+i*0.36, w:1.65, h:0.34, fill:{color:bg}, line:{color:NT,width:0.5} });
s.addText(note, { x:3.3, y:2.68+i*0.36, w:1.5, h:0.34, fontSize:FS_BODY, color:N, fontFace:"Calibri", valign:"middle", italic:true });
});
// Right column: key rules
s.addText("Key Rules", {
x:5.2, y:1.88, w:4.6, h:0.38,
fontSize:FS_SUB, bold:true, color:N, fontFace:"Calibri"
});
div(s, 2.28);
const rules = [
{ t:"No acid = No ulcer (Schwartz's law)", warn:false },
{ t:"Ulcer forms at epithelial junctions", warn:false },
{ t:"Anterior DU → tends to perforate", warn:true },
{ t:"Posterior DU → tends to bleed (GDA)", warn:true },
{ t:"Kissing ulcers: anterior + posterior DU", warn:false },
{ t:"ALL gastric ulcers must be biopsied", warn:true },
{ t:"Giant DU — malignancy extremely rare", warn:false }
];
rules.forEach((r, i) => {
s.addShape("roundRect", {
x:5.2, y:2.36+i*0.44, w:4.6, h:0.4,
fill:{color: r.warn ? N : NT}, line:{color:N,width:0.8}, rectRadius:0.05
});
s.addText(`${r.warn?"▶":"•"} ${r.t}`, {
x:5.3, y:2.36+i*0.44, w:4.4, h:0.4,
fontSize:FS_BODY, color:r.warn?W:TXT, fontFace:"Calibri", bold:r.warn, valign:"middle"
});
});
ftr(s, 4);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 5 — AETIOLOGY FLOWCHART
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Aetiology — Causes of Peptic Ulcer Disease");
navyBox(s, 3.82, 2.3, 2.36, 0.72, "PEPTIC ULCER", 22, true, 0.1);
const leftC = [
["H. pylori Infection\n(80% DU, 60% GU)", 0.2, 1.02],
["NSAIDs / Aspirin\n(↓ PGE2 → ↓ mucus)", 0.2, 2.05],
["Cigarette Smoking\n(↓ defence, ↑ relapse)", 0.2, 3.08],
["Steroids\n(Combined with NSAIDs)", 0.2, 4.11]
];
leftC.forEach(([txt, x, y]) => {
navyBox(s, x, y, 2.35, 0.7, txt, FS_BODY, true, 0.08);
s.addShape("rect", { x:2.58, y:y+0.33, w:1.2, h:0.04, fill:{color:N} });
rArr(s, 3.75, y+0.35);
});
const rightC = [
["Zollinger-Ellison\n(Gastrinoma → ↑↑ gastrin)", 7.45, 1.02],
["Stress Ulcers\n(ICU, burns, Cushing's)", 7.45, 2.05],
["Blood Group O\n(Genetic predisposition)", 7.45, 3.08],
["Alcohol / Bile Reflux\n(Minor role)", 7.45, 4.11]
];
rightC.forEach(([txt, x, y]) => {
outBox(s, x, y, 2.35, 0.7, txt, FS_BODY, false);
lArr(s, 6.98, y+0.35);
s.addShape("rect", { x:6.18, y:y+0.33, w:0.8, h:0.04, fill:{color:N} });
});
s.addShape("roundRect", { x:0.2, y:4.9, w:9.6, h:0.46, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.06 });
s.addText("H. pylori + NSAIDs account for >90% of all peptic ulcers | Smoking doubles the relapse rate", {
x:0.3, y:4.9, w:9.4, h:0.46, fontSize:FS_BODY, bold:true, color:N, fontFace:"Calibri", align:"center", valign:"middle"
});
ftr(s, 5);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 6 — PATHOPHYSIOLOGY
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Pathophysiology — Imbalance of Forces");
// Aggressive column
s.addShape("roundRect", { x:0.2, y:1.0, w:4.0, h:4.38, fill:{color:NT}, line:{color:N,width:1.5}, rectRadius:0.1 });
navyBox(s, 0.2, 1.0, 4.0, 0.52, "AGGRESSIVE FACTORS", FS_SUB, true, 0.1);
const agg = [
"Hydrochloric acid (HCl)",
"Pepsin",
"H. pylori (urease, VacA, CagA)",
"NSAIDs → inhibit COX-1 → ↓ PGE2",
"Bile reflux",
"Reactive oxygen species",
"Stress hormones (cortisol)"
];
agg.forEach((a, i) => {
s.addShape("rect", { x:0.36, y:1.62+i*0.4, w:0.16, h:0.28, fill:{color:N} });
s.addText(a, { x:0.58, y:1.6+i*0.4, w:3.48, h:0.36, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle" });
});
// Balance
s.addShape("roundRect", { x:4.28, y:2.15, w:1.44, h:1.62, fill:{color:N}, rectRadius:0.1 });
s.addText("IMBALANCE\n=\nULCER", { x:4.28, y:2.15, w:1.44, h:1.62, fontSize:20, bold:true, color:W, fontFace:"Calibri", align:"center", valign:"middle" });
// Defensive column
s.addShape("roundRect", { x:5.8, y:1.0, w:4.0, h:4.38, fill:{color:NT}, line:{color:N,width:1.5}, rectRadius:0.1 });
navyBox(s, 5.8, 1.0, 4.0, 0.52, "DEFENSIVE FACTORS", FS_SUB, true, 0.1);
const def = [
"Mucus-bicarbonate barrier",
"Prostaglandin E2 (PGE2)",
"Mucosal blood flow",
"Tight epithelial junctions",
"Epithelial restitution (repair)",
"Trefoil peptides",
"Duodenal alkaline secretion"
];
def.forEach((d, i) => {
s.addShape("roundRect", { x:5.97, y:1.62+i*0.4, w:0.22, h:0.28, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.04 });
s.addText("✓", { x:5.97, y:1.62+i*0.4, w:0.22, h:0.28, fontSize:11, bold:true, color:N, fontFace:"Calibri", align:"center", valign:"middle" });
s.addText(d, { x:6.25, y:1.6+i*0.4, w:3.48, h:0.36, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle" });
});
navyBox(s, 0.2, 5.28, 9.6, 0.3, "H. pylori → Urease → NH3 → Epithelial toxicity + ↑ Gastrin → ↑↑ Acid → Ulcer", 16, true, 0.05);
ftr(s, 6);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 7 — H. PYLORI
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "H. pylori — The Ulcer Pathogen");
const stats = [
["Gram-negative\nSpiral rod", "Morphology"],
["Urease +ve\nRapid CLO", "Key property"],
["Gastric\nantrum", "Location"],
["WHO Class I\nCarcinogen", "Risk"],
[">50% world\npopulation", "Prevalence"]
];
stats.forEach(([val, label], i) => {
navyBox(s, 0.2+i*1.93, 1.0, 1.78, 0.9, val, 20, true, 0.08);
s.addText(label, { x:0.2+i*1.93, y:1.92, w:1.78, h:0.28, fontSize:14, color:NG, fontFace:"Calibri", align:"center", italic:true });
});
s.addText("Virulence Factors", {
x:0.2, y:2.28, w:4.7, h:0.38,
fontSize:FS_SUB, bold:true, color:N, fontFace:"Calibri"
});
div(s, 2.68);
const vf = [
"Urease → NH3 + CO2 → local toxicity",
"VacA → vacuolating cytotoxin, epithelial injury",
"CagA → cag pathogenicity island, inflammation",
"BabA → adhesin, binds Lewis blood group antigens",
"OipA → outer inflammatory protein"
];
vf.forEach((v, i) => {
s.addShape("rect", { x:0.2, y:2.74+i*0.4, w:4.7, h:0.38, fill:{color:i%2===0?NT:W}, line:{color:NT,width:0.5} });
s.addText(`• ${v}`, { x:0.3, y:2.74+i*0.4, w:4.55, h:0.38, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle" });
});
s.addText("Diagnosis Methods", {
x:5.2, y:2.28, w:4.6, h:0.38,
fontSize:FS_SUB, bold:true, color:N, fontFace:"Calibri"
});
div(s, 2.68);
const diag = [
["Urea Breath Test", "Non-invasive, 95% sensitivity", true],
["CLO test (biopsy)", "Invasive, rapid, cheap", true],
["Stool Antigen Test", "Non-invasive, confirms active", true],
["Serology IgG", "Cannot confirm active infection", false],
["Histology (biopsy)", "Gold standard", true]
];
diag.forEach(([test, note, pref], i) => {
s.addShape("roundRect", {
x:5.2, y:2.74+i*0.4, w:4.6, h:0.36,
fill:{color:pref?N:NT}, line:{color:N,width:0.8}, rectRadius:0.04
});
s.addText(test, { x:5.28, y:2.74+i*0.4, w:2.1, h:0.36, fontSize:FS_BODY, bold:pref, color:pref?W:TXT, fontFace:"Calibri", valign:"middle" });
s.addText(note, { x:7.44, y:2.74+i*0.4, w:2.28, h:0.36, fontSize:FS_BODY-2, color:pref?NT:NG, fontFace:"Calibri", italic:true, valign:"middle" });
});
ftr(s, 7);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 8 — DU vs GU
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Duodenal Ulcer vs Gastric Ulcer");
const cW = [2.55, 3.42, 3.42];
const cX = [0.2, 2.78, 6.23];
const cols = ["Feature", "Duodenal Ulcer", "Gastric Ulcer"];
cols.forEach((c, i) => navyBox(s, cX[i], 1.0, cW[i], 0.44, c, 20, true, 0));
const rows = [
["Incidence", "More common (4:1)", "Less common"],
["Age", "30 – 50 years", "50 – 70 years"],
["Gender", "Male > Female (3:1)", "Male = Female"],
["Acid", "Increased or normal", "Normal or reduced"],
["H. pylori", "~80% of cases", "~60% of cases"],
["Malignancy", "Virtually never", "Must always exclude!"],
["Night pain", "Food relieves pain", "Food may worsen"],
["Weight", "Normal or gain", "Weight loss"],
["Perforation", "Anterior wall — common", "Rare"],
["Bleeding", "Posterior — erodes GDA", "Lesser curve"]
];
rows.forEach((row, r) => {
const bg = r%2===0 ? NT : W;
row.forEach((cell, c) => {
s.addShape("rect", { x:cX[c], y:1.46+r*0.36, w:cW[c], h:0.34, fill:{color:bg}, line:{color:NT,width:0.5} });
s.addText(cell, {
x:cX[c]+0.08, y:1.46+r*0.36, w:cW[c]-0.12, h:0.34,
fontSize:FS_BODY, bold:c===0, color:c===0?N:TXT,
fontFace:"Calibri", valign:"middle"
});
});
});
s.addShape("roundRect", { x:0.2, y:5.08, w:9.6, h:0.32, fill:{color:N}, rectRadius:0.05 });
s.addText("▶ All gastric ulcers must be biopsied to exclude malignancy", {
x:0.3, y:5.08, w:9.4, h:0.32, fontSize:FS_BODY, bold:true, color:W, fontFace:"Calibri", align:"center", valign:"middle"
});
ftr(s, 8);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 9 — CLINICAL FEATURES
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Clinical Features");
const cards = [
{ title:"PAIN", items:["Epigastric burning / gnawing","Radiates to back","Episodic — weeks/months pattern","Night waking — classic DU"] },
{ title:"RELIEF", items:["Food relieves pain (DU typical)","Antacids give temporary relief","Spontaneous healing & recurrence","Periodicity — hallmark of PUD"] },
{ title:"OTHER", items:["Nausea, occasional vomiting","Weight loss (GU) or gain (DU)","Anaemia — chronic blood loss","Projectile vomiting → stenosis"] }
];
cards.forEach((card, i) => {
navyBox(s, 0.2+i*3.27, 1.0, 3.12, 0.44, card.title, FS_SUB, true, 0.08);
s.addShape("roundRect", { x:0.2+i*3.27, y:1.46, w:3.12, h:1.9, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.08 });
card.items.forEach((item, j) => {
s.addText(`• ${item}`, { x:0.32+i*3.27, y:1.52+j*0.44, w:2.9, h:0.42, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"top" });
});
});
s.addText("Clinical Signs:", {
x:0.2, y:3.45, w:3.5, h:0.38,
fontSize:FS_SUB, bold:true, color:N, fontFace:"Calibri"
});
div(s, 3.85);
const signs = [
{ t:"Mild epigastric tenderness — uncomplicated PUD", warn:false },
{ t:"Succussion splash → gastric outlet obstruction", warn:true },
{ t:"Board-like rigidity, absent bowel sounds → perforation", warn:true },
{ t:"Melaena / PR bleed → upper GI haemorrhage", warn:true },
{ t:"Palpable epigastric mass → malignancy — urgent OGD", warn:true }
];
signs.forEach((sign, i) => {
s.addShape("roundRect", {
x:0.2, y:3.92+i*0.36, w:9.6, h:0.32,
fill:{color:sign.warn?N:NT}, line:{color:N,width:0.8}, rectRadius:0.05
});
s.addText(`${sign.warn?"▶":"•"} ${sign.t}`, {
x:0.3, y:3.92+i*0.36, w:9.4, h:0.32,
fontSize:FS_BODY, color:sign.warn?W:TXT, fontFace:"Calibri", bold:sign.warn, valign:"middle"
});
});
ftr(s, 9);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 10 — INVESTIGATIONS FLOWCHART
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Investigations — Stepwise Approach");
navyBox(s, 3.5, 1.02, 3.0, 0.52, "Suspected PUD\n(Symptoms + Risk Factors)", 18, true, 0.08);
dArr(s, 5.0, 1.57);
tintBox(s, 3.18, 1.9, 3.64, 0.48, "Age <55, no alarm features?", 20, false);
s.addText("YES", { x:1.82, y:1.94, w:1.3, h:0.22, fontSize:16, bold:true, color:N, fontFace:"Calibri", align:"center" });
s.addText("NO / ALARM", { x:6.9, y:1.9, w:2.1, h:0.28, fontSize:16, bold:true, color:N, fontFace:"Calibri", align:"center" });
lArr(s, 1.62, 2.14); s.addShape("rect", { x:1.9, y:2.12, w:1.24, h:0.04, fill:{color:N} });
rArr(s, 6.82, 2.14); s.addShape("rect", { x:6.82, y:2.12, w:1.1, h:0.04, fill:{color:N} });
navyBox(s, 0.2, 1.9, 1.38, 0.48, "Test &\nTreat", 16, true, 0.08);
outBox(s, 8.06, 1.9, 1.74, 0.48, "Urgent\nOGD", 16, false);
dArr(s, 5.0, 2.42);
navyBox(s, 3.18, 2.75, 3.64, 0.48, "OGD (Gold Standard)\n+ Biopsy if gastric ulcer", 18, true, 0.08);
dArr(s, 5.0, 3.26);
tintBox(s, 3.18, 3.6, 3.64, 0.48, "H. pylori Testing\n(CLO / histology)", 18, false);
s.addText("+ve", { x:1.62, y:3.64, w:1.5, h:0.22, fontSize:16, bold:true, color:N, fontFace:"Calibri", align:"center" });
s.addText("−ve", { x:6.9, y:3.64, w:1.2, h:0.22, fontSize:16, bold:true, color:N, fontFace:"Calibri", align:"center" });
lArr(s, 1.62, 3.84); s.addShape("rect", { x:1.9, y:3.82, w:1.24, h:0.04, fill:{color:N} });
rArr(s, 6.82, 3.84); s.addShape("rect", { x:6.82, y:3.82, w:1.16, h:0.04, fill:{color:N} });
navyBox(s, 0.2, 3.6, 1.38, 0.48, "Eradicate\nH. pylori", 16, true, 0.08);
tintBox(s, 8.06, 3.6, 1.74, 0.48, "Review\ncause", 16, false);
// Additional tests
const tests = ["FBC + LFT", "Erect CXR\n(free gas)", "CT Abdomen", "Serum Amylase", "Fasting Gastrin\n(ZE syndrome)"];
s.addText("Additional Tests:", { x:0.2, y:4.22, w:2.5, h:0.3, fontSize:FS_SUB, bold:true, color:N, fontFace:"Calibri" });
tests.forEach((t, i) => navyBox(s, 0.2+i*1.93, 4.56, 1.82, 0.46, t, 16, true, 0.06));
ftr(s, 10);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 11 — ENDOSCOPY & RADIOLOGY IMAGES
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Endoscopic & Radiological Appearance");
s.addText("Gold Standard: Oesophago-gastro-duodenoscopy (OGD)", {
x:0.2, y:1.0, w:9.6, h:0.36,
fontSize:FS_SUB, bold:true, color:N, fontFace:"Calibri", align:"center"
});
if (imgDuodenal) {
s.addImage({ data:imgDuodenal, x:0.2, y:1.42, w:4.65, h:3.48 });
} else {
s.addShape("rect", { x:0.2, y:1.42, w:4.65, h:3.48, fill:{color:NT} });
s.addText("Duodenal Ulcer — OGD", { x:0.2, y:1.42, w:4.65, h:3.48, fontSize:FS_BODY, color:N, fontFace:"Calibri", align:"center", valign:"middle" });
}
navyBox(s, 0.2, 4.92, 4.65, 0.42, "Duodenal ulcer at gastroduodenoscopy\n(Fig 67.10 — Bailey & Love)", 16, false, 0.06);
if (imgBarium) {
s.addImage({ data:imgBarium, x:5.15, y:1.42, w:4.65, h:3.48 });
} else {
s.addShape("rect", { x:5.15, y:1.42, w:4.65, h:3.48, fill:{color:NT} });
s.addText("Barium Meal — DU", { x:5.15, y:1.42, w:4.65, h:3.48, fontSize:FS_BODY, color:N, fontFace:"Calibri", align:"center", valign:"middle" });
}
navyBox(s, 5.15, 4.92, 4.65, 0.42, "Duodenal ulcer on barium meal\n(Fig 67.11 — Bailey & Love)", 16, false, 0.06);
ftr(s, 11);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 12 — MEDICAL MANAGEMENT STEP-UP
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Medical Management — Step-Up Approach");
const steps = [
{ n:"1", title:"Lifestyle", items:["Stop NSAIDs / aspirin","Quit smoking and alcohol","Avoid spicy food","Reduce stress"] },
{ n:"2", title:"Acid Suppression", items:["Omeprazole 20–40 mg OD","Lansoprazole 30 mg OD","Pantoprazole 40 mg OD","Duration: 4–8 weeks"] },
{ n:"3", title:"H. pylori Rx", items:["Triple therapy 7–14 days","PPI + Amox + Clarithro","Confirm with UBT ≥4 wk","Quadruple if 1st fails"] },
{ n:"4", title:"Follow-Up OGD", items:["Repeat OGD at 8 weeks (GU)","Confirm ulcer healing","Re-biopsy if non-healing","Exclude malignancy"] }
];
steps.forEach((step, i) => {
const x = 0.2 + i*2.43;
navyBox(s, x, 1.0, 2.28, 0.46, `Step ${step.n}`, FS_SUB, true, 0.08);
tintBox(s, x, 1.48, 2.28, 0.44, step.title, FS_BODY, true);
s.addShape("roundRect", { x, y:1.94, w:2.28, h:3.3, fill:{color:W}, line:{color:N,width:1}, rectRadius:0.07 });
step.items.forEach((item, j) => {
s.addText(`• ${item}`, { x:x+0.1, y:2.02+j*0.65, w:2.1, h:0.62, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"top", wrap:true });
});
if (i<3) rArr(s, x+2.3, 2.6);
});
s.addShape("roundRect", { x:0.2, y:5.3, w:9.6, h:0.28, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.05 });
s.addText("Eradication rate ~80–90% | Confirm cure with Urea Breath Test ≥4 weeks after stopping PPI & antibiotics", {
x:0.3, y:5.3, w:9.4, h:0.28, fontSize:18, bold:true, color:N, fontFace:"Calibri", align:"center", valign:"middle"
});
ftr(s, 12);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 13 — ERADICATION REGIMENS
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "H. pylori Eradication Therapy");
navyBox(s, 0.2, 1.0, 4.65, 0.44, "TRIPLE THERAPY — First Line", FS_SUB, true, 0.08);
s.addShape("roundRect", { x:0.2, y:1.46, w:4.65, h:3.82, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.08 });
const triple = [
["PPI (standard dose)", "Twice daily"],
["+ Amoxicillin 1g", "Twice daily"],
["+ Clarithromycin 500mg", "Twice daily"],
["OR (pen. allergy):", "PPI + Metronidazole + Clarithro"],
["Duration:", "7 – 14 days"],
["Success rate:", "~80 – 90%"],
["Confirm cure:", "UBT ≥4 weeks post-treatment"]
];
triple.forEach(([label, val], i) => {
const isPlus = label.startsWith("+");
s.addShape("roundRect", { x:0.3, y:1.54+i*0.5, w:2.0, h:0.42, fill:{color:isPlus?N:NL}, rectRadius:0.04 });
s.addText(label, { x:0.3, y:1.54+i*0.5, w:2.0, h:0.42, fontSize:FS_BODY, bold:true, color:W, fontFace:"Calibri", align:"center", valign:"middle" });
s.addText(val, { x:2.36, y:1.56+i*0.5, w:2.38, h:0.4, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle" });
});
navyBox(s, 5.0, 1.0, 4.8, 0.44, "QUADRUPLE THERAPY — Second Line", FS_SUB, true, 0.08);
s.addShape("roundRect", { x:5.0, y:1.46, w:4.8, h:2.0, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.08 });
const quad = [["PPI","BD"], ["+ Bismuth subcitrate","QID"], ["+ Tetracycline 500mg","QID"], ["+ Metronidazole 400mg","TID | 10–14 days"]];
quad.forEach(([label, val], i) => {
s.addShape("roundRect", { x:5.1, y:1.54+i*0.44, w:2.1, h:0.38, fill:{color:N}, rectRadius:0.04 });
s.addText(label, { x:5.1, y:1.54+i*0.44, w:2.1, h:0.38, fontSize:FS_BODY, bold:true, color:W, fontFace:"Calibri", align:"center", valign:"middle" });
s.addText(val, { x:7.26, y:1.56+i*0.44, w:2.46, h:0.36, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle" });
});
navyBox(s, 5.0, 3.52, 4.8, 0.42, "Common Pitfalls", FS_SUB, true, 0.08);
s.addShape("roundRect", { x:5.0, y:3.96, w:4.8, h:1.56, fill:{color:W}, line:{color:N,width:1.5}, rectRadius:0.08 });
const pitfalls = [
"Stop PPI 2 weeks before UBT (prevents false negative)",
"Complete the full antibiotic course",
"Clarithromycin resistance is rising globally",
"Test & Treat for dyspepsia in patients <55 years",
"Always confirm eradication after treatment"
];
pitfalls.forEach((p, i) => {
s.addText(`▶ ${p}`, { x:5.1, y:4.02+i*0.3, w:4.62, h:0.28, fontSize:FS_BODY, color:N, fontFace:"Calibri", bold:i===0, valign:"middle" });
});
ftr(s, 13);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 14 — COMPLICATIONS OVERVIEW
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Complications of Peptic Ulcer Disease");
navyBox(s, 3.82, 2.28, 2.36, 0.76, "PEPTIC ULCER\nCOMPLICATIONS", 20, true, 0.1);
const comps = [
{ name:"PERFORATION\n(Most dangerous)", x:0.2, y:1.02, navy:true },
{ name:"HAEMORRHAGE\n(Most common)", x:7.62, y:1.02, navy:false },
{ name:"PYLORIC STENOSIS\n(Gastric outlet obstruction)", x:0.2, y:3.65, navy:false },
{ name:"MALIGNANCY\n(Gastric ulcer — biopsy all)", x:7.62, y:3.65, navy:true }
];
comps.forEach(c => {
if (c.navy) navyBox(s, c.x, c.y, 2.36, 1.02, c.name, FS_SUB, true, 0.1);
else outBox(s, c.x, c.y, 2.36, 1.02, c.name, FS_SUB, true);
s.addShape("rect", { x:c.x+2.36, y:c.y+0.47, w:1.26, h:0.04, fill:{color:N} });
});
s.addShape("roundRect", { x:0.2, y:4.75, w:9.6, h:0.72, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.08 });
const facts = [
"Perforation: Sudden pain, free gas CXR >50%",
"Haemorrhage: Forrest class guides endoscopy",
"Stenosis: Succussion splash, metabolic alkalosis",
"Malignancy: GU only — biopsy is mandatory"
];
facts.forEach((f, i) => {
s.addText(`• ${f}`, { x:0.3+Math.floor(i/2)*4.85, y:4.82+(i%2)*0.3, w:4.65, h:0.28, fontSize:FS_BODY, color:N, fontFace:"Calibri", bold:false });
});
ftr(s, 14);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 15 — PERFORATED PEPTIC ULCER + CXR
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Complication 1 — Perforated Peptic Ulcer");
navyBox(s, 0.2, 1.0, 4.65, 0.44, "Clinical Features", FS_SUB, true, 0.07);
s.addShape("roundRect", { x:0.2, y:1.46, w:4.65, h:2.32, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.08 });
const pf = [
"Sudden severe epigastric pain",
"Board-like rigidity of abdomen",
"Right shoulder tip pain (phrenic)",
"Shock: tachycardia, hypotension",
"Abdomen still — no resp. movement",
"Fever — hours after perforation"
];
pf.forEach((p, i) => {
s.addText(`• ${p}`, { x:0.32, y:1.52+i*0.37, w:4.45, h:0.34, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle" });
});
navyBox(s, 5.0, 1.0, 4.8, 0.44, "Management", FS_SUB, true, 0.07);
s.addShape("roundRect", { x:5.0, y:1.46, w:4.8, h:2.32, fill:{color:W}, line:{color:N,width:1}, rectRadius:0.08 });
const pm = [
"1. IV fluids + resuscitation",
"2. Analgesia — do NOT withhold",
"3. NGT + urinary catheter",
"4. Erect CXR → free gas?",
"5. CT abdomen — most accurate",
"6. Surgery: laparotomy / laparoscopy"
];
pm.forEach((p, i) => {
s.addText(p, { x:5.1, y:1.52+i*0.37, w:4.62, h:0.34, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle", bold:i===5 });
});
// CXR image
if (imgCXR) {
s.addImage({ data:imgCXR, x:0.2, y:3.85, w:3.8, h:1.72 });
} else {
s.addShape("rect", { x:0.2, y:3.85, w:3.8, h:1.72, fill:{color:NT} });
s.addText("Erect CXR — Free air\n[Fig 67.22 Bailey & Love]", { x:0.2, y:3.85, w:3.8, h:1.72, fontSize:FS_BODY, color:N, fontFace:"Calibri", align:"center", valign:"middle" });
}
s.addText("Fig 67.22: Free air under right diaphragm — perforated DU", { x:0.2, y:5.56, w:3.8, h:0.16, fontSize:11, color:NG, fontFace:"Calibri", italic:true, align:"center" });
navyBox(s, 4.1, 3.85, 5.7, 0.42, "Surgical Options", FS_SUB, true, 0.07);
const sops = [
"Graham's omental patch repair — DU perforation",
"Excise + close — GU (histology mandatory)",
"Laparoscopic repair if expertise available",
"Roux-en-Y gastrectomy — massive perforation"
];
sops.forEach((op, i) => {
s.addShape("roundRect", { x:4.1, y:4.3+i*0.36, w:5.7, h:0.32, fill:{color:i%2===0?NT:W}, line:{color:NT,width:0.5}, rectRadius:0.04 });
s.addText(`• ${op}`, { x:4.2, y:4.3+i*0.36, w:5.5, h:0.32, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle" });
});
ftr(s, 15);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 16 — GI HAEMORRHAGE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Complication 2 — Upper GI Haemorrhage");
s.addShape("roundRect", { x:0.2, y:1.0, w:9.6, h:0.44, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.06 });
s.addText("Incidence >100/100,000/yr | Mortality 10–14% | Rises with age | Strongly associated with NSAIDs", {
x:0.3, y:1.0, w:9.4, h:0.44, fontSize:FS_BODY, bold:true, color:N, fontFace:"Calibri", align:"center", valign:"middle"
});
navyBox(s, 0.2, 1.52, 5.05, 0.42, "Forrest Classification (Endoscopic)", FS_SUB, true, 0.07);
const fX = [0.2, 1.46, 3.26];
const fW = [1.22, 1.78, 1.95];
["Class","Description","Re-bleed Risk"].forEach((h, i) => tintBox(s, fX[i], 1.96, fW[i], 0.32, h, 16, true));
const forrest = [
["Ia","Spurting arterial bleed","55%", true],
["Ib","Oozing bleed","55%", true],
["IIa","Non-bleeding visible vessel","43%", true],
["IIb","Adherent clot","22%", false],
["IIc","Haematin stained base","10%", false],
["III","Clean ulcer base","5%", false]
];
forrest.forEach(([cls, desc, risk, endo], i) => {
const bg = endo ? N : (i%2===0 ? NT : W);
const tc = endo ? W : TXT;
[0,1,2].forEach(ci => {
s.addShape("rect", { x:fX[ci], y:2.3+i*0.33, w:fW[ci], h:0.31, fill:{color:bg}, line:{color:NT,width:0.5} });
s.addText([cls,desc,risk][ci], { x:fX[ci]+0.06, y:2.3+i*0.33, w:fW[ci]-0.1, h:0.31, fontSize:FS_BODY, color:tc, fontFace:"Calibri", bold:ci===0&&endo, valign:"middle" });
});
});
s.addText("Ia–IIa = Endoscopic therapy indicated", { x:0.2, y:4.32, w:5.05, h:0.26, fontSize:18, color:N, bold:true, fontFace:"Calibri", italic:true });
navyBox(s, 5.35, 1.52, 4.45, 0.42, "Management Ladder", FS_SUB, true, 0.07);
const mgmt = [
["Resuscitation", "IV access, fluids, blood products"],
["IV PPI infusion", "Omeprazole 80mg bolus + infusion"],
["Urgent OGD", "Within 24 hrs (12 hrs if unstable)"],
["Endoscopic Rx", "Adrenaline + clips / heater probe"],
["Interventional Radiology","If endoscopy fails"],
["Surgery", "Underrunning / gastrectomy (last resort)"]
];
mgmt.forEach(([step, detail], i) => {
navyBox(s, 5.35, 1.96+i*0.55, 1.8, 0.46, step, 18, true, 0.05);
s.addText(detail, { x:7.2, y:2.0+i*0.55, w:2.58, h:0.4, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle", italic:true });
if (i<5) dArr(s, 6.25, 2.44+i*0.55);
});
ftr(s, 16);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 17 — PYLORIC STENOSIS & ZE SYNDROME
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Pyloric Stenosis & Zollinger-Ellison Syndrome");
navyBox(s, 0.2, 1.0, 4.65, 0.44, "Pyloric Stenosis", FS_SUB, true, 0.08);
s.addShape("roundRect", { x:0.2, y:1.46, w:4.65, h:4.0, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.08 });
const pyloric = [
["Cause", "Fibrosis from chronic ulcer scarring"],
["Symptoms", "Persistent non-bilious vomiting"],
["Classic sign", "Succussion splash"],
["Vomit pattern", "Projectile, contains old food"],
["Metabolic", "Hypokalaemic hypochloraemic alkalosis"],
["Investigation", "OGD + barium meal"],
["Treatment", "Resuscitate → endoscopic dilation"],
["Surgery", "Pyloroplasty or gastrojejunostomy"]
];
pyloric.forEach(([label, val], i) => {
const bg = i%2===0 ? W : NT;
s.addShape("rect", { x:0.3, y:1.54+i*0.46, w:4.45, h:0.44, fill:{color:bg}, line:{color:NT,width:0.4} });
s.addText(label+":", { x:0.38, y:1.54+i*0.46, w:1.5, h:0.44, fontSize:FS_BODY, bold:true, color:N, fontFace:"Calibri", valign:"middle" });
s.addText(val, { x:1.92, y:1.54+i*0.46, w:2.76, h:0.44, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle" });
});
navyBox(s, 5.0, 1.0, 4.8, 0.44, "Zollinger-Ellison Syndrome", FS_SUB, true, 0.08);
s.addShape("roundRect", { x:5.0, y:1.46, w:4.8, h:4.0, fill:{color:W}, line:{color:N,width:1}, rectRadius:0.08 });
const ze = [
["Cause", "Gastrinoma (pancreas / duodenum)"],
["Pathology", "↑↑ Gastrin → ↑↑ Acid → multiple ulcers"],
["Symptoms", "Refractory / multiple / unusual PUD"],
["Diarrhoea", "Acid inactivates pancreatic enzymes"],
["Diagnosis", "Fasting gastrin >1000 pg/mL"],
["Secretin test","Paradoxical rise in gastrin"],
["Imaging", "CT / MRI / Octreotide scan"],
["Treatment", "High-dose PPI + tumour resection"]
];
ze.forEach(([label, val], i) => {
const bg = i%2===0 ? NT : W;
s.addShape("rect", { x:5.1, y:1.54+i*0.46, w:4.62, h:0.44, fill:{color:bg}, line:{color:NT,width:0.4} });
s.addText(label+":", { x:5.18, y:1.54+i*0.46, w:1.6, h:0.44, fontSize:FS_BODY, bold:true, color:N, fontFace:"Calibri", valign:"middle" });
s.addText(val, { x:6.82, y:1.54+i*0.46, w:2.85, h:0.44, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle" });
});
ftr(s, 17);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 18 — SURGICAL MANAGEMENT
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Surgical Management of PUD");
navyBox(s, 0.2, 1.0, 9.6, 0.52,
"Indications: Perforation | Uncontrolled Haemorrhage | Malignancy (GU) | Gastric Outlet Obstruction | Failed Medical Therapy",
FS_BODY, true, 0.08);
navyBox(s, 0.2, 1.6, 4.65, 0.44, "For Duodenal Ulcer", FS_SUB, true, 0.07);
s.addShape("roundRect", { x:0.2, y:2.06, w:4.65, h:3.24, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.08 });
const duOps = [
"Omental patch repair (Graham's) — perforation",
"Truncal vagotomy + drainage (pyloroplasty)",
"Highly selective vagotomy — fewest side effects",
"Billroth II / Pólya — complex emergency only",
"Vagotomy reduces acid output by ~50%",
"Heineke–Mikulicz pyloroplasty for drainage",
"Elective surgery now performed in <1% cases"
];
duOps.forEach((op, i) => {
s.addText(`• ${op}`, { x:0.32, y:2.12+i*0.44, w:4.42, h:0.42, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle", wrap:true });
});
navyBox(s, 5.0, 1.6, 4.8, 0.44, "For Gastric Ulcer", FS_SUB, true, 0.07);
s.addShape("roundRect", { x:5.0, y:2.06, w:4.8, h:3.24, fill:{color:W}, line:{color:N,width:1}, rectRadius:0.08 });
const guOps = [
"Always excise ulcer — histology is mandatory",
"Billroth I gastrectomy — standard operation",
"Roux-en-Y reconstruction — massive perf",
"Wedge excision — small accessible ulcers",
"Subtotal gastrectomy if malignant",
"Cannot distinguish benign vs cancer pre-op",
"Post-op: PPI + H. pylori eradication"
];
guOps.forEach((op, i) => {
s.addText(`• ${op}`, { x:5.1, y:2.12+i*0.44, w:4.62, h:0.42, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle", wrap:true });
});
s.addShape("roundRect", { x:0.2, y:5.38, w:9.6, h:0.26, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.04 });
s.addText("Post-op sequelae: Dumping | Diarrhoea | Bilious vomiting | Small stomach | Malignant transformation 0.5%/yr", {
x:0.3, y:5.38, w:9.4, h:0.26, fontSize:18, color:N, fontFace:"Calibri", align:"center", valign:"middle"
});
ftr(s, 18);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 19 — DUMPING SYNDROME
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Post-surgical — Dumping Syndrome");
const types = [
{
title:"EARLY DUMPING (30 min after meal)",
mech: "Rapid gastric emptying → Osmotic fluid shift in jejunum → Hypovolaemia",
features:["Flushing, palpitations, sweating","Diarrhoea, nausea, cramping","Onset: 15–30 min after eating","Lasts 1–2 hours"],
x:0.2, navy:true
},
{
title:"LATE DUMPING (2–3 hrs after meal)",
mech: "Rapid glucose absorption → ↑↑ Insulin → Reactive hypoglycaemia",
features:["Sweating, tremor, faintness","Hunger, weakness, confusion","Onset: 2–3 hrs post meal","Relieved by sugar intake"],
x:5.1, navy:false
}
];
types.forEach(t => {
if (t.navy) navyBox(s, t.x, 1.0, 4.72, 0.44, t.title, FS_SUB, true, 0.08);
else outBox(s, t.x, 1.0, 4.72, 0.44, t.title, FS_SUB, true);
s.addShape("roundRect", { x:t.x, y:1.46, w:4.72, h:0.82, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.07 });
s.addText("Mechanism:", { x:t.x+0.1, y:1.5, w:1.5, h:0.26, fontSize:FS_BODY, bold:true, color:N, fontFace:"Calibri" });
s.addText(t.mech, { x:t.x+0.1, y:1.76, w:4.52, h:0.5, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"top", wrap:true });
s.addText("Clinical features:", { x:t.x+0.1, y:2.34, w:2.5, h:0.3, fontSize:FS_BODY, bold:true, color:N, fontFace:"Calibri" });
t.features.forEach((f, i) => {
s.addShape("roundRect", { x:t.x, y:2.68+i*0.44, w:4.72, h:0.4, fill:{color:i%2===0?NT:W}, line:{color:NT,width:0.5}, rectRadius:0.04 });
s.addText(`• ${f}`, { x:t.x+0.1, y:2.68+i*0.44, w:4.54, h:0.4, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle" });
});
});
navyBox(s, 0.2, 4.5, 9.6, 0.44,
"Management: Small frequent meals | Low carb, high protein | Lie down after meals | Octreotide (severe) | Surgical revision (rare)",
FS_BODY, true, 0.07);
ftr(s, 19);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 20 — COMPLETE MANAGEMENT ALGORITHM
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Management Algorithm — PUD");
navyBox(s, 3.6, 1.0, 2.8, 0.48, "Epigastric Pain / Dyspepsia", 18, true, 0.08);
dArr(s, 5.0, 1.52);
tintBox(s, 3.28, 1.85, 3.44, 0.46, "Age <55, no alarm features?", 18, false);
s.addText("YES", { x:1.82, y:1.89, w:1.4, h:0.2, fontSize:16, bold:true, color:N, fontFace:"Calibri", align:"center" });
s.addText("NO / ALARM", { x:6.86, y:1.85, w:2.0, h:0.26, fontSize:16, bold:true, color:N, fontFace:"Calibri", align:"center" });
lArr(s, 1.62, 2.08); s.addShape("rect", { x:1.9, y:2.06, w:1.34, h:0.04, fill:{color:N} });
rArr(s, 6.82, 2.08); s.addShape("rect", { x:6.82, y:2.06, w:1.1, h:0.04, fill:{color:N} });
navyBox(s, 0.2, 1.85, 1.38, 0.46, "Test &\nTreat", 16, true, 0.07);
outBox(s, 8.06, 1.85, 1.74, 0.46, "Urgent\nOGD", 16, false);
dArr(s, 5.0, 2.35);
navyBox(s, 3.28, 2.68, 3.44, 0.46, "OGD + H. pylori test", 18, true, 0.08);
dArr(s, 5.0, 3.18);
tintBox(s, 3.28, 3.51, 3.44, 0.46, "PUD confirmed?", 18, false);
s.addText("YES", { x:1.62, y:3.55, w:1.6, h:0.22, fontSize:16, bold:true, color:N, fontFace:"Calibri", align:"center" });
lArr(s, 1.62, 3.74); s.addShape("rect", { x:1.9, y:3.72, w:1.34, h:0.04, fill:{color:N} });
navyBox(s, 0.2, 3.51, 1.38, 0.46, "PPI +\nEradicate", 16, true, 0.07);
dArr(s, 5.0, 4.01);
tintBox(s, 3.28, 4.34, 3.44, 0.46, "Complication?", 18, false);
const compB = [["Perf\nSurgery",2.5],["Bleed\nOGD Rx",3.7],["Stenosis\nDilate",4.9],["Malignancy\nRefer",6.1]];
compB.forEach(([txt, xp]) => {
dArr(s, xp, 4.84);
navyBox(s, xp-0.62, 5.17, 1.2, 0.52, txt, 16, true, 0.06);
});
s.addShape("roundRect", { x:0.2, y:5.38, w:9.6, h:0.26, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.04 });
s.addText("Alarm Features: Age >55 | Dysphagia | Weight loss | Anaemia | Haematemesis | Palpable mass | Persistent vomiting", {
x:0.3, y:5.38, w:9.4, h:0.26, fontSize:16, bold:true, color:N, fontFace:"Calibri", align:"center", valign:"middle"
});
ftr(s, 20);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 21 — INTERACTIVE MCQs
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "MCQs — Test Yourself!");
const mcqs = [
{ q:"Q1. Most common site of peptic ulcer perforation?",
opts:["A. Lesser curve of stomach","B. 1st part duodenum — anterior wall","C. Prepyloric region","D. 2nd part of duodenum"], ans:1 },
{ q:"Q2. First-line H. pylori eradication therapy?",
opts:["A. H2 blockers + amoxicillin","B. PPI + clarithromycin + amoxicillin","C. Antacids alone","D. Sucralfate + tetracycline"], ans:1 },
{ q:"Q3. Best test to confirm H. pylori eradication?",
opts:["A. Serology IgG","B. CLO test on biopsy","C. Urea Breath Test (UBT)","D. Stool culture"], ans:2 },
{ q:"Q4. Metabolic abnormality in pyloric stenosis?",
opts:["A. Hypokalaemic hyperchloraemic acidosis","B. Hyperkalaemic alkalosis","C. Hypokalaemic hypochloraemic alkalosis","D. Normal electrolytes"], ans:2 }
];
mcqs.forEach((mcq, qi) => {
const yBase = 1.0 + qi*1.14;
s.addShape("roundRect", { x:0.2, y:yBase, w:9.6, h:1.08, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.08 });
s.addText(mcq.q, { x:0.32, y:yBase+0.04, w:9.4, h:0.3, fontSize:FS_BODY, bold:true, color:N, fontFace:"Calibri" });
mcq.opts.forEach((opt, oi) => {
const isAns = oi===mcq.ans;
const xp = 0.3 + (oi%2)*4.82;
const yp = yBase+0.38 + Math.floor(oi/2)*0.34;
s.addShape("roundRect", { x:xp, y:yp, w:4.65, h:0.3, fill:{color:isAns?N:W}, line:{color:N,width:1}, rectRadius:0.04 });
s.addText(opt+(isAns?" ✓":""), {
x:xp+0.08, y:yp, w:4.5, h:0.3,
fontSize:FS_BODY, color:isAns?W:TXT, fontFace:"Calibri", bold:isAns, valign:"middle"
});
});
});
ftr(s, 21);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 22 — SPECIAL SITUATIONS
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Special Situations in PUD");
const specials = [
{ title:"PUD in Elderly", items:["NSAIDs most common cause","Atypical / silent presentation","Higher complication rate","Perforations often in elderly females","Steroids mask peritonism"], navy:true },
{ title:"PUD in Pregnancy", items:["H2 blockers preferred (1st line)","PPIs: use with caution","Avoid clarithromycin","Lifestyle modification first","Metronidazole safe after 1st trimester"], navy:false },
{ title:"PUD + Anticoagulation", items:["High risk of UGIB","Reverse anticoagulation if major bleed","Early OGD mandatory","PPI co-prescription essential","H. pylori test & treat before starting"], navy:false },
{ title:"NSAID-induced PUD", items:["COX-1 inhibition → ↓ PGE2 → ↓ mucus","Use lowest effective NSAID dose","COX-2 selective if high GI risk","Mandatory PPI co-prescription","H. pylori test before starting NSAIDs"], navy:true }
];
specials.forEach((sp, i) => {
const xp = 0.2 + (i%2)*4.92;
const yp = 1.0 + Math.floor(i/2)*2.3;
if (sp.navy) navyBox(s, xp, yp, 4.72, 0.44, sp.title, FS_SUB, true, 0.08);
else outBox(s, xp, yp, 4.72, 0.44, sp.title, FS_SUB, true);
s.addShape("roundRect", { x:xp, y:yp+0.46, w:4.72, h:1.74, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.08 });
sp.items.forEach((item, j) => {
s.addText(`• ${item}`, { x:xp+0.12, y:yp+0.52+j*0.33, w:4.5, h:0.3, fontSize:FS_BODY, color:TXT, fontFace:"Calibri" });
});
});
ftr(s, 22);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 23 — PREVENTION
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Prevention Strategies");
navyBox(s, 0.2, 1.0, 9.6, 0.44, "PRIMARY PREVENTION", FS_SUB, true, 0.07);
const prev = [
["H. pylori Test & Treat", "All patients with dyspepsia or PUD", "Mandatory"],
["Minimise NSAIDs", "Lowest effective dose, shortest duration", "Essential"],
["PPI Co-prescription", "Mandatory for high-risk NSAID users", "Essential"],
["Quit Smoking", "Doubles PUD relapse rate, impairs healing", "Advised"],
["Limit Alcohol", "Damages mucosal barrier, synergistic NSAIDs","Advised"]
];
// Table headers
[[0.2,3.0,"Strategy"],[3.24,4.95,"Action"],[8.22,1.58,"Priority"]].forEach(([x,w,h]) => {
navyBox(s, x, 1.48, w, 0.34, h, 18, true, 0);
});
prev.forEach(([strat, action, prio], i) => {
const bg = i%2===0 ? NT : W;
const isEss = prio!=="Advised";
s.addShape("rect", { x:0.2, y:1.84+i*0.38, w:3.0, h:0.36, fill:{color:bg}, line:{color:NT,width:0.5} });
s.addText(strat, { x:0.3, y:1.84+i*0.38, w:2.84, h:0.36, fontSize:FS_BODY, bold:true, color:N, fontFace:"Calibri", valign:"middle" });
s.addShape("rect", { x:3.24, y:1.84+i*0.38, w:4.95, h:0.36, fill:{color:bg}, line:{color:NT,width:0.5} });
s.addText(action, { x:3.34, y:1.84+i*0.38, w:4.78, h:0.36, fontSize:FS_BODY, color:TXT, fontFace:"Calibri", valign:"middle" });
s.addShape("rect", { x:8.22, y:1.84+i*0.38, w:1.58, h:0.36, fill:{color:isEss?N:NT}, line:{color:NT,width:0.5} });
s.addText(prio, { x:8.22, y:1.84+i*0.38, w:1.58, h:0.36, fontSize:FS_BODY-2, bold:isEss, color:isEss?W:N, fontFace:"Calibri", align:"center", valign:"middle" });
});
s.addText("NSAID Risk Stratification:", {
x:0.2, y:3.8, w:5.0, h:0.38,
fontSize:FS_SUB, bold:true, color:N, fontFace:"Calibri"
});
div(s, 4.2);
const risk = [
["LOW RISK\nNSAID alone", "No co-prescription needed", false],
["MODERATE RISK\nAge >65 or H. pylori +ve", "PPI co-prescription", true ],
["HIGH RISK\nPrior PUD or anticoagulant", "PPI + COX-2 selective NSAID", true ]
];
risk.forEach(([level, action, navy], i) => {
if (navy) navyBox(s, 0.2+i*3.27, 4.26, 3.12, 0.9, `${level}\n→ ${action}`, FS_BODY, true, 0.08);
else outBox(s, 0.2+i*3.27, 4.26, 3.12, 0.9, `${level}\n→ ${action}`, FS_BODY, false);
});
ftr(s, 23);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 24 — CLOSING CASE DISCUSSION
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Closing Case Discussion");
navyBox(s, 0.2, 1.0, 9.6, 2.2,
"Sunita, 60-year-old female, on diclofenac for arthritis and aspirin for cardiac disease.\n" +
"Sudden-onset severe central abdominal pain followed by right shoulder tip pain.\n" +
"Pale, tachycardic (HR 120), hypotensive (BP 90/60 mmHg).\n" +
"Abdomen rigid, not moving with respiration. Erect CXR shows free gas under right diaphragm.",
FS_BODY, false, 0.1);
s.addText("Group Discussion (10 minutes):", {
x:0.2, y:3.28, w:9.0, h:0.38,
fontSize:FS_SUB, bold:true, color:N, fontFace:"Calibri"
});
div(s, 3.68);
const dqs = [
{ num:"Q1", q:"What is the diagnosis and causative factors?", hint:"NSAIDs + aspirin → NSAID-induced perforation" },
{ num:"Q2", q:"How do you resuscitate this patient?", hint:"IV access, fluids, analgesia, NGT, catheter, OT" },
{ num:"Q3", q:"What operation would you perform and why?", hint:"Graham's patch — do not forget peritoneal toilet" },
{ num:"Q4", q:"What post-op medical management is essential?", hint:"IV PPI → oral PPI + H. pylori eradication + stop NSAIDs" }
];
dqs.forEach((dq, i) => {
const xp = 0.2 + (i%2)*4.92;
const yp = 3.76 + Math.floor(i/2)*0.86;
const navy = i%2===0;
s.addShape("roundRect", { x:xp, y:yp, w:4.72, h:0.78, fill:{color:navy?N:W}, line:{color:N,width:1.5}, rectRadius:0.08 });
s.addText(dq.num, { x:xp+0.1, y:yp, w:0.55, h:0.78, fontSize:FS_SUB, bold:true, color:navy?NT:N, fontFace:"Calibri", align:"center", valign:"middle" });
s.addShape("rect", { x:xp+0.7, y:yp+0.1, w:0.04, h:0.58, fill:{color:navy?NL:NT} });
s.addText(dq.q, { x:xp+0.82, y:yp+0.04, w:3.78, h:0.42, fontSize:FS_BODY, color:navy?W:N, fontFace:"Calibri", bold:true, valign:"bottom" });
s.addText(`Hint: ${dq.hint}`, { x:xp+0.82, y:yp+0.48, w:3.78, h:0.28, fontSize:18, color:navy?NT:NG, fontFace:"Calibri", italic:true });
});
ftr(s, 24);
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 25 — SUMMARY & KEY MESSAGES
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
whiteBg(s);
hdr(s, "Summary — Key Take-Home Messages");
const msgs = [
"No acid = no ulcer — PPIs are cornerstone",
"H. pylori + NSAIDs cause >90% of PUD",
"Always biopsy ALL gastric ulcers",
"Triple therapy: PPI + clarithro + amoxicillin",
"Confirm eradication with UBT ≥4 weeks post-Rx",
"Free gas on CXR = perforation until proven otherwise",
"Forrest Ia / Ib = urgent endoscopic haemostasis",
"Succussion splash = pyloric stenosis",
"Surgery reserved for complications only",
"ZE: suspect with multiple, refractory ulcers"
];
msgs.forEach((msg, i) => {
const col = i<5 ? 0 : 1;
const xp = 0.2 + col*4.92;
const yp = 1.0 + (i%5)*0.48;
s.addShape("roundRect", { x:xp, y:yp, w:4.72, h:0.42, fill:{color:i%2===0?N:NT}, line:{color:N,width:1}, rectRadius:0.06 });
s.addShape("roundRect", { x:xp+0.06, y:yp+0.07, w:0.28, h:0.28, fill:{color:i%2===0?NL:N}, rectRadius:0.04 });
s.addText(`${i+1}`, { x:xp+0.06, y:yp+0.07, w:0.28, h:0.28, fontSize:11, bold:true, color:W, fontFace:"Calibri", align:"center", valign:"middle" });
s.addText(msg, { x:xp+0.42, y:yp, w:4.22, h:0.42, fontSize:FS_BODY, color:i%2===0?W:TXT, fontFace:"Calibri", valign:"middle", wrap:true });
});
// Reference — on summary slide only
s.addShape("roundRect", { x:0.2, y:3.48, w:9.6, h:0.36, fill:{color:NT}, line:{color:N,width:1}, rectRadius:0.06 });
s.addText("Reference: Bailey & Love's Short Practice of Surgery, 28th Ed. (Williams, O'Connell, McCaskie — 2023)", {
x:0.3, y:3.48, w:9.4, h:0.36, fontSize:18, color:N, fontFace:"Calibri", italic:true, align:"center", valign:"middle"
});
navyBox(s, 0.2, 3.92, 9.6, 0.44,
"Thank You! Any Questions?",
FS_SUB, true, 0.07);
// Revision note
s.addShape("roundRect", { x:0.2, y:4.42, w:9.6, h:1.2, fill:{color:W}, line:{color:N,width:1.5}, rectRadius:0.08 });
s.addText("Quick Revision Questions:", { x:0.32, y:4.46, w:3.5, h:0.28, fontSize:FS_BODY, bold:true, color:N, fontFace:"Calibri" });
const revQ = [
"1. What is the triple therapy for H. pylori?",
"2. What electrolyte abnormality occurs in pyloric stenosis?",
"3. When do you MUST take biopsies?",
"4. Which ulcer tends to bleed? Which perforates?"
];
revQ.forEach((q, i) => {
s.addText(q, { x:0.32+Math.floor(i/2)*4.85, y:4.8+(i%2)*0.34, w:4.65, h:0.3, fontSize:FS_BODY, color:TXT, fontFace:"Calibri" });
});
ftr(s, 25);
}
// ─── SAVE ─────────────────────────────────────────────────────────────────
pres.writeFile({ fileName: "/home/daytona/workspace/peptic-ulcer-ppt/PUD_v3_Final.pptx" })
.then(() => console.log("✅ Saved: PUD_v3_Final.pptx"))
.catch(err => console.error("❌ Error:", err));
cd /home/daytona/workspace/peptic-ulcer-ppt && node create_ppt_v3.js 2>&1
ls -lh /home/daytona/workspace/peptic-ulcer-ppt/PUD_v3_Final.pptx && node -e "co…
PUD v3 Final
Presentation · PPTX
Peptic Ulcer Disease | Dept of Surgery | X/25Create a teacher's speaker notes PDF with timing guidance
~/peptic-ulcer-ppt/create_speaker_notes.py
"""
Teacher's Speaker Notes PDF — Peptic Ulcer Disease
25-slide lecture, 60-minute session
Bailey & Love, 28th Ed.
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether, PageBreak
)
from reportlab.platypus.flowables import Flowable
# ─── COLOUR PALETTE (Navy + White) ────────────────────────────────────────
NAVY = colors.HexColor("#0D2B4E")
NAVY_LIGHT = colors.HexColor("#1A4A78")
NAVY_TINT = colors.HexColor("#E8EEF5")
NAVY_GREY = colors.HexColor("#6B8DB2")
WHITE = colors.white
BLACK = colors.HexColor("#1A1A2E")
GREY_LINE = colors.HexColor("#CCCCCC")
WARN_BG = colors.HexColor("#F0F4FA")
# ─── PAGE SETUP ───────────────────────────────────────────────────────────
OUTPUT = "/home/daytona/workspace/peptic-ulcer-ppt/PUD_Speaker_Notes.pdf"
W, H = A4
MARGIN_L = 18*mm
MARGIN_R = 18*mm
MARGIN_T = 22*mm
MARGIN_B = 20*mm
# ─── STYLES ───────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def S(name, **kw):
return ParagraphStyle(name, **kw)
DOC_TITLE = S("DocTitle", fontSize=22, fontName="Helvetica-Bold", textColor=WHITE, alignment=TA_CENTER, spaceAfter=2)
DOC_SUB = S("DocSub", fontSize=11, fontName="Helvetica", textColor=NAVY_TINT, alignment=TA_CENTER, spaceAfter=4)
SLIDE_NUM = S("SlideNum", fontSize=9, fontName="Helvetica-Bold", textColor=NAVY_GREY, spaceBefore=0, spaceAfter=1)
SLIDE_HEAD = S("SlideHead", fontSize=14, fontName="Helvetica-Bold", textColor=NAVY, spaceBefore=2, spaceAfter=3)
TIME_LABEL = S("TimeLabel", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE, alignment=TA_CENTER)
SECTION_H = S("SectionH", fontSize=10, fontName="Helvetica-Bold", textColor=NAVY, spaceBefore=5, spaceAfter=2)
BODY = S("Body", fontSize=9.5,fontName="Helvetica", textColor=BLACK, spaceBefore=1, spaceAfter=1, leading=14)
BODY_J = S("BodyJ", fontSize=9.5,fontName="Helvetica", textColor=BLACK, spaceBefore=1, spaceAfter=1, leading=14, alignment=TA_JUSTIFY)
BULLET = S("Bullet", fontSize=9.5,fontName="Helvetica", textColor=BLACK, spaceBefore=1, spaceAfter=1, leading=13, leftIndent=12, bulletIndent=2)
WARN_TXT = S("WarnTxt", fontSize=9, fontName="Helvetica-Bold", textColor=NAVY, spaceBefore=2, spaceAfter=2, leftIndent=8)
ITALIC_TXT = S("ItalicTxt", fontSize=9, fontName="Helvetica-Oblique",textColor=NAVY_GREY,spaceBefore=1,spaceAfter=1)
TOC_ENTRY = S("TOC", fontSize=10, fontName="Helvetica", textColor=BLACK, spaceBefore=0, spaceAfter=1)
TOC_HEAD = S("TOCHead", fontSize=12, fontName="Helvetica-Bold", textColor=NAVY, spaceBefore=4, spaceAfter=4)
FOOTER_TXT = S("FooterTxt", fontSize=8, fontName="Helvetica", textColor=NAVY_GREY, alignment=TA_CENTER)
# ─── CUSTOM FLOWABLES ─────────────────────────────────────────────────────
class NavyBanner(Flowable):
"""Full-width navy banner with white title text."""
def __init__(self, text, height=22, sub=None):
super().__init__()
self.text = text
self.sub = sub
self.bh = height
self.width = W - MARGIN_L - MARGIN_R
def wrap(self, *args):
return (self.width, self.bh + (10 if self.sub else 0))
def draw(self):
c = self.canv
c.setFillColor(NAVY)
c.rect(0, 0, self.width, self.bh + (10 if self.sub else 0), fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 13 if self.sub else 13)
c.drawString(8, self.bh - 8 + (10 if self.sub else 0), self.text)
if self.sub:
c.setFont("Helvetica-Oblique", 8)
c.setFillColor(NAVY_TINT)
c.drawString(8, 3, self.sub)
class SlideBanner(Flowable):
"""Per-slide header: slide number badge + title + timing badge."""
def __init__(self, num, title, timing, cumulative):
super().__init__()
self.num = num
self.title = title
self.timing = timing
self.cumul = cumulative
self.width = W - MARGIN_L - MARGIN_R
def wrap(self, *args):
return (self.width, 28)
def draw(self):
c = self.canv
# Background tint
c.setFillColor(NAVY_TINT)
c.roundRect(0, 0, self.width, 28, 3, fill=1, stroke=0)
# Slide number badge
c.setFillColor(NAVY)
c.roundRect(0, 0, 38, 28, 3, fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 10)
c.drawCentredString(19, 10, f"{self.num:02d}")
c.setFont("Helvetica", 7)
c.drawCentredString(19, 2, "SLIDE")
# Title
c.setFillColor(NAVY)
c.setFont("Helvetica-Bold", 11)
c.drawString(46, 10, self.title)
# Timing badge (right side)
badge_w = 90
c.setFillColor(NAVY)
c.roundRect(self.width - badge_w - 2, 4, badge_w, 20, 3, fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 8)
c.drawCentredString(self.width - badge_w/2 - 2, 12, f"{self.timing} | Cum: {self.cumul} min")
class TimingBar(Flowable):
"""Visual progress bar showing where this slide sits in 60-min session."""
def __init__(self, start, duration):
super().__init__()
self.start = start
self.dur = duration
self.width = W - MARGIN_L - MARGIN_R
def wrap(self, *args):
return (self.width, 10)
def draw(self):
c = self.canv
total = 60.0
bar_w = self.width
# Background track
c.setFillColor(GREY_LINE)
c.rect(0, 3, bar_w, 5, fill=1, stroke=0)
# Fill portion
x0 = (self.start / total) * bar_w
fw = (self.dur / total) * bar_w
c.setFillColor(NAVY)
c.rect(x0, 3, fw, 5, fill=1, stroke=0)
class SectionTag(Flowable):
"""Small coloured tag label."""
def __init__(self, text, color=None):
super().__init__()
self.text = text
self.color = color or NAVY_LIGHT
self.width = W - MARGIN_L - MARGIN_R
def wrap(self, *args):
return (self.width, 14)
def draw(self):
c = self.canv
tw = len(self.text) * 5.5 + 10
c.setFillColor(self.color)
c.roundRect(0, 1, tw, 12, 2, fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 7.5)
c.drawString(5, 4, self.text)
# ─── HELPER FUNCTIONS ─────────────────────────────────────────────────────
def b(text):
"""Bullet paragraph."""
return Paragraph(f"• {text}", BULLET)
def h(text):
"""Section subheading."""
return Paragraph(text, SECTION_H)
def p(text):
"""Body paragraph."""
return Paragraph(text, BODY_J)
def warn(text):
"""Warning / key point."""
return Paragraph(f"▶ {text}", WARN_TXT)
def italic(text):
return Paragraph(text, ITALIC_TXT)
def sp(n=3):
return Spacer(1, n*mm)
def hr():
return HRFlowable(width="100%", thickness=0.5, color=GREY_LINE, spaceAfter=3, spaceBefore=3)
def qa_table(items):
"""Two-column Q&A table."""
data = [[Paragraph(f"<b>Q:</b> {q}", BODY), Paragraph(f"<b>A:</b> {a}", BODY)] for q, a in items]
t = Table(data, colWidths=[85*mm, 85*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY_TINT),
("GRID", (0,0), (-1,-1), 0.4, NAVY_GREY),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0),(-1,-1),4),
("LEFTPADDING",(0,0),(-1,-1),5),
]))
return t
def timing_note(start, dur, cum):
data = [[
Paragraph(f"<b>Start:</b> {start} min", BODY),
Paragraph(f"<b>Duration:</b> {dur} min", BODY),
Paragraph(f"<b>Cumulative:</b> {cum} min", BODY),
Paragraph(f"<b>Remaining:</b> {60-cum} min", BODY),
]]
t = Table(data, colWidths=[43*mm]*4)
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), NAVY_TINT),
("GRID", (0,0),(-1,-1), 0.4, NAVY_GREY),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING",(0,0),(-1,-1),3),
("LEFTPADDING",(0,0),(-1,-1),5),
]))
return t
# ─── DOCUMENT BUILDER ─────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=MARGIN_L, rightMargin=MARGIN_R,
topMargin=MARGIN_T, bottomMargin=MARGIN_B,
title="Teacher's Speaker Notes — Peptic Ulcer Disease",
author="Dept of Surgery",
subject="60-minute MBBS Lecture"
)
story = []
# ══════════════════════════════════════════════════════════════════════════
# COVER PAGE
# ══════════════════════════════════════════════════════════════════════════
story.append(Spacer(1, 30*mm))
story.append(NavyBanner("TEACHER'S SPEAKER NOTES", height=50))
story.append(Spacer(1, 6*mm))
story.append(Paragraph("<b>PEPTIC ULCER DISEASE</b>", ParagraphStyle("CVTitle", fontSize=22, fontName="Helvetica-Bold", textColor=NAVY, alignment=TA_CENTER, spaceAfter=6)))
story.append(Paragraph("Interactive Case-Based Lecture — MBBS Surgery", ParagraphStyle("CVSub", fontSize=13, fontName="Helvetica-Oblique", textColor=NAVY_GREY, alignment=TA_CENTER, spaceAfter=4)))
story.append(Paragraph("Bailey & Love's Short Practice of Surgery, 28th Edition", ParagraphStyle("CVRef", fontSize=11, fontName="Helvetica", textColor=NAVY_GREY, alignment=TA_CENTER, spaceAfter=4)))
story.append(Spacer(1, 8*mm))
# Session summary table
summary_data = [
[Paragraph("<b>Total Duration</b>", BODY), Paragraph("60 minutes", BODY)],
[Paragraph("<b>Total Slides</b>", BODY), Paragraph("25 slides", BODY)],
[Paragraph("<b>Target Audience</b>",BODY), Paragraph("MBBS — 3rd / 4th year surgery posting", BODY)],
[Paragraph("<b>Format</b>", BODY), Paragraph("Interactive, case-based, with MCQs", BODY)],
[Paragraph("<b>Source</b>", BODY), Paragraph("Bailey & Love, 28th Ed. — Chapter 67", BODY)],
[Paragraph("<b>AV Requirements</b>", BODY), Paragraph("Projector, laser pointer, whiteboard for flowcharts", BODY)],
[Paragraph("<b>Handout</b>", BODY), Paragraph("Distribute at end of session (not beginning)", BODY)],
]
st = Table(summary_data, colWidths=[55*mm, 112*mm])
st.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,-1), NAVY_TINT),
("BACKGROUND", (1,0),(1,-1), WHITE),
("GRID", (0,0),(-1,-1), 0.5, NAVY_GREY),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING",(0,0),(-1,-1),5),
("LEFTPADDING",(0,0),(-1,-1),6),
("FONTNAME", (0,0),(0,-1), "Helvetica-Bold"),
]))
story.append(st)
story.append(Spacer(1, 8*mm))
story.append(warn("Before you begin: Arrive 10 min early. Test projector. Write key terms on the board (H. pylori, PGE2, Forrest classification). Have the student seating arranged for pair-discussion."))
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════════════
# SESSION TIMELINE TABLE
# ══════════════════════════════════════════════════════════════════════════
story.append(NavyBanner("SESSION TIMELINE AT A GLANCE", height=22))
story.append(Spacer(1, 4*mm))
timeline = [
[Paragraph("<b>Slides</b>", BODY), Paragraph("<b>Topic</b>", BODY), Paragraph("<b>Duration</b>", BODY), Paragraph("<b>Cum.</b>", BODY), Paragraph("<b>Activity</b>", BODY)],
["1–2", "Title + Objectives", "5 min", "5 min", "Introduce yourself; state objectives clearly"],
["3", "Opening Case (Raju)", "5 min", "10 min", "Think-pair-share: 4 questions in pairs"],
["4–5", "Definition + Aetiology", "5 min", "15 min", "Interactive: ask students for risk factors"],
["6–7", "Pathophysiology + H. pylori", "8 min", "23 min", "Draw balance diagram on board"],
["8–9", "DU vs GU + Clinical Features", "5 min", "28 min", "Comparison quiz: ask class"],
["10–11","Investigations + Images", "5 min", "33 min", "Show endoscopy images; CLO test demo"],
["12–13","Medical Management", "8 min", "41 min", "Role-play: prescribe triple therapy"],
["14–16","Complications (Perf + Bleed)", "7 min", "48 min", "Emergency scenario discussion"],
["17–19","Stenosis / ZE / Surgery", "5 min", "53 min", "Flowchart on board: when to operate"],
["20–21","Algorithm + MCQs", "4 min", "57 min", "Class votes on MCQ options"],
["22–23","Special situations + Prev.", "2 min", "59 min", "Take-home messages — rapid fire"],
["24", "Closing Case (Sunita)", "—", "—", "Woven through last 10 min discussion"],
["25", "Summary + Q&A", "1 min", "60 min", "Key messages — invite 2 questions"],
]
tl_col = [18*mm, 52*mm, 18*mm, 15*mm, 64*mm]
tl_table = Table(timeline, colWidths=tl_col)
tl_table.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), NAVY),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 9),
("BACKGROUND", (0,1),(-1,-1), WHITE),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, NAVY_TINT]),
("GRID", (0,0),(-1,-1), 0.4, NAVY_GREY),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 5),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
story.append(tl_table)
story.append(Spacer(1, 5*mm))
story.append(italic("Tip: Keep a watch or timer visible. The opening case and closing case are the anchors — spend full time on them. Compress the middle sections if running late."))
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════════════
# PER-SLIDE NOTES
# ══════════════════════════════════════════════════════════════════════════
slides = [
# ── SLIDE 1 ───────────────────────────────────────────────────────────────
dict(
num=1, title="Title Slide", timing="1 min", start=0, dur=1, cum=1,
purpose="Arouse interest and set context before stating objectives.",
script=[
"Welcome the class. Ask one student to read the slide title aloud.",
"Say: 'Peptic ulcer disease is one of the commonest conditions you will encounter as a houseman — and one of the most rewarding to treat, because most ulcers heal completely with the right treatment.'",
"Point to the topic list on the right. Say: 'We will cover all of these in 60 minutes — but we start and end with a real patient story.'"
],
key_points=[
"Bailey & Love is the primary source — reference it throughout.",
"Mention that the session is interactive — students should ask questions at any time.",
"This is a case-based session — students will be expected to apply knowledge, not just recall."
],
interaction=None,
teaching_tip="Make eye contact with students in different parts of the room. Do not read the slide.",
watch_for=None
),
# ── SLIDE 2 ───────────────────────────────────────────────────────────────
dict(
num=2, title="Session Overview & Objectives", timing="2 min", start=1, dur=2, cum=3,
purpose="State learning objectives clearly — satisfies evaluation criteria #2.",
script=[
"Read each objective once, clearly and slowly.",
"Say: 'By the end of this hour, I expect each of you to be able to prescribe triple therapy, manage a perforation in the emergency, and recognise pyloric stenosis at the bedside.'",
"Point to the timeline. Say: 'We have a structured 60-minute plan. I will keep us on time.'"
],
key_points=[
"Objectives anchor the session — students know where they are heading.",
"Refer back to these at the summary slide to close the loop.",
"The two case discussions bookend the entire session."
],
interaction="Ask: 'Has anyone admitted a patient with peptic ulcer this posting?' — 1–2 student responses.",
teaching_tip="Keep this slide brief. Do not read every timeline row — just highlight the case discussions.",
watch_for=None
),
# ── SLIDE 3 ───────────────────────────────────────────────────────────────
dict(
num=3, title="Opening Case — Raju", timing="5 min", start=3, dur=5, cum=8,
purpose="Arouse interest by relating to clinical reality. Creates cognitive curiosity.",
script=[
"Read the case vignette aloud, slowly. Pause after 'takes diclofenac daily.'",
"Say: 'Before I tell you anything about peptic ulcer disease — I want you to think. Take 90 seconds, turn to the person next to you, and answer Q1 and Q2.'",
"After 90 seconds, take responses from 2–3 pairs for each question.",
"Do NOT give the answers yet. Say: 'Hold these thoughts — every answer will become clear as we go through the session.'"
],
key_points=[
"Provisional diagnosis: Peptic ulcer disease (likely duodenal — NSAID + smoker + night pain).",
"Risk factors: NSAIDs (diclofenac), smoking, male, manual labour (stress), no mention of H. pylori yet.",
"Initial investigations: OGD, H. pylori testing (CLO / UBT), FBC (anaemia?).",
"Immediate management: Stop NSAIDs, start PPI, test for H. pylori."
],
interaction="Think-pair-share: 90 sec pair discussion → 2 min class feedback. Deliberately leave the case open.",
teaching_tip="Write 'Raju' on the board. Return to him at key points — 'Remember Raju's diclofenac...' This technique ties learning to a person and aids recall.",
watch_for="Students may jump to 'OGD immediately' — acceptable. Note that Test & Treat is appropriate if age <55 with no alarm features."
),
# ── SLIDE 4 ───────────────────────────────────────────────────────────────
dict(
num=4, title="Definition & Common Sites", timing="3 min", start=8, dur=3, cum=11,
purpose="Establish baseline definitions and anatomical context.",
script=[
"Read the definition. Emphasise 'muscularis mucosae' — this distinguishes ulcer from erosion.",
"Point to the sites table. Ask: 'Why do you think the first part of the duodenum is most common?' — let 2 students guess.",
"Explain: 'Because after the pylorus, gastric acid floods the duodenal cap before it can be neutralised by bicarbonate-rich pancreatic secretion.'",
"Highlight the red-bordered rules on the right. Read each one. Pause on 'ALL gastric ulcers must be biopsied' — repeat it twice.",
"Anterior DU perforates, posterior DU bleeds — draw a quick diagram if time allows."
],
key_points=[
"Erosion = superficial, does not breach muscularis mucosae. Ulcer = full breach.",
"Most common site = 1st part of duodenum (anterior = perforation, posterior = bleeds into GDA).",
"Meckel's diverticulum: ectopic gastric mucosa → acid secretion → ulceration → bleeding PR.",
"Stomal ulcers occur at the jejunal side of gastroenterostomy or Billroth II anastomosis."
],
interaction="Quick question: 'Name two other sites where peptic ulcers occur besides duodenum.' — Meckel's, stoma, oesophagus.",
teaching_tip="Draw the duodenum on the board — mark anterior and posterior walls. Students remember diagrams better than text.",
watch_for="Students confuse erosion and ulcer. Clarify: depth of penetration is the key difference."
),
# ── SLIDE 5 ───────────────────────────────────────────────────────────────
dict(
num=5, title="Aetiology — Flowchart", timing="4 min", start=11, dur=4, cum=15,
purpose="Identify all causative factors using a visual flowchart — aids chunking.",
script=[
"Start by asking: 'Before you look at the slide — name the two most important causes of PUD.' (H. pylori + NSAIDs)",
"Reveal the flowchart. Walk left to right: H. pylori (most important), NSAIDs, smoking, steroids → all converging on the central ulcer node.",
"Right side: ZE syndrome (gastrinoma), stress ulcers (Cushing's = brain injury → neurogenic acid, Curling's = burns → mucosal ischaemia), Blood Group O.",
"Highlight the bottom banner: H. pylori + NSAIDs = >90% of all peptic ulcers.",
"Connect back to Raju: 'Raju has TWO risk factors — NSAIDs and smoking. What was missing from his history that we should ask about? — H. pylori symptoms.'"
],
key_points=[
"H. pylori: 80% of DU, 60% of GU. Causes ~50% of UGIB in developing countries.",
"NSAIDs: Systemic effect (COX-1 inhibition → ↓PGE2 → ↓mucus/bicarbonate). Topical acid injury is secondary.",
"Stress ulcers: Curling's = burns; Cushing's = CNS injury (vagal hyperactivity). Both managed with prophylactic PPI in ICU.",
"ZE: <1% of cases — but important differential for multiple/refractory ulcers."
],
interaction="Ask: 'What is the mechanism by which NSAIDs cause ulcers?' — Students should mention COX-1, PGE2, mucosal defence.",
teaching_tip="Use the mnemonic HANS-ZSB: H. pylori, Acid, NSAIDs, Smoking, ZE, Stress, Blood group O.",
watch_for="Do not spend more than 4 minutes here. The pathophysiology slide expands on this."
),
# ── SLIDE 6 ───────────────────────────────────────────────────────────────
dict(
num=6, title="Pathophysiology — Balance of Forces", timing="4 min", start=15, dur=4, cum=19,
purpose="Explain the central imbalance concept that underpins all treatment decisions.",
script=[
"Draw a simple balance on the board — two sides. Ask students to call out factors for each side.",
"Label: Aggressive (acid, pepsin, H. pylori, NSAIDs) vs. Defensive (mucus, PGE2, blood flow, epithelial repair).",
"Say: 'Every drug we use targets this balance. PPIs remove acid. H. pylori eradication removes infection. Misoprostol adds back PGE2.'",
"Explain the H. pylori mechanism at the bottom strip: 'H. pylori produces urease → splits urea → NH3 → local toxicity → damages epithelium AND stimulates gastrin release → more acid.'",
"Ask: 'If you give a COX-2 selective NSAID instead of a COX-1 inhibitor — which side of the balance changes?' — Correct: COX-2 selective spares PGE2 (mucosal defence preserved)."
],
key_points=[
"PGE2 is the pivotal protective mediator — stimulates mucus, bicarbonate, blood flow.",
"NSAIDs have both systemic (COX-1 inhibition) and topical (direct acid) effects on mucosa.",
"H. pylori virulence factors: VacA (epithelial vacuolation), CagA (inflammation), BabA (adhesin).",
"Endarteritis obliterans at base of chronic ulcer = why they bleed when vessels erode."
],
interaction="Board diagram: students call out items for each side. Takes 90 seconds and reinforces learning.",
teaching_tip="The balance concept is the 'Big Idea' of this lecture. Everything else flows from it. Spend the full 4 min here.",
watch_for="Students sometimes say 'H. pylori only affects acid' — correct this: it also directly damages the epithelium via cytotoxins."
),
# ── SLIDE 7 ───────────────────────────────────────────────────────────────
dict(
num=7, title="H. pylori — Details", timing="4 min", start=19, dur=4, cum=23,
purpose="Deep-dive on the most important pathogen in PUD — high-yield for exams.",
script=[
"Quickly review the 5 stat cards: 'Gram-negative spiral rod, urease positive, lives in the antrum, WHO Class 1 carcinogen, infects more than half the world's population — especially in low-income countries.'",
"Virulence: 'The most important are Urease (rapid test uses this), VacA (causes cell vacuolation), and CagA (induces inflammation — associated with higher cancer risk).'",
"Diagnosis table: 'Non-invasive tests — Urea Breath Test is the best for confirming eradication. CLO test is rapid and cheap at OGD. Serology only tells you past exposure — useless for confirming active infection.'",
"Key exam point: 'Never use serology to confirm eradication — it stays positive for months after cure.'"
],
key_points=[
"Urea Breath Test: patient drinks 13C-urea → H. pylori urease → 13CO2 exhaled → detected. Stop PPI 2 weeks before — otherwise false negative.",
"CLO = Campylobacter-like organism test. Biopsy sample in urea-containing gel → urease changes colour.",
"Stool antigen test: monoclonal antibody. Good for primary diagnosis and confirmation of cure.",
"Culture: only needed when antibiotic sensitivity testing is required (resistant cases)."
],
interaction="Quiz: 'Which test CANNOT be used to confirm eradication and why?' — Serology (stays positive after cure).",
teaching_tip="Draw the UBT mechanism on the board — students find it fascinating and it reinforces the biochemistry.",
watch_for="Students often confuse CLO test (rapid urease on biopsy) with Culture. Clarify the distinction."
),
# ── SLIDE 8 ───────────────────────────────────────────────────────────────
dict(
num=8, title="DU vs GU Comparison", timing="3 min", start=23, dur=3, cum=26,
purpose="Consolidate the clinical and demographic differences — high-frequency exam table.",
script=[
"Cover the right two columns with your hand (or use a laser pointer to reveal row by row). Ask the class: 'DU or GU?' for each feature.",
"Key teaching moment — Malignancy row: 'This is the most important row in this table. Duodenal ulcer — virtually never malignant. Gastric ulcer — MUST biopsy every single one. You cannot distinguish a benign GU from an ulcerating gastric cancer on symptoms alone, or even on appearance at endoscopy.'",
"Night pain relieved by food: classic DU teaching — food buffers acid.",
"Read the red banner at the bottom. Repeat: 'All gastric ulcers — biopsy — every time.'"
],
key_points=[
"DU 4x more common than GU. DU affects younger patients.",
"Acid levels: DU = high/normal; GU = normal/low — yet BOTH need acid to occur.",
"Giant DU (>2 cm): malignancy in duodenum is extremely rare — can treat confidently as benign. Giant GU: always exclude cancer.",
"Both GU and DU can now be diagnosed by OGD — barium meal now rarely used."
],
interaction="Row-by-row reveal quiz: cover columns, ask students DU or GU for each feature. 90 seconds.",
teaching_tip="This table appears in nearly every surgery exam. Give students 30 seconds to photograph or note it.",
watch_for="Students sometimes state 'GU has higher acid' — this is wrong. Correct it immediately."
),
# ── SLIDE 9 ───────────────────────────────────────────────────────────────
dict(
num=9, title="Clinical Features", timing="3 min", start=26, dur=3, cum=29,
purpose="Identify characteristic symptoms and danger-sign clinical findings.",
script=[
"Review the 3 feature cards: Pain, Relief, Other. 'The cardinal feature is episodic epigastric pain with periodicity — it comes and goes over weeks/months. This spontaneous healing and relapse is the hallmark of PUD.'",
"Clinical signs: 'In uncomplicated PUD, the examination is almost normal — just mild tenderness. The dangerous signs are in the red-highlighted rows.'",
"Walk through red signs: 'Succussion splash = fluid sloshing in distended stomach = outlet obstruction. Board-like rigidity = peritonitis = perforation. Melaena = upper GI haemorrhage. Palpable mass = until proven otherwise, malignancy.'",
"Return to Raju: 'Raju has mild epigastric tenderness — uncomplicated. No danger signs. But if he had come with a rigid abdomen — what would you think?'"
],
key_points=[
"Periodicity (weeks of pain, weeks of remission) = characteristic of PUD. Not seen in dyspepsia or functional disorders.",
"Food relief: classic of DU (food buffers acid). Food worsening: more typical of GU (food may stimulate more acid).",
"Vomiting in PUD without obstruction = uncommon. Persistent vomiting = think pyloric stenosis.",
"Chronic blood loss → microcytic anaemia — check FBC in all PUD patients."
],
interaction="Ask: 'What is the difference between haematemesis and melaena in terms of bleeding site?' — Upper vs lower GI distinction.",
teaching_tip="Succussion splash demonstration: ask a student to stand up, place hands on their abdomen, and gently shake — mimics the examination. Students remember physical demonstrations.",
watch_for="Students may say 'PUD always presents with pain' — stress that elderly and NSAID users can have silent ulcers presenting first with a complication (haemorrhage)."
),
# ── SLIDE 10 ───────────────────────────────────────────────────────────────
dict(
num=10, title="Investigations Flowchart", timing="3 min", start=29, dur=3, cum=32,
purpose="Show a clear decision algorithm for investigation — practical application.",
script=[
"Walk through the flowchart top to bottom. 'The first branch point is age and alarm features. Under 55 with no alarm features — we use Test & Treat: test for H. pylori non-invasively and treat if positive.'",
"'If alarm features present — or if the test-and-treat approach fails — go straight to OGD.'",
"'At OGD: biopsy ALL gastric lesions. Take CLO test from the antrum. Take biopsies for histology.'",
"Additional tests strip: 'Erect CXR in anyone with acute abdomen — free gas under diaphragm. CT is now the gold standard for perforation. Serum amylase to exclude pancreatitis. Fasting serum gastrin only if you suspect ZE syndrome.'"
],
key_points=[
"Test & Treat: appropriate for age <55 with typical dyspepsia and NO alarm features. Uses UBT or stool antigen test.",
"Alarm features (DYSPHAGIA mnemonic): Dysphagia, Unexplained weight loss, Anaemia, Persistent vomiting, Haematemesis, AGE >55, GI mass.",
"OGD: gold standard. Allows biopsy, CLO test, and therapeutic intervention.",
"Barium meal: now rarely used — only if OGD unavailable or patient cannot tolerate scope."
],
interaction="Ask: 'For Raju — age 35, no alarm features — which investigation pathway would you use?' — Test & Treat.",
teaching_tip="The alarm feature list is high-yield. Ask students to memorise it as a mnemonic.",
watch_for="Students often say 'just do OGD for everyone' — explain that Test & Treat reduces unnecessary scoping and healthcare costs."
),
# ── SLIDE 11 ───────────────────────────────────────────────────────────────
dict(
num=11, title="Endoscopy & Radiology Images", timing="2 min", start=32, dur=2, cum=34,
purpose="Visualise the disease — connects textbook knowledge to real clinical appearances.",
script=[
"Left image: 'This is a duodenal ulcer at gastroduodenoscopy. Note the punched-out appearance, clean base, and surrounding oedematous mucosa. This is from Bailey & Love, Figure 67.10.'",
"Right image: 'This is a barium meal showing a duodenal ulcer — the classic 'duodenal cap deformity' from scarring. Note how the cap has lost its normal triangular shape. This is Figure 67.11.'",
"Say: 'In modern practice, we would do OGD, not barium meal, as the first investigation. But barium meal images appear in written exams — so recognise this pattern.'"
],
key_points=[
"At OGD, a gastric ulcer must have at minimum 6 biopsies from the edge — not the base (necrotic). The 'U-manoeuvre' of the scope visualises the incisura and lesser curve fully.",
"Duodenal ulcers are biopsied for H. pylori (CLO test), not routinely for malignancy.",
"Barium meal signs: duodenal cap deformity (scarring), 'niche' sign (ulcer crater), mucosal folds radiating to ulcer."
],
interaction="Show images and ask: 'What would be your next step if you saw this at OGD?' — CLO test, biopsy if GU.",
teaching_tip="Spend 30 seconds on each image. Do not over-explain — the visual speaks for itself.",
watch_for=None
),
# ── SLIDE 12 ───────────────────────────────────────────────────────────────
dict(
num=12, title="Medical Management — Step-Up", timing="4 min", start=34, dur=4, cum=38,
purpose="Establish the logical treatment approach — links directly to pathophysiology.",
script=[
"Walk through steps 1–4 in order. 'Every step targets one part of the imbalance we drew earlier.'",
"Step 1 — Lifestyle: 'Stop the cause first. Stopping NSAIDs is more important than any drug. If a patient must continue NSAIDs — always add a PPI.'",
"Step 2 — PPI: 'Proton pump inhibitors block the H+/K+ ATPase — the final common pathway for ALL acid secretion. They are the single most important drug in PUD management.'",
"Step 3 — Eradication: 'If H. pylori is present, eradication is curative in most patients. This is one of the few times in medicine we can cure a chronic disease completely with a 2-week course of treatment.'",
"Step 4 — Follow-up OGD: 'Only mandatory for gastric ulcers — to confirm healing and re-biopsy if not healed. Duodenal ulcers do not need repeat OGD if symptoms resolve.'"
],
key_points=[
"PPI mechanism: irreversibly bind H+/K+ ATPase on parietal cell. Effect lasts 24–72 hrs. Must be given before meals (30 min before breakfast) for maximum efficacy.",
"Duration: DU — 4 weeks; GU — 8 weeks. Eradication therapy usually given alongside PPI.",
"NSAID-PPI combination: if NSAID cannot be stopped, give full-dose PPI indefinitely (especially in elderly/history of GI bleed).",
"Sucralfate: acts as a physical barrier in the ulcer crater. Still used in pregnancy and ICU stress ulcer prophylaxis."
],
interaction="Role-play: Ask a student to 'prescribe' treatment for Raju. Correct gently if wrong. This is application of knowledge.",
teaching_tip="The 4-step framework is easily memorised. Write it on the board: Stop cause → Suppress acid → Eradicate bug → Check healing.",
watch_for="Students often omit Step 1 (lifestyle) and jump to drugs. Emphasise that removing the cause (NSAIDs, smoking) is the first step."
),
# ── SLIDE 13 ───────────────────────────────────────────────────────────────
dict(
num=13, title="H. pylori Eradication Regimens", timing="4 min", start=38, dur=4, cum=42,
purpose="Teach the specific regimens and their rationale — immediately applicable to clinical practice.",
script=[
"Triple therapy: 'PPI twice daily — any PPI works. Amoxicillin 1g BD — covers most strains. Clarithromycin 500mg BD — the key antibiotic. 7–14 days. In India, 14 days is preferred due to higher bacterial load.'",
"'If penicillin allergy — replace amoxicillin with metronidazole 400mg BD.'",
"Quadruple therapy: 'Used if triple therapy fails, or if clarithromycin resistance suspected. Adds bismuth — which has direct anti-H. pylori activity.'",
"Pitfalls box: 'The most important pitfall — stopping PPI 2 weeks before UBT. If you forget this, you will get a false-negative result and miss ongoing infection.'",
"Ask: 'What is the eradication rate of triple therapy?' — 80–90%. 'What do you do if it fails?' — Quadruple therapy, then culture + sensitivity-guided therapy."
],
key_points=[
"Bismuth subcitrate: direct bactericidal effect on H. pylori + forms protective film over ulcer base.",
"Clarithromycin resistance: rising globally (now 15–20% in some regions). Sequential therapy and culture-guided therapy becoming more important.",
"Confirm eradication: UBT at ≥4 weeks after completing treatment AND stopping PPI for 2 weeks.",
"India: primary clarithromycin resistance lower than Europe, but rising. Metronidazole resistance higher."
],
interaction="Ask: 'Your patient had triple therapy 6 weeks ago. How do you confirm H. pylori is gone?' — UBT (not serology, not CLO on repeat scope unless indicated).",
teaching_tip="Give students a card/mnemonic for triple therapy: 'PCA' — PPI, Clarithromycin, Amoxicillin.",
watch_for="Students sometimes say 'repeat OGD to check H. pylori eradication' — this is not required routinely for DU. UBT is sufficient and non-invasive."
),
# ── SLIDE 14 ───────────────────────────────────────────────────────────────
dict(
num=14, title="Complications Overview", timing="2 min", start=42, dur=2, cum=44,
purpose="Provide an overview map of the four major complications before drilling down.",
script=[
"Use the four-corner layout as a map. 'Peptic ulcer has four major complications: perforation, haemorrhage, pyloric stenosis, and malignancy.'",
"Say: 'Haemorrhage is the MOST COMMON. Perforation is the MOST DANGEROUS. Stenosis is the most insidious. Malignancy applies to gastric ulcers ONLY.'",
"Read the four summary points at the bottom. 'We will now spend 5 minutes on each of the first two — perforation and haemorrhage — because these are surgical emergencies you will face as a houseman.'"
],
key_points=[
"Haemorrhage: most common complication; accounts for most PUD-related deaths.",
"Perforation: mortality increases sharply with delay — every hour after perforation worsens outcome.",
"Pyloric stenosis: chronic fibrosis — presents with recurrent vomiting, weight loss, succussion splash, hypokalaemic hypochloraemic metabolic alkalosis.",
"Malignancy: gastric ulcer ONLY. Duodenal malignancy so rare as to be practically irrelevant."
],
interaction="Quick-fire quiz: 'Most common complication?' — Haemorrhage. 'Most dangerous?' — Perforation. 'Metabolic complication of stenosis?' — Hypokalaemic hypochloraemic alkalosis.",
teaching_tip="Draw a 2x2 grid on the board: Most common / Most dangerous / Metabolic / Malignant risk. Students fill it in. 60 seconds.",
watch_for=None
),
# ── SLIDE 15 ───────────────────────────────────────────────────────────────
dict(
num=15, title="Perforated Peptic Ulcer", timing="4 min", start=44, dur=4, cum=48,
purpose="Teach emergency recognition and management of the most dangerous complication.",
script=[
"Clinical features: 'The presentation is INSTANTLY recognisable — Bailey & Love says so explicitly. Sudden severe epigastric pain — often described as being struck by a knife. Board-like rigidity. Patient lying still — any movement worsens pain.'",
"Shoulder tip pain: 'Free gastric acid under the diaphragm irritates the phrenic nerve — referred pain to the right shoulder. This is a classic clinical sign.'",
"Management: 'Step one — resuscitate. Step two — analgesia. NEVER withhold analgesia for fear of masking signs — in fact, adequate analgesia makes signs more obvious, not less. Bailey & Love is explicit on this.'",
"CXR image: 'Free air under the right diaphragm — seen in >50% of perforated peptic ulcers. But CT is more accurate. Always do CT in ambiguous cases.'",
"Surgery: 'Graham's omental patch — close the hole, place omentum over it. For GU perforations — excise and close, so histology can be sent.'"
],
key_points=[
"Free gas on CXR in >50% of perforations — but CT is more sensitive and specific.",
"Serum amylase: may be mildly elevated in perforation (from enzyme absorption from gut contents) — does not mean pancreatitis.",
"Conservative management (Taylor's method): only for small, sealed perforations in selected, stable patients with minimal contamination.",
"Elderly female patients on NSAIDs: increasingly the demographic for perforation — may have atypical presentation (less pain, less guarding due to NSAIDs/steroids)."
],
interaction="Emergency scenario: 'Patient arrives at casualty with sudden-onset abdominal pain and board-like rigidity. Your next 3 steps?' — IV access + fluids, analgesia, erect CXR/CT.",
teaching_tip="Refer to the CXR image on the slide. Ask: 'What is the dark area under the right diaphragm?' — Free gas = air. This is one of the most important X-ray findings to recognise.",
watch_for="Intern-level mistake: withholding analgesia in acute abdomen. Correct this explicitly and cite Bailey & Love."
),
# ── SLIDE 16 ───────────────────────────────────────────────────────────────
dict(
num=16, title="Upper GI Haemorrhage", timing="3 min", start=48, dur=3, cum=51,
purpose="Teach Forrest classification and the management ladder — core surgical knowledge.",
script=[
"Statistics: 'Over 100 per 100,000 per year. 10–14% mortality — despite decades of improvements. The mortality is largely driven by the elderly and comorbid population.'",
"Forrest classification: 'This is one of the most important tables in surgery. Forrest Ia and Ib — active bleeding — 55% risk of re-bleeding. Forrest IIa — non-bleeding visible vessel — 43% risk. These need endoscopic treatment NOW.'",
"'Forrest III — clean base — 5% re-bleed risk — can be managed conservatively.'",
"Management ladder: 'Resuscitate first. Then IV PPI — high dose omeprazole 80mg bolus, then infusion. Urgent OGD within 24 hours — or within 12 hours if haemodynamically unstable. Endoscopic treatment: adrenaline injection (causes vasoconstriction + tamponade) combined with mechanical clip or heater probe.'",
"'If OGD fails — interventional radiology (angioembolisation). If that fails — surgery: underrunning the vessel (Billroth II or simple oversewing).'"
],
key_points=[
"Rockall score: used to predict re-bleed and mortality risk. Age, shock, comorbidities, diagnosis, stigmata of recent haemorrhage.",
"Endoscopic haemostasis: dual therapy (adrenaline + thermal/mechanical) superior to adrenaline alone.",
"H. pylori eradication after UGIB significantly reduces re-bleed rate — must be done once stable.",
"Transfusion trigger: Hb <7 g/dL (or <8 if cardiovascular disease). Restrictive transfusion improves outcomes in UGIB."
],
interaction="Ask: 'A patient with UGIB has a Forrest IIa lesion. What is your management?' — Urgent OGD + dual endoscopic therapy.",
teaching_tip="The Forrest table is a frequent exam question. Give students 30 seconds to note it down or photograph.",
watch_for="Students sometimes say 'surgery first for UGIB' — correct: endoscopy is first-line. Surgery is reserved for failure of endoscopy."
),
# ── SLIDE 17 ───────────────────────────────────────────────────────────────
dict(
num=17, title="Pyloric Stenosis & ZE Syndrome", timing="3 min", start=51, dur=3, cum=54,
purpose="Cover two important but less common complications with high exam relevance.",
script=[
"Pyloric stenosis: 'Chronic fibrosis from repeated ulceration and healing. Patient vomits repeatedly — non-bilious because the obstruction is at or proximal to the pylorus, so bile cannot reflux back. The classic sign is the succussion splash.'",
"Metabolic consequence: 'This is a high-yield exam question. Repeated vomiting of gastric contents → loss of HCl → hypochloraemia → kidneys conserve sodium by excreting hydrogen ions (paradoxical aciduria) → hypokalaemic hypochloraemic metabolic alkalosis. Write this down.'",
"ZE syndrome: 'Rare. Think of it when: multiple ulcers, ulcers in unusual sites (e.g., jejunum), refractory to standard PPI doses, associated diarrhoea (acid flooding the gut destroys pancreatic enzymes).'",
"'Diagnosis: fasting serum gastrin. A level >1000 pg/mL is virtually diagnostic. Secretin stimulation test: paradoxically INCREASES gastrin in ZE (unlike normal, where secretin suppresses gastrin).'"
],
key_points=[
"Succussion splash: patient standing, examiner places stethoscope over epigastrium and gently shakes patient — sloshing sound = retained gastric contents.",
"Treatment of pyloric stenosis: NG tube + IV fluids + correct electrolytes FIRST (may take days). Then endoscopic balloon dilation. Surgery if dilation fails or concurrent malignancy.",
"ZE: 20% associated with MEN-1 (multiple endocrine neoplasia type 1) — check calcium, parathyroid, pituitary.",
"ZE treatment: high-dose PPI is the cornerstone. Surgical resection of tumour if localised and no metastases."
],
interaction="Ask: 'What electrolyte abnormality would you expect in pyloric stenosis?' — Let students think, then explain the sequence.",
teaching_tip="Draw the sequence on the board: Vomiting → Loss HCl → ↓ Cl → ↓ K → Kidneys: Na+/H+ exchange → Paradoxical aciduria. Students must be able to explain this chain.",
watch_for="Students confuse hypochloraemic alkalosis with hyperchloraemic acidosis (which occurs in diarrhoea). Draw the comparison."
),
# ── SLIDE 18 ───────────────────────────────────────────────────────────────
dict(
num=18, title="Surgical Management", timing="3 min", start=54, dur=3, cum=57,
purpose="Outline indications and operations — for completeness and exam preparation.",
script=[
"Indications bar: 'Elective surgery for PUD is now extremely rare — less than 1% of cases need it with modern PPIs. The indications are almost entirely for complications: perforation, uncontrolled bleed, malignancy, and obstruction.'",
"DU operations: 'The key concepts are: (1) acid reduction via vagotomy and (2) drainage procedure to prevent gastric stasis. Highly selective vagotomy (HSV) denervates only the parietal cell mass — spares the antrum. Fewest side effects. But technically demanding and high recurrence rate.'",
"GU operations: 'The principle is ALWAYS excision — because you must send it to histology. You cannot confidently exclude malignancy at operation. Bailey & Love: even an experienced surgeon may not distinguish benign from malignant ulcer.'",
"Sequelae note: 'A generation of patients operated on before PPIs exist have post-gastric surgery complications — dumping syndrome, diarrhoea, small stomach syndrome.'"
],
key_points=[
"Truncal vagotomy: reduces acid by ~50% but causes gastric atony — requires drainage procedure (pyloroplasty or gastrojejunostomy).",
"Billroth I: removes distal stomach, reattaches duodenum to stomach end. More physiological.",
"Billroth II / Pólya: removes distal stomach, duodenal stump closed, stomach anastomosed to jejunum. Diverts bile from stomach.",
"Roux-en-Y: used for very large or complex perforations, or when re-anastomosis is not feasible."
],
interaction="Ask: 'You find a perforated gastric ulcer at laparotomy. What is your operative priority beyond closing the perforation?' — Send it for histology (excise the ulcer edge).",
teaching_tip="The operations are less important than the principles — acid reduction, drainage, and histology for GU. Focus on principles, not operative details.",
watch_for="Students may say 'just close the GU perforation' — stress that the ulcer edge must be excised and sent for histology."
),
# ── SLIDE 19 ───────────────────────────────────────────────────────────────
dict(
num=19, title="Dumping Syndrome", timing="2 min", start=57, dur=2, cum=59,
purpose="Explain a common post-gastrectomy complication — frequently examined.",
script=[
"Early dumping: 'Rapid gastric emptying after loss of pyloric function. Hypertonic food rushes into jejunum. Osmotic pressure draws fluid from the bloodstream — causes vasomotor symptoms: flushing, palpitations, sweating, diarrhoea. Onset 15–30 minutes after eating.'",
"Late dumping: 'Rapid glucose absorption from the jejunum → massive insulin release → reactive hypoglycaemia 2–3 hours later. Symptoms of hypoglycaemia: tremor, sweating, confusion, faintness.'",
"Management: 'Small frequent meals, low-carbohydrate, high-protein diet. Lie down after meals (slows gastric emptying). Octreotide for severe cases (slows GI motility). Surgical revision rarely needed.'"
],
key_points=[
"Early dumping = osmotic/vasomotor (fluid shift). Late dumping = hormonal/glycaemic (insulin excess).",
"Late dumping: give sugar at onset of symptoms for immediate relief.",
"Dietary advice is first-line for both. Patients need detailed dietitian input.",
"Incidence of dumping after vagotomy + pyloroplasty: ~10% early, ~1% severe. After gastrectomy: higher."
],
interaction="Ask: 'A patient had a gastrectomy 2 years ago. He gets faint and sweaty 2 hours after meals. What is the diagnosis?' — Late dumping syndrome.",
teaching_tip="The Early vs Late distinction is a classic exam comparison. Use the board: Early = within 30 min = osmotic. Late = 2–3 hrs = glycaemic.",
watch_for="Students sometimes confuse early dumping with lactose intolerance or IBS. Timing post-meal and surgical history distinguishes them."
),
# ── SLIDE 20 ───────────────────────────────────────────────────────────────
dict(
num=20, title="Complete Management Algorithm", timing="2 min", start=59, dur=1, cum=60,
purpose="Consolidate the entire management pathway in one visual — synthesis slide.",
script=[
"Walk through the algorithm quickly — students should now be able to follow it confidently.",
"'Start at the top: epigastric pain. Branch point: age and alarm features. Left path: Test & Treat. Right path: OGD urgently. Both converge at OGD and H. pylori testing. Confirmed PUD: PPI + eradicate. Complication present: specific pathway for each.'",
"Alarm features strip: 'Memorise these. Any one of these mandates OGD regardless of age.'",
"NSAID note: 'Always ask about NSAID use. If the patient must continue NSAIDs: always co-prescribe a PPI.'"
],
key_points=[
"The algorithm is the integration of everything taught — refer back to it as the 'decision map'.",
"Test & Treat saves thousands of unnecessary OGDs — cost-effective and evidence-based.",
"Alarm features: any ONE is sufficient to bypass Test & Treat and go straight to OGD.",
"Post-complication management always includes H. pylori eradication — even if the patient had surgical treatment."
],
interaction="Run through the algorithm with a student volunteer: 'You are the doctor — I describe the patient, you make the decisions.'",
teaching_tip="This slide works well as a group exercise. Give students 60 seconds to trace through the algorithm on their own before you explain.",
watch_for=None
),
# ── SLIDE 21 ───────────────────────────────────────────────────────────────
dict(
num=21, title="MCQs — Test Yourself", timing="3 min", start=57, dur=3, cum=60,
purpose="Assess learning and consolidate recall — builds confidence for exams.",
script=[
"For each MCQ: Read the question aloud. Ask the class to vote by show of hands — or use a polling app if available.",
"Q1: 'Most common site of perforation — anterior wall of 1st part of duodenum. Anterior perforates, posterior bleeds.'",
"Q2: 'First-line eradication — PPI + clarithromycin + amoxicillin. This is Option B.'",
"Q3: 'Best test to CONFIRM eradication — Urea Breath Test. Not serology — stays positive after cure. Not CLO on repeat OGD — invasive and unnecessary for DU.'",
"Q4: 'Metabolic abnormality in pyloric stenosis — hypokalaemic hypochloraemic metabolic alkalosis. Option C.'"
],
key_points=[
"Q1 answer rationale: Anterior DU wall perforates into peritoneum → chemical peritonitis. Posterior wall erodes into GDA → haemorrhage.",
"Q2 answer rationale: H2 blockers insufficient for eradication — need PPI-level acid suppression.",
"Q3 answer rationale: UBT uses 13C-urea — urease from live H. pylori generates 13CO2 → detected in breath.",
"Q4 answer rationale: Vomiting → loss of H+ and Cl- → alkalosis + hypochloraemia → kidneys conserve Na+ by excreting K+ → hypokalaemia."
],
interaction="Class vote on each option before revealing the answer. This creates engagement and reveals misconceptions.",
teaching_tip="Reward correct answers verbally — 'Well done, that is exactly right.' Positive reinforcement increases participation in future sessions.",
watch_for="If majority votes wrong on Q4 — take 90 seconds to re-explain the electrolyte cascade. This is a commonly misunderstood concept."
),
# ── SLIDE 22 ───────────────────────────────────────────────────────────────
dict(
num=22, title="Special Situations", timing="2 min", start=57, dur=2, cum=59,
purpose="Extend knowledge to important clinical subgroups — applied clinical reasoning.",
script=[
"Scan through the four boxes quickly — one sentence each.",
"Elderly: 'Higher complication rate, atypical presentation, NSAIDs are the main driver. Elderly patients may perforate without classic peritonism because NSAIDs mask inflammation.'",
"Pregnancy: 'H2 blockers (ranitidine) are safe in pregnancy. PPIs — use with caution. Avoid clarithromycin. Always lifestyle first.'",
"Anticoagulation: 'Any patient on warfarin or NOACs with UGIB — immediate reversal, urgent OGD, PPI. Never restart anticoagulation without discussion with the cardiologist.'",
"NSAIDs: 'Risk stratify every NSAID-user. High-risk: always add PPI. COX-2 selective agents reduce GI toxicity — but do NOT eliminate it completely.'"
],
key_points=[
"Elderly perforation: increasing incidence in elderly women on NSAIDs — now outnumber young men.",
"Pregnancy: PUD often improves in 2nd/3rd trimester (progesterone slows gastric acid secretion).",
"NSAID risk stratification: prior GI bleed = highest risk. Age >65 + H. pylori positive = moderate risk.",
"COX-2 inhibitors: reduce GI events by ~50% vs traditional NSAIDs, but not zero risk."
],
interaction="Ask: 'An 80-year-old woman on ibuprofen and aspirin presents with sudden abdominal pain but no guarding — what do you suspect?' — Perforated peptic ulcer with atypical presentation.",
teaching_tip="Keep this brief — 2 minutes maximum. These topics can be followed up with self-directed reading.",
watch_for=None
),
# ── SLIDE 23 ───────────────────────────────────────────────────────────────
dict(
num=23, title="Prevention Strategies", timing="1 min", start=58, dur=1, cum=59,
purpose="Reinforce preventive medicine — connects to public health component of MBBS.",
script=[
"Quick scan — 'Prevention works at three levels. Primary: test and treat H. pylori, minimise NSAIDs, add PPI when you must use NSAIDs, stop smoking.'",
"NSAID risk stratification boxes: 'This is practical — you will prescribe NSAIDs. Always ask: is this patient high risk for GI bleed? If yes — use a COX-2 selective agent AND add a PPI.'"
],
key_points=[
"H. pylori test-and-treat strategy for dyspepsia <55 years: evidence-based and cost-effective.",
"Smoking cessation: reduces PUD relapse rate by 50% — as effective as some drug therapies.",
"Low-dose aspirin (75mg): causes significant GI risk. Add PPI for all patients on long-term aspirin.",
"The WHO has listed H. pylori as a Group 1 carcinogen — eradication also reduces gastric cancer risk."
],
interaction=None,
teaching_tip="Use the NSAID risk grid as a quick clinical decision tool. Students can apply it immediately in the ward.",
watch_for=None
),
# ── SLIDE 24 ───────────────────────────────────────────────────────────────
dict(
num=24, title="Closing Case — Sunita", timing="5 min", start=53, dur=5, cum=58,
purpose="Apply all session learning to a complex clinical scenario — higher-order thinking.",
script=[
"Read the case vignette aloud. Pause after 'free gas under right diaphragm.'",
"Ask: 'What is the diagnosis?' — Perforated peptic ulcer, secondary to NSAID + aspirin combination.",
"Q2 — Resuscitation: 'Think ABCDE. Airway — patent. Breathing — supplemental O2. Circulation — two large-bore IV cannulae, blood for FBC/U&E/group&crossmatch, 500mL crystalloid bolus. Disability — check GCS. Exposure — full abdomen examination.'",
"Q3 — Operation: 'Graham's omental patch repair. Thorough peritoneal toilet — this is as important as closing the perforation. Collect peritoneal fluid for culture. Post-op: NG tube, nil-by-mouth, IV PPI.'",
"Q4 — Post-op: 'IV PPI for 48 hours, then oral PPI for 8 weeks. Test for H. pylori — eradicate if positive. STOP NSAIDs AND aspirin — discuss with cardiologist about alternative antiplatelet. If H. pylori negative, lifelong PPI if NSAIDs cannot be stopped.'"
],
key_points=[
"This case deliberately has TWO pro-ulcer drugs: diclofenac (NSAID) + aspirin (antiplatelet) — highest risk combination for GI bleed/perforation.",
"Sunita is elderly female — increasingly the typical perforation patient. NSAIDs driving the epidemiology.",
"Peritoneal toilet is as critical as the repair — inadequate toilet → persistent contamination → septic peritonitis.",
"Post-op: H. pylori eradication is MANDATORY even after surgical treatment of complications."
],
interaction="Group discussion format: 4 questions in 5 minutes. Each question to a different student or group. Close by connecting back to Raju from the opening case.",
teaching_tip="Close the loop: 'Remember Raju from the beginning? Sunita is Raju 25 years later — if Raju had not been treated and had continued NSAIDs.' This narrative arc makes the session memorable.",
watch_for="Students may not know to stop aspirin — discuss the balance between GI risk and cardiovascular benefit. Always involve cardiology."
),
# ── SLIDE 25 ───────────────────────────────────────────────────────────────
dict(
num=25, title="Summary & Key Messages", timing="2 min", start=58, dur=2, cum=60,
purpose="Close the cognitive loop — summarise, reference back to objectives, invite questions.",
script=[
"Walk through all 10 key messages. For each one, ask a student to expand on it: 'You — tell me what triple therapy consists of.'",
"Message 10 — ZE: 'Any time you see a patient with multiple ulcers, unusual sites, refractory to PPI, or associated diarrhoea — think gastrinoma.'",
"Reference Bailey & Love: 'Everything today comes from Chapter 67 of Bailey & Love 28th edition. I strongly recommend reading pages 1178–1200 before your surgery exam.'",
"Quick revision questions: Go through all 4. Ask for hands.",
"Close: 'If you remember only three things from today: (1) Biopsy all gastric ulcers. (2) Triple therapy cures most PUD. (3) Perforated PUD needs urgent surgery — do not delay analgesia.' Thank the class."
],
key_points=[
"Refer back to the opening objectives — ask students if they can now answer the same 4 questions from the opening case.",
"Announce what the next lecture/topic will be — connects to the learning pathway.",
"Distribute handout now (not at the start) — so students engaged throughout and don't read ahead."
],
interaction="Ask students: 'Who can now answer Raju's case questions from the beginning?' — Full circle closure. 1–2 student responses.",
teaching_tip="End on time. Staying even 2 minutes over erodes trust and reduces attention in future sessions. If behind — cut from slides 22–23 first.",
watch_for="If students are disengaged by slide 25, your pacing was too slow in the middle sections. Note for next time."
),
] # end of slides list
# ─── RENDER SLIDES ────────────────────────────────────────────────────────
for sld in slides:
story.append(KeepTogether([
SlideBanner(sld["num"], sld["title"], sld["timing"], sld["cum"]),
Spacer(1, 2*mm),
TimingBar(sld["start"], sld["dur"]),
Spacer(1, 2*mm),
]))
# Timing details row
story.append(timing_note(sld["start"], sld["dur"], sld["cum"]))
story.append(Spacer(1, 2*mm))
# Purpose
story.append(SectionTag("PURPOSE"))
story.append(Spacer(1, 1*mm))
story.append(p(sld["purpose"]))
story.append(Spacer(1, 2*mm))
# Script
story.append(SectionTag("WHAT TO SAY (Script Guide)"))
story.append(Spacer(1, 1*mm))
for line in sld["script"]:
story.append(b(line))
story.append(Spacer(1, 2*mm))
# Key points
story.append(SectionTag("KEY TEACHING POINTS"))
story.append(Spacer(1, 1*mm))
for pt in sld["key_points"]:
story.append(b(pt))
story.append(Spacer(1, 2*mm))
# Interaction
if sld.get("interaction"):
story.append(SectionTag("STUDENT INTERACTION", NAVY_LIGHT))
story.append(Spacer(1, 1*mm))
story.append(warn(sld["interaction"]))
story.append(Spacer(1, 2*mm))
# Teaching tip
if sld.get("teaching_tip"):
story.append(SectionTag("TEACHING TIP", NAVY_LIGHT))
story.append(Spacer(1, 1*mm))
story.append(italic(sld["teaching_tip"]))
story.append(Spacer(1, 2*mm))
# Watch for
if sld.get("watch_for"):
story.append(SectionTag("WATCH FOR / COMMON ERRORS", NAVY_LIGHT))
story.append(Spacer(1, 1*mm))
story.append(warn(sld["watch_for"]))
story.append(Spacer(1, 2*mm))
story.append(hr())
# Page break every 2 slides to keep pages readable
if sld["num"] % 2 == 0 or sld["num"] in [3, 15, 24]:
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════════════
# APPENDIX A — QUICK REFERENCE CARD
# ══════════════════════════════════════════════════════════════════════════
story.append(PageBreak())
story.append(NavyBanner("APPENDIX A — QUICK REFERENCE CARD (Print & Keep)", height=22))
story.append(Spacer(1, 4*mm))
qr_data = [
[Paragraph("<b>Topic</b>", BODY), Paragraph("<b>Key Fact</b>", BODY)],
["Most common cause of PUD", "H. pylori (80% DU, 60% GU) + NSAIDs — together >90%"],
["Schwartz's law", "No acid = No ulcer"],
["Triple therapy", "PPI + Amoxicillin 1g + Clarithromycin 500mg — BD × 7–14 days"],
["Confirm eradication", "Urea Breath Test — ≥4 weeks after stopping PPI & antibiotics"],
["Gastric ulcer rule", "ALWAYS biopsy — cannot exclude malignancy clinically"],
["Anterior DU", "Tends to perforate"],
["Posterior DU", "Tends to bleed — erodes gastroduodenal artery (GDA)"],
["Forrest Ia / Ib", "Spurting / oozing bleed — 55% re-bleed — needs endoscopic Rx"],
["Perforation CXR", "Free gas under diaphragm — seen in >50% of cases"],
["Pyloric stenosis metabolic Dx", "Hypokalaemic hypochloraemic metabolic alkalosis"],
["ZE syndrome clue", "Fasting gastrin >1000 pg/mL + multiple/refractory ulcers"],
["Surgical indication", "Perforation, haemorrhage, obstruction, malignancy, failed Rx"],
["Post-op after PUD surgery", "Always eradicate H. pylori — reduces recurrence"],
["NSAID + aspirin combination", "Highest risk for GI bleed/perforation — always add PPI"],
["Alarm features — OGD mandatory", "Age >55, dysphagia, weight loss, anaemia, haematemesis, mass"],
]
qr_table = Table(qr_data, colWidths=[72*mm, 100*mm])
qr_table.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), NAVY),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 9),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, NAVY_TINT]),
("GRID", (0,0),(-1,-1), 0.4, NAVY_GREY),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 5),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
story.append(qr_table)
# ══════════════════════════════════════════════════════════════════════════
# APPENDIX B — QUESTION BANK
# ══════════════════════════════════════════════════════════════════════════
story.append(PageBreak())
story.append(NavyBanner("APPENDIX B — QUESTION BANK FOR IN-SESSION USE", height=22))
story.append(Spacer(1, 4*mm))
story.append(h("Opening Questions (use at start — gauge baseline)"))
for q in [
"Has anyone seen a patient with peptic ulcer on the ward this week?",
"Name two drugs that can cause peptic ulcers.",
"What is the most important investigation for upper GI symptoms?"
]:
story.append(b(q))
story.append(Spacer(1, 3*mm))
story.append(h("Mid-Lecture Questions (embed during teaching)"))
for q in [
"Why does the posterior duodenal ulcer bleed more than the anterior?",
"What is the mechanism by which NSAIDs cause gastric ulcers?",
"If you cannot stop the NSAID — what do you do?",
"What makes a gastric ulcer different from a duodenal ulcer in terms of malignancy risk?",
"A patient on dual antiplatelet therapy needs an OGD — what special precaution?",
"What is the CLO test and what does it detect?"
]:
story.append(b(q))
story.append(Spacer(1, 3*mm))
story.append(h("Case Discussion Questions (slides 3 & 24)"))
qa_items_case = [
("Raju — risk factors?", "NSAIDs (diclofenac), smoking, manual worker (stress). Missing: H. pylori status."),
("Sunita — what drugs caused this?", "Diclofenac (NSAID) + aspirin (antiplatelet) combination — highest GI risk."),
("Sunita — 3 immediate steps?", "IV access + fluids, IV analgesia, erect CXR / CT abdomen."),
("Sunita — operation of choice?", "Graham's omental patch repair + thorough peritoneal toilet."),
("Sunita — post-op drug to start?", "IV omeprazole infusion → oral PPI 40mg BD × 8 weeks + H. pylori eradication."),
]
story.append(qa_table(qa_items_case))
story.append(Spacer(1, 3*mm))
story.append(h("Closing / Assessment Questions"))
for q in [
"Without looking at your notes — what is triple therapy?",
"Name three alarm features that mandate urgent OGD.",
"What is the single most important post-operative medication after PUD surgery?",
"What electrolyte abnormality does pyloric stenosis cause?",
"A patient vomits 2 hours after a gastrectomy every time they eat — diagnosis and first-line management?"
]:
story.append(b(q))
# ══════════════════════════════════════════════════════════════════════════
# APPENDIX C — BOARD DIAGRAMS TO DRAW
# ══════════════════════════════════════════════════════════════════════════
story.append(PageBreak())
story.append(NavyBanner("APPENDIX C — BOARD DIAGRAMS TO DRAW DURING LECTURE", height=22))
story.append(Spacer(1, 4*mm))
diags = [
("Slide 6 — Aggressive vs Defensive Balance",
"Draw a simple balance scale. Left pan: HCl, pepsin, H. pylori, NSAIDs. Right pan: mucus, PGE2, blood flow. Tip the scale to show 'ulcer' when left outweighs right."),
("Slide 7 — H. pylori UBT Mechanism",
"Draw: Patient → drinks 13C-urea → H. pylori urease in stomach → 13C-urea broken down → 13CO2 exhaled → detected by mass spectrometry / IR sensor."),
("Slide 15 — Duodenal Anatomy (Anterior vs Posterior)",
"Simple cross-section of duodenum: mark anterior wall (faces peritoneum = perforation) and posterior wall (faces GDA = haemorrhage). Gastroduodenal artery runs behind first part."),
("Slide 17 — Electrolyte Cascade in Pyloric Stenosis",
"Repeated vomiting → ↓ H+ → ↓ Cl- (alkalosis) → kidney tries to restore: Na+/H+ exchange → H+ excreted (paradoxical aciduria) → K+ exchanged for Na+ → ↓ K+. Final: hypokalaemic hypochloraemic metabolic alkalosis."),
("Slide 20 — Management Algorithm (abbreviated)",
"Quick 3-branch tree on board: (1) <55, no alarm → Test & Treat. (2) >55 or alarm → OGD. (3) Complication → specific pathway. Students trace their patient through it."),
]
for title, desc in diags:
story.append(SectionTag(title))
story.append(Spacer(1, 1*mm))
story.append(p(desc))
story.append(Spacer(1, 3*mm))
# ─── BUILD PDF ────────────────────────────────────────────────────────────
def on_first_page(canvas, doc):
pass # no extra header on pages — already handled by flowables
doc.build(story, onFirstPage=on_first_page, onLaterPages=on_first_page)
print(f"✅ PDF saved: {OUTPUT}")
cd /home/daytona/workspace/peptic-ulcer-ppt && python3 create_speaker_notes.py 2…
ls -lh /home/daytona/workspace/peptic-ulcer-ppt/PUD_Speaker_Notes.pdf
PUD Speaker Notes
PDF Document · PDF
| Section | What it contains |
|---|---|
| Slide banner | Slide number, title, timing, cumulative time |
| Visual progress bar | Shows exactly where the slide sits in the 60-minute session |
| Timing row | Start, duration, cumulative, remaining |
| Purpose | Why this slide exists pedagogically |
| Script guide | Bullet-by-bullet what to say — word-for-word guidance |
| Key teaching points | Core facts the teacher must convey |
| Student interaction | Specific questions to ask / activities to run |
| Teaching tip | Board diagrams, mnemonics, memory techniques |
| Watch for | Common student mistakes to correct proactively |
Create a teacher's speaker notes PDF with timing guidance
PUD Speaker Notes
PDF Document · PDF