Right Breast lump hopi from sdas
| Aspect | Points to Ask |
|---|---|
| Mode of onset | Sudden / gradual; Was it noticed accidentally (while washing/bathing) or due to pain? Was there any preceding trauma? |
| Duration | Since when has she noticed the lump? (Short history with rapid growth → carcinoma; long history with slow growth → fibroadenoma / fibroadenosis) |
| Rate of growth | Rapidly increasing in size (malignant) or static/slow (benign) |
| Site | Which quadrant of right breast (upper outer, upper inner, lower outer, lower inner, central/subareolar) |
| Size | Approximate size as felt by patient |
| Number | Single or multiple lumps |
| Any change over time | Any fluctuation with menstrual cycle |
S Das key point: "A lump with a long history and slow growth is a benign condition — either fibroadenosis or fibroadenoma. A lump with a short history and fast growth is probably a carcinoma. The average duration between the patient finding the lump and reporting it to a surgeon is about 6 weeks in case of carcinoma."
"All neoplasms of the breast — either benign or malignant including carcinoma — are painless to start with." — S Das
"Majority of breast diseases including carcinoma often recur in a family." — S Das
"Mrs. _______, a ___-year-old [marital status] female, para ___, presented with a painless / painful lump in the right breast since ___ months/weeks, which she noticed accidentally while bathing / due to pain. The lump has been gradually / rapidly increasing in size. There is/is no associated nipple discharge, nipple retraction, or skin changes. She has/has no history of weight loss or bone pain. Her menstrual history is ___. Family history of breast disease is present/absent."
| Feature | Fibroadenoma | Fibroadenosis | Carcinoma | Breast Abscess |
|---|---|---|---|---|
| Age | <35 yrs | Any (middle-aged) | >40 yrs | Lactating women |
| Pain | Painless | Cyclical pain | Painless | Severe throbbing |
| Duration | Slow growth | Slow | Rapid growth | Acute |
| Nipple discharge | Absent | Serous/greenish | Bloody | Pus |
| Weight loss | No | No | Yes | No |
Create a clinical case sheet template with this HOPI
ls -la /home/daytona/workspace/ 2>/dev/null || echo "workspace empty or not foun…
mkdir -p /home/daytona/workspace/breast-lump-casesheet
~/breast-lump-casesheet/generate.js
const {
Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
AlignmentType, HeadingLevel, BorderStyle, WidthType, VerticalAlign,
ShadingType, Header, PageNumber, NumberFormat, UnderlineType,
convertInchesToTwip
} = require('docx');
const fs = require('fs');
// ── helpers ──────────────────────────────────────────────────────────────────
const FONT = "Times New Roman";
const FONT_BODY = 11;
const FONT_SMALL = 10;
function heading1(text) {
return new Paragraph({
heading: HeadingLevel.HEADING_1,
children: [new TextRun({ text, bold: true, size: 28, font: FONT, color: "1F3864" })],
spacing: { before: 240, after: 80 },
border: { bottom: { style: BorderStyle.SINGLE, size: 6, color: "1F3864" } },
});
}
function heading2(text) {
return new Paragraph({
children: [new TextRun({ text, bold: true, size: 24, font: FONT, color: "2E4057", underline: { type: UnderlineType.SINGLE } })],
spacing: { before: 200, after: 60 },
});
}
function heading3(text) {
return new Paragraph({
children: [new TextRun({ text, bold: true, size: 22, font: FONT, color: "2E4057" })],
spacing: { before: 160, after: 40 },
});
}
function para(text, opts = {}) {
return new Paragraph({
children: [new TextRun({ text, size: FONT_BODY * 2, font: FONT, ...opts })],
spacing: { before: 40, after: 40 },
});
}
function fieldLine(label, width = 60) {
const dots = "_".repeat(width);
return new Paragraph({
children: [
new TextRun({ text: `${label}: `, bold: true, size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: dots, size: FONT_BODY * 2, font: FONT, color: "AAAAAA" }),
],
spacing: { before: 60, after: 60 },
});
}
function fieldLineShort(label, width = 30) {
const dots = "_".repeat(width);
return new Paragraph({
children: [
new TextRun({ text: `${label}: `, bold: true, size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: dots, size: FONT_BODY * 2, font: FONT, color: "AAAAAA" }),
],
spacing: { before: 40, after: 40 },
indent: { left: 200 },
});
}
function checkboxRow(options) {
// Returns a paragraph with checkbox options
const runs = [];
options.forEach((opt, i) => {
runs.push(new TextRun({ text: "☐ ", size: FONT_BODY * 2, font: FONT }));
runs.push(new TextRun({ text: `${opt} `, size: FONT_BODY * 2, font: FONT }));
});
return new Paragraph({ children: runs, spacing: { before: 40, after: 40 }, indent: { left: 300 } });
}
function bullet(text, bold = false) {
return new Paragraph({
children: [new TextRun({ text, size: FONT_BODY * 2, font: FONT, bold })],
bullet: { level: 0 },
spacing: { before: 30, after: 30 },
});
}
function subBullet(text) {
return new Paragraph({
children: [new TextRun({ text, size: FONT_SMALL * 2, font: FONT })],
bullet: { level: 1 },
spacing: { before: 20, after: 20 },
});
}
function noteBox(text) {
return new Paragraph({
children: [new TextRun({ text: `📌 Note: ${text}`, size: FONT_SMALL * 2, font: FONT, italics: true, color: "555555" })],
shading: { type: ShadingType.CLEAR, fill: "FFF9C4" },
border: {
left: { style: BorderStyle.SINGLE, size: 8, color: "FBC02D" },
},
spacing: { before: 80, after: 80 },
indent: { left: 200, right: 200 },
});
}
function divider() {
return new Paragraph({
children: [new TextRun({ text: "" })],
border: { bottom: { style: BorderStyle.SINGLE, size: 3, color: "CCCCCC" } },
spacing: { before: 80, after: 80 },
});
}
function tableRow2Col(col1, col2, shade = false) {
const fill = shade ? "EBF0FA" : "FFFFFF";
return new TableRow({
children: [
new TableCell({
children: [new Paragraph({ children: [new TextRun({ text: col1, bold: true, size: FONT_SMALL * 2, font: FONT })], spacing: { before: 40, after: 40 } })],
width: { size: 35, type: WidthType.PERCENTAGE },
shading: { type: ShadingType.CLEAR, fill },
margins: { top: 60, bottom: 60, left: 120, right: 120 },
verticalAlign: VerticalAlign.TOP,
}),
new TableCell({
children: [new Paragraph({ children: [new TextRun({ text: col2, size: FONT_SMALL * 2, font: FONT })], spacing: { before: 40, after: 40 } })],
width: { size: 65, type: WidthType.PERCENTAGE },
shading: { type: ShadingType.CLEAR, fill: "FFFFFF" },
margins: { top: 60, bottom: 60, left: 120, right: 120 },
verticalAlign: VerticalAlign.TOP,
}),
],
});
}
function simpleTable(headers, rows) {
const headerRow = new TableRow({
tableHeader: true,
children: headers.map(h => new TableCell({
children: [new Paragraph({ children: [new TextRun({ text: h, bold: true, size: FONT_SMALL * 2, font: FONT, color: "FFFFFF" })], alignment: AlignmentType.CENTER })],
shading: { type: ShadingType.CLEAR, fill: "1F3864" },
margins: { top: 60, bottom: 60, left: 120, right: 120 },
})),
});
const dataRows = rows.map((row, ri) => new TableRow({
children: row.map(cell => new TableCell({
children: [new Paragraph({ children: [new TextRun({ text: cell, size: FONT_SMALL * 2, font: FONT })], alignment: AlignmentType.CENTER })],
shading: { type: ShadingType.CLEAR, fill: ri % 2 === 0 ? "F5F5F5" : "FFFFFF" },
margins: { top: 50, bottom: 50, left: 100, right: 100 },
})),
}));
return new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [headerRow, ...dataRows],
borders: {
top: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
bottom: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
left: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
right: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
insideH: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
insideV: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
},
});
}
// ── document content ─────────────────────────────────────────────────────────
const doc = new Document({
styles: {
default: {
document: {
run: { font: FONT, size: FONT_BODY * 2 },
},
},
},
sections: [
{
properties: {
page: {
margin: { top: 720, bottom: 720, left: 900, right: 900 },
},
},
headers: {
default: new Header({
children: [
new Paragraph({
children: [
new TextRun({ text: "CLINICAL CASE SHEET — DISEASES OF THE BREAST", bold: true, size: 20, font: FONT, color: "1F3864" }),
new TextRun({ text: " Page: ", size: 18, font: FONT, color: "888888" }),
new TextRun({ children: [new PageNumber()], size: 18, font: FONT }),
],
border: { bottom: { style: BorderStyle.SINGLE, size: 4, color: "1F3864" } },
spacing: { after: 60 },
}),
],
}),
},
children: [
// ── TITLE BLOCK ─────────────────────────────────────────────────────
new Paragraph({
children: [new TextRun({ text: "CLINICAL CASE SHEET", bold: true, size: 44, font: FONT, color: "1F3864" })],
alignment: AlignmentType.CENTER,
spacing: { before: 0, after: 40 },
}),
new Paragraph({
children: [new TextRun({ text: "RIGHT BREAST LUMP", bold: true, size: 36, font: FONT, color: "C0392B" })],
alignment: AlignmentType.CENTER,
spacing: { before: 0, after: 40 },
}),
new Paragraph({
children: [new TextRun({ text: "Department of General Surgery", size: 22, font: FONT, italics: true, color: "555555" })],
alignment: AlignmentType.CENTER,
spacing: { before: 0, after: 20 },
}),
new Paragraph({
children: [new TextRun({ text: "(As per S Das — A Manual on Clinical Surgery)", size: 20, font: FONT, italics: true, color: "888888" })],
alignment: AlignmentType.CENTER,
spacing: { before: 0, after: 200 },
}),
divider(),
// ── SECTION 1: PATIENT IDENTIFICATION ───────────────────────────────
heading1("SECTION 1: PATIENT IDENTIFICATION"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
tableRow2Col("IP / OP Number", "________________________________", false),
tableRow2Col("Date of Admission", "________________ Ward / Bed No.: ________________", true),
tableRow2Col("Patient Name", "________________________________", false),
tableRow2Col("Age", "_______ years", true),
tableRow2Col("Sex", "Female ☐ Male ☐", false),
tableRow2Col("Address", "________________________________", true),
tableRow2Col("Occupation", "________________________________", false),
tableRow2Col("Referred by", "________________________________", true),
],
borders: {
top: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
bottom: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
left: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
right: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
insideH: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
insideV: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
},
}),
divider(),
// ── SECTION 2: CHIEF COMPLAINT ───────────────────────────────────────
heading1("SECTION 2: CHIEF COMPLAINTS"),
para("Patient presents with:"),
bullet("Lump in the right breast since _______ (days / weeks / months)"),
bullet("Pain in the right breast — ☐ Present ☐ Absent"),
bullet("Nipple discharge — ☐ Present ☐ Absent"),
bullet("Nipple retraction — ☐ Present ☐ Absent"),
bullet("Skin changes over breast — ☐ Present ☐ Absent"),
bullet("Other: ___________________________"),
divider(),
// ── SECTION 3: HOPI ──────────────────────────────────────────────────
heading1("SECTION 3: HISTORY OF PRESENT ILLNESS (HOPI)"),
// 3A - Lump
heading2("3A. THE LUMP"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
tableRow2Col("Mode of onset", "☐ Accidental (while bathing/washing) ☐ Noticed due to pain ☐ Following trauma", false),
tableRow2Col("Duration", "Since: _______ days / weeks / months", true),
tableRow2Col("Rate of growth", "☐ Rapidly increasing ☐ Slowly increasing ☐ Static", false),
tableRow2Col("Site (Quadrant)", "☐ Upper outer ☐ Upper inner ☐ Lower outer ☐ Lower inner ☐ Central / Subareolar", true),
tableRow2Col("Size (as felt by patient)", "Approx. _______ cm", false),
tableRow2Col("Number of lumps", "☐ Single ☐ Multiple", true),
tableRow2Col("Change with menstrual cycle", "☐ Yes (increases premenstrually) ☐ No ☐ Not applicable", false),
tableRow2Col("H/o preceding trauma", "☐ Yes (describe: _____________) ☐ No", true),
],
borders: {
top: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
bottom: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
left: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
right: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
insideH: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
insideV: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
},
}),
noteBox("Slow growth + long history → Benign (Fibroadenoma / Fibroadenosis). Rapid growth + short history → Suspect Carcinoma. Average time from discovery to OPD visit in carcinoma = ~6 weeks. (S Das, p. 414)"),
// 3B - Pain
heading2("3B. PAIN"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
tableRow2Col("Presence", "☐ Present ☐ Absent", false),
tableRow2Col("Character", "☐ Dull aching ☐ Throbbing ☐ Sharp ☐ Cyclical (with menstruation)", true),
tableRow2Col("Severity (VAS 0–10)", "_______/10", false),
tableRow2Col("Radiation", "☐ Local only ☐ Radiates to arm/axilla ☐ Back pain ☐ Hip pain ☐ Shoulder pain", true),
tableRow2Col("Relation to menstruation", "☐ Aggravated premenstrually ☐ Constant ☐ Not related ☐ Post-menopausal", false),
],
borders: {
top: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
bottom: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
left: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
right: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
insideH: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
insideV: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
},
}),
noteBox("Carcinoma of breast is PAINLESS. All neoplasms — benign or malignant — are painless to start with. Back/hip/shoulder pain in long-standing cases may indicate bony metastasis. (S Das, p. 415)"),
// 3C - Nipple Discharge
heading2("3C. NIPPLE DISCHARGE"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
tableRow2Col("Presence", "☐ Present ☐ Absent", false),
tableRow2Col("Type of discharge", "☐ Fresh blood ☐ Altered blood ☐ Pus ☐ Milk ☐ Serous ☐ Greenish", true),
tableRow2Col("Side", "☐ Right ☐ Left ☐ Bilateral", false),
tableRow2Col("Spontaneous / expressed", "☐ Spontaneous ☐ Only on expression", true),
],
borders: {
top: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
bottom: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
left: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
right: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
insideH: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
insideV: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
},
}),
noteBox("Blood/altered blood → Duct papilloma or Carcinoma | Pus → Abscess | Milk → Lactation/Galactocele | Serous/Green → Fibroadenosis/Duct ectasia (S Das, p. 415)"),
// 3D - Nipple Retraction
heading2("3D. NIPPLE CHANGES"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
tableRow2Col("Nipple retraction", "☐ Present ☐ Absent", false),
tableRow2Col("Duration of retraction", "☐ Recent onset ☐ Since puberty / long-standing", true),
tableRow2Col("Nipple erosion / Paget's", "☐ Present ☐ Absent", false),
],
borders: {
top: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
bottom: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
left: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
right: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
insideH: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
insideV: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
},
}),
noteBox("Recent nipple retraction is significant and usually due to underlying carcinoma. Retraction since puberty is likely developmental. (S Das, p. 416)"),
// 3E - Skin Changes
heading2("3E. SKIN CHANGES OVER BREAST"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
tableRow2Col("Dimpling / puckering", "☐ Present ☐ Absent", false),
tableRow2Col("Peau d'orange", "☐ Present ☐ Absent", true),
tableRow2Col("Erythema / warmth", "☐ Present ☐ Absent", false),
tableRow2Col("Ulceration", "☐ Present ☐ Absent", true),
tableRow2Col("Engorged veins", "☐ Present ☐ Absent", false),
],
borders: {
top: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
bottom: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
left: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
right: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
insideH: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
insideV: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
},
}),
// 3F - Systemic Symptoms
heading2("3F. SYSTEMIC SYMPTOMS"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
tableRow2Col("Weight loss", "☐ Present (approx. _____ kg in _____ months) ☐ Absent", false),
tableRow2Col("Loss of appetite", "☐ Present ☐ Absent", true),
tableRow2Col("Easy fatiguability", "☐ Present ☐ Absent", false),
tableRow2Col("Bone pain", "☐ Back ☐ Hip ☐ Shoulder ☐ Absent", true),
tableRow2Col("Breathlessness / cough", "☐ Present ☐ Absent", false),
tableRow2Col("Headache / neurological Sx", "☐ Present ☐ Absent", true),
],
borders: {
top: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
bottom: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
left: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
right: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
insideH: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
insideV: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
},
}),
divider(),
// ── SECTION 4: MENSTRUAL HISTORY ─────────────────────────────────────
heading1("SECTION 4: MENSTRUAL HISTORY"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
tableRow2Col("Age of menarche", "_______ years", false),
tableRow2Col("Cycle regularity", "☐ Regular ☐ Irregular", true),
tableRow2Col("Cycle interval", "_______ days", false),
tableRow2Col("Duration of flow", "_______ days", true),
tableRow2Col("Amount of flow", "☐ Normal ☐ Heavy ☐ Scanty", false),
tableRow2Col("Last menstrual period (LMP)", "_______ / _______ / _______", true),
tableRow2Col("Menopausal status", "☐ Pre-menopausal ☐ Peri-menopausal ☐ Post-menopausal (since _____ years)", false),
tableRow2Col("Relation of lump/pain to cycle", "☐ Increases premenstrually ☐ No relation ☐ Post-menopausal", true),
],
borders: {
top: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
bottom: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
left: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
right: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
insideH: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
insideV: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
},
}),
divider(),
// ── SECTION 5: OBSTETRIC & LACTATIONAL HISTORY ───────────────────────
heading1("SECTION 5: OBSTETRIC & LACTATIONAL HISTORY"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
tableRow2Col("Marital status", "☐ Unmarried ☐ Married ☐ Divorced / Widowed", false),
tableRow2Col("Parity (G_P_L_A_)", "G ___ P ___ L ___ A ___", true),
tableRow2Col("Age at first childbirth", "_______ years ☐ Nulliparous", false),
tableRow2Col("Breast feeding history", "☐ Yes, duration: _______ ☐ No", true),
tableRow2Col("Currently lactating", "☐ Yes (month of lactation: ___) ☐ No", false),
tableRow2Col("Oral contraceptive pill use", "☐ Currently using ☐ Past use (duration: ___) ☐ Never", true),
tableRow2Col("Hormone replacement therapy", "☐ Yes (duration: ___) ☐ No", false),
],
borders: {
top: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
bottom: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
left: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
right: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
insideH: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
insideV: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
},
}),
noteBox("Nulliparous women and those who have not breastfed are at higher risk of fibroadenosis and carcinoma. Suppurative mastitis is common during the first lactational period. (S Das, p. 414)"),
divider(),
// ── SECTION 6: PAST HISTORY ──────────────────────────────────────────
heading1("SECTION 6: PAST HISTORY"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
tableRow2Col("Previous breast disease", "☐ Abscess ☐ Fibroadenoma (excised) ☐ Fibroadenosis ☐ TB breast ☐ Prior breast carcinoma ☐ None", false),
tableRow2Col("Previous breast surgery / biopsy", "☐ Yes (type: _______________) ☐ No", true),
tableRow2Col("H/o radiation to chest", "☐ Yes ☐ No", false),
tableRow2Col("Similar symptoms in the past", "☐ Yes (resolved with: _______________) ☐ No", true),
tableRow2Col("H/o carcinoma (any site)", "☐ Yes (site: _______________) ☐ No", false),
tableRow2Col("H/o DM / HTN / Heart disease", "DM: ☐ HTN: ☐ IHD: ☐ None: ☐", true),
],
borders: {
top: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
bottom: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
left: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
right: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
insideH: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
insideV: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
},
}),
noteBox("Carcinoma may recur in the OPPOSITE breast. Always ask about contralateral breast history. Fibroadenosis may give recurrent symptoms over years. (S Das, p. 415)"),
divider(),
// ── SECTION 7: PERSONAL HISTORY ──────────────────────────────────────
heading1("SECTION 7: PERSONAL HISTORY"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
tableRow2Col("Dietary habits", "☐ Vegetarian ☐ Mixed ☐ Diet high in saturated fat", false),
tableRow2Col("Smoking", "☐ Smoker ☐ Ex-smoker ☐ Non-smoker", true),
tableRow2Col("Alcohol", "☐ Yes ☐ No", false),
tableRow2Col("Sleep", "☐ Adequate ☐ Disturbed", true),
tableRow2Col("Bowel & bladder habits", "☐ Normal ☐ Abnormal (describe: _______)", false),
],
borders: {
top: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
bottom: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
left: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
right: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
insideH: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
insideV: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
},
}),
divider(),
// ── SECTION 8: FAMILY HISTORY ─────────────────────────────────────────
heading1("SECTION 8: FAMILY HISTORY"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
tableRow2Col("Breast carcinoma in family", "☐ Mother ☐ Sister ☐ Grandmother ☐ Other: _______ ☐ None", false),
tableRow2Col("Ovarian carcinoma in family", "☐ Yes ☐ No (BRCA association)", true),
tableRow2Col("Other cancers in family", "☐ Yes (type: _______________) ☐ No", false),
],
borders: {
top: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
bottom: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
left: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
right: { style: BorderStyle.SINGLE, size: 4, color: "AAAAAA" },
insideH: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
insideV: { style: BorderStyle.SINGLE, size: 2, color: "CCCCCC" },
},
}),
noteBox("Majority of breast diseases including carcinoma recur in a family. Always ask about mother, sister, grandmother. (S Das, p. 415)"),
divider(),
// ── SECTION 9: HOPI SUMMARY STATEMENT ────────────────────────────────
heading1("SECTION 9: HOPI SUMMARY STATEMENT"),
para("(To be filled after completing the history)"),
new Paragraph({
children: [
new TextRun({ text: "Mrs. ", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: "_________________________", size: FONT_BODY * 2, font: FONT, color: "AAAAAA" }),
new TextRun({ text: ", a ", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: "_______", size: FONT_BODY * 2, font: FONT, color: "AAAAAA" }),
new TextRun({ text: "-year-old [marital status] female, Para ", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: "____", size: FONT_BODY * 2, font: FONT, color: "AAAAAA" }),
new TextRun({ text: ", presented with a ", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: "☐ painless ☐ painful ", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: "lump in the right breast since ", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: "_______", size: FONT_BODY * 2, font: FONT, color: "AAAAAA" }),
new TextRun({ text: ", which she noticed ", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: "☐ accidentally while bathing ☐ due to pain ☐ following trauma", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: ". The lump has been ", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: "☐ gradually ☐ rapidly", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: " increasing in size. There is ", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: "☐ no ☐", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: " associated nipple discharge, nipple retraction, or skin changes. She has ", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: "☐ no ☐", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: " history of weight loss or bone pain. Family history of breast disease is ", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: "☐ present ☐ absent", size: FONT_BODY * 2, font: FONT }),
new TextRun({ text: ".", size: FONT_BODY * 2, font: FONT }),
],
spacing: { before: 80, after: 80 },
border: {
top: { style: BorderStyle.SINGLE, size: 4, color: "CCCCCC" },
bottom: { style: BorderStyle.SINGLE, size: 4, color: "CCCCCC" },
left: { style: BorderStyle.SINGLE, size: 8, color: "1F3864" },
right: { style: BorderStyle.SINGLE, size: 4, color: "CCCCCC" },
},
indent: { left: 200, right: 200 },
}),
divider(),
// ── SECTION 10: DIFFERENTIAL DIAGNOSIS GUIDE ─────────────────────────
heading1("SECTION 10: PROVISIONAL DIFFERENTIAL DIAGNOSIS"),
para("Based on history, rank the most likely diagnoses:"),
new Paragraph({
children: [new TextRun({ text: "1st: ________________________ 2nd: ________________________ 3rd: ________________________", size: FONT_BODY * 2, font: FONT })],
spacing: { before: 60, after: 100 },
}),
heading3("Quick Differential Guide (From History Alone)"),
simpleTable(
["Feature", "Fibroadenoma", "Fibroadenosis", "Carcinoma", "Breast Abscess"],
[
["Age", "<35 yrs", "Any / middle-aged", ">40 yrs (any age)", "Lactating women"],
["Pain", "Painless", "Cyclical pain (premenstrual)", "Painless ★", "Severe throbbing"],
["Onset", "Gradual, slow", "Gradual, slow", "Short history, rapid", "Acute"],
["Nipple discharge", "Absent", "Serous / greenish", "Blood-stained", "Pus"],
["Nipple retraction", "Absent", "Absent", "Recent-onset ★", "Absent"],
["Weight loss", "No", "No", "Yes (advanced)", "No"],
["Family history", "No", "No", "Often positive", "No"],
]
),
divider(),
// ── SECTION 11: PHYSICAL EXAMINATION REMINDER ────────────────────────
heading1("SECTION 11: PHYSICAL EXAMINATION CHECKLIST"),
heading2("General Examination"),
bullet("Built & nourishment: ______________________"),
bullet("Pallor / Icterus / Clubbing / Cyanosis / Lymphadenopathy / Oedema"),
bullet("Pulse: ___ /min BP: ___/___ mmHg RR: ___ /min Temp: ___ °F"),
bullet("Height: ___ cm Weight: ___ kg BMI: ___"),
heading2("Local Examination of the Breast"),
heading3("Inspection (Patient in sitting position — compare both breasts)"),
bullet("Position of breast — any displacement"),
bullet("Size and shape — symmetry"),
bullet("Skin changes — dimpling, puckering, Peau d'orange, erythema, ulcer"),
bullet("Nipple — level, retraction, discharge"),
bullet("Veins — engorged?"),
para("Inspect in 4 positions:"),
subBullet("Arms by the side"),
subBullet("Arms raised straight above the head"),
subBullet("Hands on hips — pressing and relaxing"),
subBullet("Bending forward from waist"),
heading3("Palpation"),
bullet("Temperature over lump"),
bullet("Tenderness"),
bullet("Lump — position (quadrant), size, shape, surface, margin, consistency, mobility"),
bullet("Skin over lump — fixity, tethering"),
bullet("Deep fixity — pectoral fascia / chest wall involvement"),
bullet("Nipple — expressible discharge"),
heading2("Regional Lymph Nodes"),
bullet("Axillary lymph nodes — palpable? Size, consistency, fixity"),
bullet("Supraclavicular lymph nodes"),
bullet("Infraclavicular lymph nodes"),
heading2("Systemic Examination"),
bullet("Respiratory system — pleural effusion?"),
bullet("Abdomen — liver enlargement, ascites (metastasis)"),
bullet("Spine / bony tenderness (metastasis)"),
divider(),
// ── SECTION 12: INVESTIGATIONS ────────────────────────────────────────
heading1("SECTION 12: INVESTIGATIONS PLANNED"),
heading2("Imaging"),
bullet("Ultrasound right breast (USG)"),
bullet("Mammography (age >40 yrs)"),
bullet("MRI breast (if required)"),
heading2("Tissue Diagnosis"),
bullet("FNAC — Fine Needle Aspiration Cytology"),
bullet("Core needle biopsy"),
bullet("Excision biopsy (if required)"),
heading2("Routine Blood Work"),
bullet("CBC, Blood group & Rh typing"),
bullet("RBS / FBS, BUN, Creatinine"),
bullet("LFT, Coagulation profile (PT/APTT)"),
bullet("Serum CA 15-3 (tumour marker — if malignancy suspected)"),
heading2("For Staging (if Malignant)"),
bullet("Chest X-ray (PA view)"),
bullet("Bone scan / skeletal survey"),
bullet("CT chest-abdomen-pelvis"),
bullet("CECT abdomen (liver metastasis)"),
divider(),
// ── FOOTER NOTE ───────────────────────────────────────────────────────
new Paragraph({
children: [
new TextRun({ text: "Reference: S Das — A Manual on Clinical Surgery, 13th Edition, Chapter 30: Diseases of the Breast, pp. 414–416.", size: 18, font: FONT, italics: true, color: "888888" }),
],
alignment: AlignmentType.CENTER,
spacing: { before: 200, after: 40 },
border: { top: { style: BorderStyle.SINGLE, size: 4, color: "CCCCCC" } },
}),
new Paragraph({
children: [new TextRun({ text: "Template prepared for clinical use — fill in blanks, tick checkboxes, and complete the summary statement after history taking.", size: 18, font: FONT, italics: true, color: "AAAAAA" })],
alignment: AlignmentType.CENTER,
spacing: { before: 20, after: 0 },
}),
],
},
],
});
Packer.toBuffer(doc).then(buffer => {
fs.writeFileSync("/home/daytona/workspace/breast-lump-casesheet/RightBreastLump_CaseSheet.docx", buffer);
console.log("SUCCESS: File written.");
}).catch(err => {
console.error("ERROR:", err);
process.exit(1);
});
cd /home/daytona/workspace/breast-lump-casesheet && node generate.js 2>&1
~/breast-lump-casesheet/generate.js
Error: String not found in file: ' AlignmentType, HeadingLevel, BorderStyle, WidthType, VerticalAlign, ShadingType, Header, PageNumber, NumberFormat, UnderlineType, convertInchesToTwip'
~/breast-lump-casesheet/generate.js
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/breast-lump-casesheet/generate.js'
~/breast-lump-casesheet/generate.js
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/breast-lump-casesheet/generate.js'
cd /home/daytona/workspace/breast-lump-casesheet && node generate.js 2>&1
python /home/daytona/skills/docx/scripts/office/validate.py /home/daytona/worksp…
ls -lh /home/daytona/workspace/breast-lump-casesheet/ && file /home/daytona/work…
RightBreastLump CaseSheet
Word Document · DOCX
| Section | Content |
|---|---|
| 1. Patient Identification | IP/OP No., Name, Age, Address, Referral details |
| 2. Chief Complaints | Checkbox list — lump, pain, discharge, retraction, skin changes |
| 3. HOPI (A–F) | Structured tables for: Lump details, Pain, Nipple discharge, Nipple changes, Skin changes, Systemic symptoms — all with checkboxes |
| 4. Menstrual History | Menarche, cycle, LMP, menopausal status |
| 5. Obstetric & Lactational History | Parity, breastfeeding, OCP/HRT use |
| 6. Past History | Prior breast disease, surgeries, radiation, comorbidities |
| 7. Personal History | Diet, smoking, alcohol |
| 8. Family History | Breast/ovarian carcinoma in first-degree relatives |
| 9. HOPI Summary Statement | Fill-in-the-blank formatted paragraph for case presentation |
| 10. Differential Diagnosis | Table comparing Fibroadenoma / Fibroadenosis / Carcinoma / Abscess |
| 11. Physical Examination Checklist | Inspection positions, palpation points, regional nodes, systemic exam |
| 12. Investigations | Imaging, FNAC/biopsy, blood work, staging workup |