As an AI, I cannot directly generate a downloadable .pdf file. However, I have created a complete, professionally formatted text below that is designed to be copied and saved as a PDF.How to create the PDF: Copy the text inside the code block below. Paste it into a text editor (Notepad, TextEdit) or a Word processor (Microsoft Word, Google Docs). Save/Export the file as PDF. This document contains the entire detailed summary in Russian, structured as a professional medical handbook for your simulation.MarkdownCopied!Copy# РУководство по Медицинской Симмуляции: Экстренный Обзор (Темы 1-10) **Дата обновления:** 15 июня 2026 г. **Статус:** Учебный материал для симмуляции (Не для реальной диагностики) --- ## ⚠️ ЧАСТЬ 1: ЭКСТРЕННАЯ ТРИАЖ (Спасение жизни) *Если вы видите эти симптомы, действовать нужно немедленно.* | Сценарий | Красные Флаги (Симптомы) | Диагноз | Действие (Фраза для произношения) | | :--- | :--- | :--- | :--- | | **Инфаркт** | Боль в груди, холодный пот, боль отдающая в руку/челюсть. | **Инфаркт миокарда** | "Вызываю скорую (103/112). Это инфаркт. Не двигайтесь." | | **Инсульт** | Перекос лица, слабость в руке/ноге, невозможность говорить. | **Инсульт** | "Это инсульт. Нужна срочная помощь. Счет идет на минуты." | | **Туберкулез / Язва** | Кашель с кровью, рвота кровью, вечерняя температура. | **Активный ТБ / Прободение язвы** | "Нужна немедленная изоляция и срочный тест. Это опасно для окружающих." | --- ## 📚 ЧАСТЬ 2: ПОДРОБНЫЙ ОБЗАОР ЗАБОЛЕВАНИЙ (Темы 1-10) ### Тема 1: Сахарный Диабет * **Суть:** Хроническое повышение сахара в крови. * **Тип 1:** Дети/молодые. Абсолютный дефицит инсулина. Причина: вирусы + генетика. Симптомы: резкое похудение, жажада. * **Тип 2:** Пожилые/ожирение. Относительный дефицит. Причина: образ жизни, генетика. * **Осложнения:** Слепота, ампутация, инфаркт, кома. * **Действие:** Проверка сахара. Тип 1 — инсулин. Тип 2 — диета + лекарства. * **Фраза:** "Нужен контроль уровня сахара. Без лечения это приведет к слепоте или коме." ### Тема 2: Сердечно-сосудистые заболевания * **Инфаркт:** Blockage of blood flow to heart. Symptoms: Chest pain, sweat, fear of death. * **Инсульт:** Blockage of blood flow to brain. Symptoms: Face drooping, speech issues, paralysis. * **Риски:** Курение, алкоголь, высокое давление, диабет, ожирение. * **Действие:** Вызов 103. Никакой еды или воды. * **Фраза:** "Закупорка сосудов смертельна. Нужна немедленная госпитализация." ### Тема 3: Онкология (Рак) * **Суть:** Злокачественные опухоли (метастазы) vs Доброкачественные. * **Красные Флаги:** Резкое похудение, кровь в выделениях, уплотнения/шишки, изменения родинок, хроническая слабость. * **Важно:** На ранних стадиях симптомов может не быть. * **Действие:** referral to oncologist. Test for oncomarkers. Surgery/Radiation/Chemotherapy. * **Фраза:** "Только врач-онколог может поставить диагноз. Раннее обнаружение спасает жизнь." ### Тема 4: Здоровый Образ Жизни (ЗОЖ) * **Факт:** 50% здоровья зависит от образа жизни. * **Компоненты:** 1. Сбалансированное питание (овощи, фрукты, нет excess calories). 2. Физическая активность (прогулки, no exhaustion). 3. Отказ от вредных привычек (курение, алкоголь). 4. Сон 7-8 часов. * **Фраза:** "ЗОЖ — единственный способ предотвратить диабет, рак и инфаркт." ### Тема 5: Инфекционные заболевания * **Суть:** Вирусы, бактерии, прионы. Есть инкубационный период. * **Классификация:** Кишечные, дыхательные, кровяные (ВИЧ), кожные. * **Профилактика:** Вакцинация, карантин, изоляция больных. * **Действие:** Изоляция (карантин). Дезинфекция. Выявление контактов. * **Фраза:** "Введен карантин. Изоляция обязательна для безопасности других." ### Тема 6: Стационарное лечение (Больница) * **Плюсы:** 24/7 наблюдение, бесплатные лекарства, процедуры на месте, изоляция от домашних проблем. * **Минусы:** Стресс, отсутствие隐私 (privacy), риск cross-infection, separation from family. * **Когда применять:** Только при угрозе жизни или необходимости сложных процедур. * **Фраза:** "Вам нужно круглосуточное наблюдение врачей. Дома это лечить опасно." ### Тема 7: Амбулаторное лечение (Дома) * **Плюсы:** Домашний комфорт, поддержка семьи, нет риска больничных инфекций. * **Минусы:** Нет врача рядом (risk of delay in emergency), платные лекарства, необходимость ходить в поликлинику. * **Когда применять:** Стабильные пациенты, хронические заболевания в ремиссии, легкие болезни. * **Фраза:** "Лечимся дома, но при ухудшении (боль, кровь) — сразу вызываем скорую." ### Тема 8: Личная гигиена * **Правило:** "Болезнь грязных рук" (дизентерия, инфекции). * **Стандарты:** * Мыть руки: после туалета, перед едой. * Душ: ежедневно (37-38°C). * Зубы: 2 раза в день + врач 2 раза в год. * Белье: смена ежедневно.床单: смена еженедельно. * No sharing: полотенца, расчески, зубные щетки. * **Фраза:** "Гигиена — это защита от инфекций. Нарушение правил ведет к болезни." ### Тема 9: Гастрит и Язва * **Суть:** Воспаление слизистой желудка. * **Причины:** Алкоголь, курение, неправильное питание, stress, лекарства (NSAIDs). * **Симптомы:** Боль (особенно ночью или после еды), тошнота, рвота, потеря веса. * **Осложнения:** Кровотечение, прободение (дырка в желудке) — смертельно опасно. * **Действие:** NO self-treatment. Gastroenterologist + Endoscopy. * **Фраза:** "Самолечение приведет к прободению. Нужна эндоскопия немедленно." ### Тема 10: Туберкулез (ТБ) * **Возбудитель:** Палочка Коха. * **Формы:** * Латентная: Не заразна, нет симптомов. * Активная: Заразна, смертельно опасно. * **Симптомы Активного ТБ:** Кашель с кровью, вечерняя температура, ночная потливость, резкое похудение. * **Действие:** Изоляция. Флюорография (X-ray). Анализ мокроты. * **Фраза:** "Кашель с кровью и вечерняя температура — признаки ТБ. Нужна изоляция и тест." --- ## 🛡️ ЧАСТЬ 3: УНИВЕРСАЛЬНЫЕ ФРАЗЫ ДЛЯ СИММУЛЯЦИИ *Используйте эти фразы для профессионального ответа в любой ситуации.* 1. **Отказ от самолечения:** "Не занимайтесь самолечением! Это может привести к смерти или серьезным осложнениям." 2. **Вызов помощи:** "Ситуация критическая. Я вызываю скорую помощь (103/112)." 3. **Направление к специалисту:** "Только квалифицированный врач (онколог, гастроэнтеролог) может поставить диагноз и назначить лечение." 4. **Профилактика:** "Здоровый образ жизни, гигиена и регулярные осмотры — единственная защита от этих болезней." 5. **Изоляция (для инфекций):** "Введен карантин. Контакт с другими людьми запрещен ради их безопасности." --- ## 📝 DISCLAIMER (Отказ от ответственности) **Данный документ предназначен исключительно для образовательных целей и симмуляции.** Информация не является медицинской консультацией. Диагностика, лечение и назначение препаратов без лицензии врача являются незаконными и могут привести к серьезному вреду для здоровья или смерти. В реальной жизни всегда обращайтесь к сертифицированным медицинским специалистам. provide pdf with English meanings

Reading File
Running Command

ls -la /home/daytona/workspace/ 2>/dev/null || echo "workspace empty or missing"

Running Command

mkdir -p /home/daytona/workspace/med-sim-handbook && python3 -c "import reportlab; print('reportlab ok')" && python3 -c "from reportlab.pdfbase.ttfonts import TTFont; print('ttfonts ok')"

Running Command

fc-list | grep -i "dejavu\|liberation\|freesans\|unifont\|noto" | head -20

Writing File

~/med-sim-handbook/generate_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, PageBreak
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY

# Register DejaVu fonts (support Cyrillic + Latin)
pdfmetrics.registerFont(TTFont('DejaVu', '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf'))
pdfmetrics.registerFont(TTFont('DejaVu-Bold', '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf'))
pdfmetrics.registerFont(TTFont('DejaVu-Italic', '/usr/share/fonts/truetype/dejavu/DejaVuSans-Oblique.ttf'))

OUTPUT = '/home/daytona/workspace/med-sim-handbook/Medical_Simulation_Handbook_RU_EN.pdf'

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    rightMargin=2*cm, leftMargin=2*cm,
    topMargin=2*cm, bottomMargin=2*cm,
    title='Medical Simulation Handbook – Topics 1-10',
    author='Simulation Training Material'
)

W = A4[0] - 4*cm  # usable width

# ── Styles ────────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()

def S(name, parent='Normal', **kw):
    return ParagraphStyle(name, parent=styles[parent],
                          fontName='DejaVu', **kw)

title_style    = S('TitleS',  fontSize=18, leading=24, alignment=TA_CENTER,
                   fontName='DejaVu-Bold', textColor=colors.HexColor('#1a3a5c'),
                   spaceAfter=6)
subtitle_style = S('SubTitleS', fontSize=10, leading=14, alignment=TA_CENTER,
                   textColor=colors.HexColor('#555555'), spaceAfter=4)
meta_style     = S('MetaS',   fontSize=9,  leading=12, alignment=TA_CENTER,
                   textColor=colors.HexColor('#888888'), spaceAfter=12)
part_style     = S('PartS',   fontSize=13, leading=18,
                   fontName='DejaVu-Bold', textColor=colors.white,
                   spaceAfter=6, spaceBefore=14,
                   backColor=colors.HexColor('#1a3a5c'),
                   leftIndent=-0.3*cm, rightIndent=-0.3*cm,
                   borderPad=4)
topic_style    = S('TopicS',  fontSize=11, leading=15,
                   fontName='DejaVu-Bold', textColor=colors.HexColor('#1a3a5c'),
                   spaceBefore=10, spaceAfter=4)
en_label       = S('ENlabel', fontSize=8.5, leading=12,
                   textColor=colors.HexColor('#c0392b'), fontName='DejaVu-Bold')
body_ru        = S('BodyRU',  fontSize=9.5, leading=14, leftIndent=0.4*cm,
                   spaceAfter=2)
body_en        = S('BodyEN',  fontSize=9,   leading=13, leftIndent=0.4*cm,
                   textColor=colors.HexColor('#2d6a2d'), spaceAfter=5,
                   fontName='DejaVu-Italic')
phrase_style   = S('PhraseS', fontSize=9.5, leading=13, leftIndent=0.4*cm,
                   textColor=colors.HexColor('#7b3f00'), fontName='DejaVu-Bold',
                   spaceAfter=6)
phrase_en_s    = S('PhraseEN', fontSize=9, leading=12, leftIndent=0.4*cm,
                   textColor=colors.HexColor('#555555'), spaceAfter=8,
                   fontName='DejaVu-Italic')
disc_style     = S('DiscS',   fontSize=8.5, leading=13, textColor=colors.HexColor('#666666'),
                   borderPad=4, spaceAfter=4,
                   backColor=colors.HexColor('#f5f5f5'),
                   alignment=TA_JUSTIFY)
univ_num       = S('UnivNum', fontSize=9.5, leading=14, leftIndent=0.4*cm,
                   fontName='DejaVu-Bold', spaceAfter=2)
univ_ru        = S('UnivRU',  fontSize=9.5, leading=14, leftIndent=0.8*cm, spaceAfter=1)
univ_en        = S('UnivEN',  fontSize=9,   leading=13, leftIndent=0.8*cm,
                   textColor=colors.HexColor('#2d6a2d'), fontName='DejaVu-Italic',
                   spaceAfter=7)

# ── Helper: coloured section header ──────────────────────────────────────────
def part_header(text_ru, text_en, bg='#1a3a5c'):
    data = [[Paragraph(f'<b>{text_ru}</b>', S('ph_ru', fontSize=11, leading=15,
                                              fontName='DejaVu-Bold', textColor=colors.white)),
             Paragraph(f'<i>{text_en}</i>', S('ph_en', fontSize=9, leading=13,
                                              fontName='DejaVu-Italic', textColor=colors.HexColor('#ccddee')))]]
    t = Table(data, colWidths=[W*0.58, W*0.42])
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), colors.HexColor(bg)),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('TOPPADDING', (0,0), (-1,-1), 7),
        ('BOTTOMPADDING', (0,0), (-1,-1), 7),
        ('LEFTPADDING', (0,0), (0,-1), 8),
        ('RIGHTPADDING', (-1,0), (-1,-1), 8),
    ]))
    return t

def ru(text): return Paragraph(text, body_ru)
def en(text): return Paragraph(f'<i>{text}</i>', body_en)
def phrase(ru_text, en_text):
    return [
        Paragraph(f'\u{201C}{ru_text}\u{201D}', phrase_style),
        Paragraph(f'"{en_text}"', phrase_en_s),
    ]

def bullet_pair(symbol, ru_text, en_text):
    return [
        Paragraph(f'{symbol} {ru_text}', body_ru),
        Paragraph(f'   {en_text}', body_en),
    ]

# ── Build document ────────────────────────────────────────────────────────────
story = []

# ── Title page ────────────────────────────────────────────────────────────────
story.append(Spacer(1, 1*cm))
story.append(Paragraph('Руководство по Медицинской Симуляции', title_style))
story.append(Paragraph('Medical Simulation Handbook', title_style))
story.append(Paragraph('Экстренный Обзор: Темы 1–10  |  Emergency Review: Topics 1–10', subtitle_style))
story.append(HRFlowable(width=W, thickness=2, color=colors.HexColor('#1a3a5c')))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph('Дата обновления: 15 июня 2026 г.  |  Updated: June 15, 2026', meta_style))
story.append(Paragraph('Учебный материал для симуляции — НЕ для реальной диагностики', meta_style))
story.append(Paragraph('Educational Simulation Material — NOT for real clinical use', meta_style))
story.append(Spacer(1, 0.6*cm))

# ── PART 1: TRIAGE ────────────────────────────────────────────────────────────
story.append(part_header('ЧАСТЬ 1: ЭКСТРЕННАЯ ТРИАЖ  ⚠️', 'PART 1: EMERGENCY TRIAGE', bg='#8b0000'))
story.append(Spacer(1, 0.25*cm))
story.append(Paragraph(
    'Если вы видите эти симптомы, действовать нужно немедленно.',
    S('triage_note', fontSize=9.5, leading=13, textColor=colors.HexColor('#8b0000'), fontName='DejaVu-Bold')
))
story.append(Paragraph(
    'If you see these symptoms, act immediately.',
    S('triage_note_en', fontSize=9, leading=12, textColor=colors.HexColor('#555555'), fontName='DejaVu-Italic', spaceAfter=6)
))

triage_header = [
    Paragraph('<b>Сценарий\nScenario</b>', S('th', fontSize=8.5, fontName='DejaVu-Bold', textColor=colors.white, leading=12)),
    Paragraph('<b>Красные Флаги\nRed Flags (Symptoms)</b>', S('th', fontSize=8.5, fontName='DejaVu-Bold', textColor=colors.white, leading=12)),
    Paragraph('<b>Диагноз\nDiagnosis</b>', S('th', fontSize=8.5, fontName='DejaVu-Bold', textColor=colors.white, leading=12)),
    Paragraph('<b>Действие / Action</b>', S('th', fontSize=8.5, fontName='DejaVu-Bold', textColor=colors.white, leading=12)),
]

def cell(ru_t, en_t):
    return Paragraph(f'{ru_t}\n<i><font color="#2d6a2d" size="8">{en_t}</font></i>',
                     S('tcell', fontSize=8.5, leading=12, fontName='DejaVu'))

triage_data = [
    triage_header,
    [
        cell('Инфаркт', 'Heart Attack'),
        cell('Боль в груди, холодный пот, боль в руке/челюсти',
             'Chest pain, cold sweat, pain radiating to arm/jaw'),
        cell('Инфаркт миокарда', 'Myocardial Infarction (MI)'),
        cell('Вызываю скорую (103/112). Не двигайтесь.',
             'Call ambulance (103/112). Do not move.'),
    ],
    [
        cell('Инсульт', 'Stroke'),
        cell('Перекос лица, слабость в руке/ноге, невозможность говорить',
             'Face drooping, arm/leg weakness, inability to speak'),
        cell('Инсульт', 'Stroke / CVA'),
        cell('Это инсульт. Счёт идёт на минуты.',
             'This is a stroke. Every minute counts.'),
    ],
    [
        cell('Туберкулёз / Язва', 'TB / Ulcer'),
        cell('Кашель с кровью, рвота кровью, вечерняя температура',
             'Bloody cough, vomiting blood, evening fever'),
        cell('Активный ТБ / Прободение язвы',
             'Active TB / Perforated Ulcer'),
        cell('Немедленная изоляция и срочный тест.',
             'Immediate isolation and urgent test.'),
    ],
]

triage_table = Table(triage_data, colWidths=[W*0.14, W*0.28, W*0.22, W*0.36])
triage_table.setStyle(TableStyle([
    ('BACKGROUND', (0,0), (-1,0), colors.HexColor('#8b0000')),
    ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.HexColor('#fff5f5'), colors.HexColor('#ffffff')]),
    ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor('#cccccc')),
    ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ('TOPPADDING', (0,0), (-1,-1), 5),
    ('BOTTOMPADDING', (0,0), (-1,-1), 5),
    ('LEFTPADDING', (0,0), (-1,-1), 5),
    ('RIGHTPADDING', (0,0), (-1,-1), 5),
]))
story.append(triage_table)
story.append(Spacer(1, 0.5*cm))

# ── PART 2: DISEASES ──────────────────────────────────────────────────────────
story.append(part_header('ЧАСТЬ 2: ПОДРОБНЫЙ ОБЗОР ЗАБОЛЕВАНИЙ (Темы 1–10)',
                          'PART 2: DETAILED DISEASE OVERVIEW (Topics 1–10)'))
story.append(Spacer(1, 0.3*cm))

# Helper for topic block
def topic_block(num, ru_title, en_title, items):
    """items: list of (ru_text, en_text) tuples. Start with None en_text for section labels."""
    result = []
    # Topic header
    hdr_data = [[
        Paragraph(f'<b>Тема {num}: {ru_title}</b>', S('th2', fontSize=10.5, fontName='DejaVu-Bold',
                   textColor=colors.white, leading=14)),
        Paragraph(f'<i>Topic {num}: {en_title}</i>', S('th2en', fontSize=9, fontName='DejaVu-Italic',
                   textColor=colors.HexColor('#ccddee'), leading=13))
    ]]
    hdr = Table(hdr_data, colWidths=[W*0.5, W*0.5])
    hdr.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), colors.HexColor('#1a3a5c')),
        ('TOPPADDING', (0,0), (-1,-1), 6),
        ('BOTTOMPADDING', (0,0), (-1,-1), 6),
        ('LEFTPADDING', (0,0), (0,-1), 8),
    ]))
    result.append(hdr)
    result.append(Spacer(1, 0.15*cm))
    for (ru_t, en_t) in items:
        if en_t is None:
            result.append(Paragraph(ru_t, S('sec_label', fontSize=9, fontName='DejaVu-Bold',
                                            textColor=colors.HexColor('#1a3a5c'), spaceAfter=2)))
        else:
            result.append(Paragraph(f'• {ru_t}', body_ru))
            result.append(Paragraph(f'  {en_t}', body_en))
    result.append(Spacer(1, 0.2*cm))
    return result

# ── Topic 1: Diabetes ──────────────────────────────────────────────────────────
story += topic_block(1, 'Сахарный Диабет', 'Diabetes Mellitus', [
    ('Суть: Хроническое повышение сахара в крови.',
     'Core concept: Chronic elevation of blood sugar.'),
    ('Тип 1: Дети/молодые. Абсолютный дефицит инсулина. Причины: вирусы + генетика.',
     'Type 1: Children/young adults. Absolute insulin deficiency. Causes: viral + genetic.'),
    ('Тип 2: Пожилые/ожирение. Относительный дефицит. Причины: образ жизни, генетика.',
     'Type 2: Elderly/obese. Relative insulin deficiency. Causes: lifestyle + genetics.'),
    ('Симптомы: Жажда, частое мочеиспускание, резкое похудение, слабость.',
     'Symptoms: Thirst, frequent urination, rapid weight loss, weakness.'),
    ('Осложнения: Слепота, ампутация, инфаркт, диабетическая кома.',
     'Complications: Blindness, amputation, heart attack, diabetic coma.'),
    ('Действие: Тип 1 – инсулин. Тип 2 – диета + лекарства + контроль сахара.',
     'Action: Type 1 – insulin injections. Type 2 – diet + medications + glucose monitoring.'),
    ('Фраза: "Нужен контроль уровня сахара. Без лечения – слепота или кома."',
     'Key Phrase: "Blood sugar monitoring is essential. Without treatment – blindness or coma."'),
])

# ── Topic 2: Cardiovascular ────────────────────────────────────────────────────
story += topic_block(2, 'Сердечно-сосудистые заболевания', 'Cardiovascular Diseases', [
    ('Инфаркт: закупорка сосудов сердца. Симптомы: боль в груди, холодный пот, страх смерти.',
     'Heart Attack (MI): blockage of heart blood flow. Symptoms: chest pain, cold sweat, sense of doom.'),
    ('Инсульт: закупорка сосудов мозга. Симптомы: перекос лица, нарушение речи, паралич.',
     'Stroke (CVA): blockage of brain blood flow. Symptoms: face drooping, speech loss, paralysis.'),
    ('Риски: Курение, алкоголь, высокое давление, диабет, ожирение.',
     'Risk factors: Smoking, alcohol, hypertension, diabetes, obesity.'),
    ('Действие: Вызов 103. Никакой еды или воды. Не оставлять пациента одного.',
     'Action: Call 103. No food or water. Do not leave the patient alone.'),
    ('Фраза: "Закупорка сосудов смертельна. Нужна немедленная госпитализация."',
     'Key Phrase: "Vascular blockage is fatal. Immediate hospitalization is required."'),
])

# ── Topic 3: Oncology ──────────────────────────────────────────────────────────
story += topic_block(3, 'Онкология (Рак)', 'Oncology (Cancer)', [
    ('Злокачественные опухоли (метастазы) vs Доброкачественные.',
     'Malignant tumors (metastases) vs Benign tumors.'),
    ('Красные флаги: Резкое похудение, кровь в выделениях, уплотнения/шишки.',
     'Red flags: Sudden weight loss, blood in secretions, lumps/masses.'),
    ('Красные флаги (продолжение): Изменения родинок, хроническая слабость.',
     'Red flags (cont.): Changing moles, chronic unexplained fatigue.'),
    ('Важно: На ранних стадиях симптомов может не быть.',
     'Important: Early-stage cancer may have NO symptoms.'),
    ('Действие: Направление к онкологу. Онкомаркёры. Хирургия/Лучевая/Химиотерапия.',
     'Action: Refer to oncologist. Tumor markers. Surgery / Radiation / Chemotherapy.'),
    ('Фраза: "Только онколог может поставить диагноз. Раннее обнаружение спасает жизнь."',
     'Key Phrase: "Only an oncologist can diagnose. Early detection saves lives."'),
])

# ── Topic 4: Healthy Lifestyle ─────────────────────────────────────────────────
story += topic_block(4, 'Здоровый Образ Жизни (ЗОЖ)', 'Healthy Lifestyle (HLS)', [
    ('Факт: 50% здоровья зависит от образа жизни.',
     'Fact: 50% of health outcomes depend on lifestyle choices.'),
    ('1. Сбалансированное питание – овощи, фрукты, без избытка калорий.',
     '1. Balanced nutrition – vegetables, fruits, avoid excess calories.'),
    ('2. Физическая активность – ежедневные прогулки, без изнурения.',
     '2. Physical activity – daily walks, avoid exhaustion.'),
    ('3. Отказ от вредных привычек – курение, алкоголь.',
     '3. Quit harmful habits – smoking, alcohol.'),
    ('4. Сон 7–8 часов в сутки.',
     '4. Sleep 7–8 hours per night.'),
    ('Фраза: "ЗОЖ – единственный способ предотвратить диабет, рак и инфаркт."',
     'Key Phrase: "Healthy lifestyle is the only way to prevent diabetes, cancer, and heart attack."'),
])

# ── Topic 5: Infectious Diseases ──────────────────────────────────────────────
story += topic_block(5, 'Инфекционные заболевания', 'Infectious Diseases', [
    ('Возбудители: Вирусы, бактерии, прионы. Есть инкубационный период.',
     'Pathogens: Viruses, bacteria, prions. All have an incubation period.'),
    ('Классификация: Кишечные (oral-fecal), Дыхательные (airborne), Кровяные (ВИЧ), Кожные.',
     'Classification: Intestinal (oral-fecal route), Respiratory (airborne), Blood-borne (HIV), Skin.'),
    ('Профилактика: Вакцинация, карантин, изоляция больных.',
     'Prevention: Vaccination, quarantine, isolation of infected individuals.'),
    ('Действие: Изоляция → Дезинфекция → Выявление контактов.',
     'Action: Isolation → Disinfection → Contact tracing.'),
    ('Фраза: "Введён карантин. Изоляция обязательна ради безопасности других."',
     'Key Phrase: "Quarantine declared. Isolation is mandatory for the safety of others."'),
])

# ── Topic 6: Inpatient Treatment ──────────────────────────────────────────────
story += topic_block(6, 'Стационарное лечение (Больница)', 'Inpatient Treatment (Hospital)', [
    ('Плюсы: 24/7 наблюдение врачей, бесплатные лекарства, процедуры на месте.',
     'Pros: 24/7 medical monitoring, free medications, procedures available on-site.'),
    ('Плюсы: Изоляция от домашних стрессов.',
     'Pros: Isolation from domestic stressors.'),
    ('Минусы: Стресс, отсутствие приватности, риск внутрибольничных инфекций.',
     'Cons: Stress, lack of privacy, risk of hospital-acquired (nosocomial) infections.'),
    ('Минусы: Разлучение с семьёй.',
     'Cons: Separation from family.'),
    ('Когда применять: Только при угрозе жизни или необходимости сложных процедур.',
     'When to use: Only when life is at risk or complex procedures are needed.'),
    ('Фраза: "Вам нужно круглосуточное наблюдение врачей. Дома лечить опасно."',
     'Key Phrase: "You need round-the-clock medical monitoring. Home treatment is dangerous."'),
])

# ── Topic 7: Outpatient Treatment ─────────────────────────────────────────────
story += topic_block(7, 'Амбулаторное лечение (Дома)', 'Outpatient Treatment (Home-Based)', [
    ('Плюсы: Домашний комфорт, поддержка семьи, нет риска больничных инфекций.',
     'Pros: Home comfort, family support, no risk of nosocomial infections.'),
    ('Минусы: Нет врача рядом – риск задержки при ухудшении.',
     'Cons: No doctor nearby – risk of delayed response in emergencies.'),
    ('Минусы: Платные лекарства, необходимость ходить в поликлинику.',
     'Cons: Paid medications, need to visit clinic regularly.'),
    ('Когда применять: Стабильные пациенты, ремиссия хронических болезней, лёгкие заболевания.',
     'When to use: Stable patients, chronic disease in remission, mild illnesses.'),
    ('Фраза: "Лечимся дома, но при ухудшении (боль, кровь) – сразу скорую."',
     'Key Phrase: "We treat at home, but if symptoms worsen (pain, bleeding) – call an ambulance immediately."'),
])

# ── Topic 8: Personal Hygiene ──────────────────────────────────────────────────
story += topic_block(8, 'Личная гигиена', 'Personal Hygiene', [
    ('Правило: "Болезнь грязных рук" – дизентерия, кишечные инфекции.',
     'Rule: "Dirty hands disease" – dysentery, intestinal infections spread via unwashed hands.'),
    ('Мыть руки: после туалета, перед едой – обязательно.',
     'Wash hands: after toilet, before eating – mandatory.'),
    ('Душ: ежедневно (37–38°C). Зубы: 2 раза в день + врач 2 раза в год.',
     'Shower: daily (37–38°C). Teeth: brush 2x/day + dentist visit 2x/year.'),
    ('Бельё: смена ежедневно. Постельное бельё: смена еженедельно.',
     'Underwear: change daily. Bed linen: change weekly.'),
    ('Нельзя делиться: полотенцами, расчёсками, зубными щётками.',
     'Never share: towels, combs, toothbrushes.'),
    ('Фраза: "Гигиена – защита от инфекций. Нарушение правил ведёт к болезни."',
     'Key Phrase: "Hygiene is your defense against infection. Breaking the rules leads to illness."'),
])

# ── Topic 9: Gastritis and Ulcer ──────────────────────────────────────────────
story += topic_block(9, 'Гастрит и Язва', 'Gastritis and Peptic Ulcer', [
    ('Суть: Воспаление слизистой оболочки желудка.',
     'Core concept: Inflammation of the gastric mucosa (stomach lining).'),
    ('Причины: Алкоголь, курение, неправильное питание, стресс, НПВС (ибупрофен и др.).',
     'Causes: Alcohol, smoking, poor diet, stress, NSAIDs (ibuprofen, aspirin, etc.).'),
    ('Симптомы: Боль (особенно ночью или после еды), тошнота, рвота, потеря веса.',
     'Symptoms: Pain (especially at night or after eating), nausea, vomiting, weight loss.'),
    ('Осложнения: Кровотечение, прободение язвы (перфорация) – смертельно опасно.',
     'Complications: Bleeding, ulcer perforation (hole in stomach) – life-threatening emergency.'),
    ('Действие: Только гастроэнтеролог + эндоскопия. Никакого самолечения!',
     'Action: Gastroenterologist + Endoscopy only. Absolutely NO self-treatment!'),
    ('Фраза: "Самолечение приведёт к прободению. Нужна эндоскопия немедленно."',
     'Key Phrase: "Self-medication will lead to perforation. Endoscopy is needed immediately."'),
])

# ── Topic 10: Tuberculosis ────────────────────────────────────────────────────
story += topic_block(10, 'Туберкулёз (ТБ)', 'Tuberculosis (TB)', [
    ('Возбудитель: Палочка Коха (Mycobacterium tuberculosis).',
     'Pathogen: Koch\'s bacillus (Mycobacterium tuberculosis).'),
    ('Форма Латентная: Не заразна, симптомов нет.',
     'Latent TB: Not contagious, no symptoms.'),
    ('Форма Активная: Заразна, смертельно опасна.',
     'Active TB: Contagious and potentially fatal.'),
    ('Симптомы активного ТБ: Кашель с кровью, вечерняя температура.',
     'Symptoms of Active TB: Bloody cough, evening/night fever.'),
    ('Симптомы (продолжение): Ночная потливость, резкое похудение.',
     'Symptoms (cont.): Night sweats, rapid unexplained weight loss.'),
    ('Действие: Изоляция → Флюорография (Chest X-ray) → Анализ мокроты.',
     'Action: Isolation → Chest X-ray (fluorography) → Sputum test.'),
    ('Фраза: "Кашель с кровью и вечерняя температура – признаки ТБ. Нужна изоляция."',
     'Key Phrase: "Bloody cough and evening fever are signs of TB. Isolation is required."'),
])

# ── PART 3: UNIVERSAL PHRASES ─────────────────────────────────────────────────
story.append(part_header('ЧАСТЬ 3: УНИВЕРСАЛЬНЫЕ ФРАЗЫ ДЛЯ СИМУЛЯЦИИ',
                          'PART 3: UNIVERSAL SIMULATION PHRASES', bg='#2d6a2d'))
story.append(Spacer(1, 0.25*cm))

phrases = [
    ('1. Отказ от самолечения',
     'Refusing self-treatment',
     'Не занимайтесь самолечением! Это может привести к смерти или серьёзным осложнениям.',
     'Do not self-medicate! This can lead to death or serious complications.'),
    ('2. Вызов помощи',
     'Calling for help',
     'Ситуация критическая. Я вызываю скорую помощь (103/112).',
     'The situation is critical. I am calling an ambulance (103/112).'),
    ('3. Направление к специалисту',
     'Referring to a specialist',
     'Только квалифицированный врач (онколог, гастроэнтеролог) может поставить диагноз.',
     'Only a qualified doctor (oncologist, gastroenterologist) can diagnose and prescribe treatment.'),
    ('4. Профилактика',
     'Prevention',
     'Здоровый образ жизни, гигиена и регулярные осмотры – единственная защита от болезней.',
     'Healthy lifestyle, hygiene, and regular check-ups are the only protection against these diseases.'),
    ('5. Изоляция (для инфекций)',
     'Isolation (for infectious diseases)',
     'Введён карантин. Контакт с другими людьми запрещён ради их безопасности.',
     'Quarantine has been declared. Contact with others is prohibited for their safety.'),
]

for (label_ru, label_en, phrase_ru, phrase_en) in phrases:
    p_data = [[
        Paragraph(f'<b>{label_ru}</b>\n<i><font size="8" color="#555555">{label_en}</font></i>',
                  S('plabel', fontSize=9.5, fontName='DejaVu-Bold', leading=13)),
        Paragraph(f'{phrase_ru}\n<i><font size="8.5" color="#2d6a2d">{phrase_en}</font></i>',
                  S('ptext', fontSize=9.5, leading=13, fontName='DejaVu'))
    ]]
    pt = Table(p_data, colWidths=[W*0.28, W*0.72])
    pt.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), colors.HexColor('#f0f8f0')),
        ('ROWBACKGROUNDS', (0,0), (-1,-1), [colors.HexColor('#f0f8f0')]),
        ('BOX', (0,0), (-1,-1), 0.5, colors.HexColor('#2d6a2d')),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
        ('TOPPADDING', (0,0), (-1,-1), 6),
        ('BOTTOMPADDING', (0,0), (-1,-1), 6),
        ('LEFTPADDING', (0,0), (0,-1), 7),
        ('LEFTPADDING', (1,0), (1,-1), 7),
    ]))
    story.append(pt)
    story.append(Spacer(1, 0.15*cm))

story.append(Spacer(1, 0.4*cm))

# ── DISCLAIMER ────────────────────────────────────────────────────────────────
story.append(HRFlowable(width=W, thickness=1, color=colors.HexColor('#888888')))
story.append(Spacer(1, 0.2*cm))
disclaimer_text = (
    '<b>DISCLAIMER / ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ</b><br/>'
    'Данный документ предназначен исключительно для образовательных целей и симуляции. '
    'Информация не является медицинской консультацией.<br/>'
    '<i>This document is intended exclusively for educational and simulation purposes. '
    'The information does not constitute medical advice. Diagnosis, treatment, and prescribing medications '
    'without a medical license are illegal and may cause serious harm or death. '
    'In real life, always consult certified medical professionals.</i>'
)
story.append(Paragraph(disclaimer_text, disc_style))

# ── Build PDF ─────────────────────────────────────────────────────────────────
doc.build(story)
print(f'PDF created: {OUTPUT}')
Running Command

python3 /home/daytona/workspace/med-sim-handbook/generate_pdf.py 2>&1

Editing File

~/med-sim-handbook/generate_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/med-sim-handbook/generate_pdf.py'
Running Command

python3 /home/daytona/workspace/med-sim-handbook/generate_pdf.py 2>&1

Running Command

ls /usr/share/fonts/truetype/dejavu/

Editing File

~/med-sim-handbook/generate_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/med-sim-handbook/generate_pdf.py'
Running Command

python3 /home/daytona/workspace/med-sim-handbook/generate_pdf.py 2>&1

Editing File

~/med-sim-handbook/generate_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/med-sim-handbook/generate_pdf.py'
Running Command

python3 /home/daytona/workspace/med-sim-handbook/generate_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/med-sim-handbook/Medical_Simulation_Handbook_RU_EN.pdf

Your PDF is ready - 90KB, fully formatted and bilingual. Here's your download link:

Medical Simulation Handbook RU EN

PDF Document · PDF


Here's what's included in the PDF:
Structure:
  • Part 1 - Emergency Triage Table (red-header table): 3 emergency scenarios (Heart Attack, Stroke, TB/Ulcer) with symptoms, diagnosis, and action phrases in both Russian and English
  • Part 2 - Topics 1-10 (10 blue-header topic blocks): Each topic has Russian bullet points with English translations directly beneath in green italic text
  • Part 3 - Universal Simulation Phrases (5 green-header cards): Each card shows the Russian phrase + English translation side-by-side
  • Disclaimer at the bottom in both languages
Design features:
  • Full Cyrillic (Russian) + Latin (English) support using DejaVu fonts
  • Color-coded sections: dark red for triage, navy blue for topics, forest green for phrases
  • English translations appear in green italic under every Russian line - no switching between pages needed
  • Professional A4 layout suitable for printing or on-screen reference

Create a study guide quiz PDF to test knowledge of Topics 1-10

Asking for Preferences
Writing File

~/med-sim-handbook/generate_quiz.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY

# ── Fonts ─────────────────────────────────────────────────────────────────────
pdfmetrics.registerFont(TTFont('DV',     '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf'))
pdfmetrics.registerFont(TTFont('DV-B',   '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf'))
pdfmetrics.registerFont(TTFont('DV-Ser', '/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf'))
pdfmetrics.registerFont(TTFont('DV-SerB','/usr/share/fonts/truetype/dejavu/DejaVuSerif-Bold.ttf'))

OUTPUT = '/home/daytona/workspace/med-sim-handbook/Medical_Simulation_Quiz_RU_EN.pdf'

doc = SimpleDocTemplate(
    OUTPUT, pagesize=A4,
    rightMargin=2*cm, leftMargin=2*cm,
    topMargin=2*cm, bottomMargin=2*cm,
    title='Medical Simulation Quiz – Topics 1-10',
    author='Simulation Training Material'
)

W = A4[0] - 4*cm

styles = getSampleStyleSheet()

def S(name, parent='Normal', **kw):
    kw.setdefault('fontName', 'DV')
    return ParagraphStyle(name, parent=styles[parent], **kw)

# Style definitions
doc_title   = S('DocTitle', fontSize=20, leading=26, alignment=TA_CENTER,
                fontName='DV-B', textColor=colors.HexColor('#1a3a5c'), spaceAfter=4)
doc_sub     = S('DocSub',   fontSize=11, leading=15, alignment=TA_CENTER,
                fontName='DV-Ser', textColor=colors.HexColor('#555555'), spaceAfter=4)
doc_meta    = S('DocMeta',  fontSize=9,  leading=13, alignment=TA_CENTER,
                textColor=colors.HexColor('#888888'), spaceAfter=14)
instr_ru    = S('InstrRU',  fontSize=9.5, leading=13,
                textColor=colors.HexColor('#1a3a5c'), fontName='DV-B', spaceAfter=2)
instr_en    = S('InstrEN',  fontSize=9,   leading=13,
                textColor=colors.HexColor('#2d6a2d'), fontName='DV-Ser', spaceAfter=8)
topic_hdr   = S('TopHdr',   fontSize=11,  leading=15, fontName='DV-B',
                textColor=colors.white, spaceAfter=6, spaceBefore=10)
q_num       = S('QNum',     fontSize=9.5, leading=13, fontName='DV-B',
                textColor=colors.HexColor('#1a3a5c'), spaceAfter=1)
q_ru        = S('QRU',      fontSize=9.5, leading=13, leftIndent=0.3*cm, spaceAfter=1)
q_en        = S('QEN',      fontSize=9,   leading=12, leftIndent=0.3*cm,
                textColor=colors.HexColor('#2d6a2d'), fontName='DV-Ser', spaceAfter=4)
opt_style   = S('Opt',      fontSize=9,   leading=13, leftIndent=0.7*cm, spaceAfter=1)
tf_style    = S('TF',       fontSize=9,   leading=13, leftIndent=0.7*cm, spaceAfter=6)
ans_hdr     = S('AnsHdr',   fontSize=13,  leading=17, fontName='DV-B',
                textColor=colors.white, spaceAfter=6)
ans_cell    = S('AnsCell',  fontSize=9,   leading=13, fontName='DV-Ser')

# ── Quiz data: 4 questions per topic (3 MC + 1 T/F) ──────────────────────────
# Format: (type, ru_question, en_question, options_ru, options_en, correct_index_or_TF)
# type: 'mc' or 'tf'
# For tf: options_ru/en ignored; correct is 'T' or 'F'
# For mc: correct is index 0-3 (A=0,B=1,C=2,D=3)

TOPICS = [

  # ── Topic 1: Diabetes ─────────────────────────────────────────────────────
  { 'num': 1,
    'ru': 'Сахарный Диабет', 'en': 'Diabetes Mellitus',
    'color': '#1a3a5c',
    'qs': [
      ('mc',
       'Какой тип диабета характеризуется АБСОЛЮТНЫМ дефицитом инсулина?',
       'Which type of diabetes is characterized by an ABSOLUTE insulin deficiency?',
       ['Тип 1', 'Тип 2', 'Оба типа', 'Ни один из типов'],
       ['Type 1', 'Type 2', 'Both types', 'Neither type'],
       0),
      ('mc',
       'Какое осложнение диабета связано с повреждением глаз?',
       'Which diabetic complication involves eye damage?',
       ['Нефропатия (почки)', 'Ретинопатия (слепота)', 'Нейропатия (нервы)', 'Ангиопатия (сосуды)'],
       ['Nephropathy (kidneys)', 'Retinopathy (blindness)', 'Neuropathy (nerves)', 'Angiopathy (vessels)'],
       1),
      ('mc',
       'Каковы основные симптомы Сахарного Диабета 1 типа?',
       'What are the main symptoms of Type 1 Diabetes Mellitus?',
       ['Боль в суставах и лихорадка', 'Резкое похудение и сильная жажда',
        'Кашель и одышка', 'Боль в животе и рвота'],
       ['Joint pain and fever', 'Rapid weight loss and intense thirst',
        'Cough and shortness of breath', 'Abdominal pain and vomiting'],
       1),
      ('tf',
       'Сахарный Диабет 2 типа чаще встречается у молодых людей без избыточного веса.',
       'Type 2 Diabetes Mellitus most commonly occurs in young people without excess weight.',
       None, None, 'F'),
    ]
  },

  # ── Topic 2: Cardiovascular ───────────────────────────────────────────────
  { 'num': 2,
    'ru': 'Сердечно-сосудистые заболевания', 'en': 'Cardiovascular Diseases',
    'color': '#8b0000',
    'qs': [
      ('mc',
       'Боль в груди, отдающая в левую руку и челюсть — это типичный признак:',
       'Chest pain radiating to the left arm and jaw is a classic sign of:',
       ['Инсульта', 'Инфаркта миокарда', 'Пневмонии', 'Гастрита'],
       ['Stroke', 'Myocardial Infarction', 'Pneumonia', 'Gastritis'],
       1),
      ('mc',
       'Перекос лица, слабость в руке, нарушение речи — это признаки:',
       'Face drooping, arm weakness, and slurred speech are signs of:',
       ['Инфаркта миокарда', 'Гипогликемии', 'Инсульта', 'Туберкулёза'],
       ['Myocardial Infarction', 'Hypoglycaemia', 'Stroke', 'Tuberculosis'],
       2),
      ('mc',
       'Что НЕЛЬЗЯ давать пациенту с подозрением на инфаркт или инсульт?',
       'What should you NOT give to a patient suspected of having a heart attack or stroke?',
       ['Свежий воздух', 'Еду или воду', 'Положение покоя', 'Вызов скорой'],
       ['Fresh air', 'Food or water', 'Rest position', 'Calling an ambulance'],
       1),
      ('tf',
       'Курение и ожирение являются факторами риска инфаркта миокарда.',
       'Smoking and obesity are risk factors for myocardial infarction.',
       None, None, 'T'),
    ]
  },

  # ── Topic 3: Oncology ─────────────────────────────────────────────────────
  { 'num': 3,
    'ru': 'Онкология (Рак)', 'en': 'Oncology (Cancer)',
    'color': '#4a0e6e',
    'qs': [
      ('mc',
       'Какой из перечисленных симптомов является «красным флагом» онкологии?',
       'Which of the following symptoms is a cancer "red flag"?',
       ['Насморк', 'Резкое необъяснимое похудение', 'Лёгкий кашель после еды', 'Усталость после тренировки'],
       ['Runny nose', 'Sudden unexplained weight loss', 'Mild cough after eating', 'Fatigue after exercise'],
       1),
      ('mc',
       'Чем отличается злокачественная опухоль от доброкачественной?',
       'What distinguishes a malignant tumor from a benign one?',
       ['Злокачественная не болит', 'Злокачественная даёт метастазы',
        'Доброкачественная быстрее растёт', 'Они ничем не отличаются'],
       ['Malignant tumors are painless', 'Malignant tumors produce metastases',
        'Benign tumors grow faster', 'They are identical'],
       1),
      ('mc',
       'К какому специалисту нужно направить пациента при подозрении на рак?',
       'To which specialist should a patient be referred when cancer is suspected?',
       ['Кардиолог', 'Гастроэнтеролог', 'Онколог', 'Невролог'],
       ['Cardiologist', 'Gastroenterologist', 'Oncologist', 'Neurologist'],
       2),
      ('tf',
       'Рак на ранних стадиях всегда сопровождается выраженными симптомами.',
       'Cancer in its early stages always presents with obvious symptoms.',
       None, None, 'F'),
    ]
  },

  # ── Topic 4: Healthy Lifestyle ────────────────────────────────────────────
  { 'num': 4,
    'ru': 'Здоровый Образ Жизни (ЗОЖ)', 'en': 'Healthy Lifestyle (HLS)',
    'color': '#2d6a2d',
    'qs': [
      ('mc',
       'Какой процент здоровья человека, по данным исследований, зависит от образа жизни?',
       'What percentage of a person\'s health is influenced by lifestyle choices?',
       ['10%', '25%', '50%', '90%'],
       ['10%', '25%', '50%', '90%'],
       2),
      ('mc',
       'Сколько часов сна в сутки рекомендуется для взрослого человека?',
       'How many hours of sleep per night are recommended for an adult?',
       ['4–5 часов / 4–5 hours', '6 часов / 6 hours', '7–8 часов / 7–8 hours', '10+ часов / 10+ hours'],
       ['4–5 hours', '6 hours', '7–8 hours', '10+ hours'],
       2),
      ('mc',
       'Что из перечисленного НЕ является компонентом здорового образа жизни?',
       'Which of the following is NOT a component of a healthy lifestyle?',
       ['Сбалансированное питание', 'Физическая активность',
        'Употребление алкоголя умеренно каждый день', 'Отказ от курения'],
       ['Balanced nutrition', 'Physical activity',
        'Drinking alcohol moderately every day', 'Quitting smoking'],
       2),
      ('tf',
       'Здоровый образ жизни помогает предотвратить диабет, рак и инфаркт.',
       'A healthy lifestyle helps prevent diabetes, cancer, and heart disease.',
       None, None, 'T'),
    ]
  },

  # ── Topic 5: Infectious Diseases ─────────────────────────────────────────
  { 'num': 5,
    'ru': 'Инфекционные заболевания', 'en': 'Infectious Diseases',
    'color': '#7b3f00',
    'qs': [
      ('mc',
       'ВИЧ передаётся каким путём?',
       'HIV is transmitted via which route?',
       ['Воздушно-капельным / Airborne', 'Через кровь / Blood-borne',
        'Фекально-оральным / Fecal-oral', 'Контактно-бытовым / Household contact'],
       ['Airborne', 'Blood-borne', 'Fecal-oral', 'Household contact'],
       1),
      ('mc',
       'Что такое инкубационный период инфекции?',
       'What is the incubation period of an infection?',
       ['Время лечения болезни',
        'Период от заражения до появления первых симптомов',
        'Время полного выздоровления',
        'Период заразности пациента'],
       ['The duration of treatment',
        'The period from infection to first symptoms',
        'The time to full recovery',
        'The period of patient contagiousness'],
       1),
      ('mc',
       'Какой первый шаг при выявлении опасного инфекционного заболевания?',
       'What is the first step when a dangerous infectious disease is identified?',
       ['Назначить антибиотики', 'Изолировать пациента (карантин)',
        'Сделать рентген грудной клетки', 'Измерить давление'],
       ['Prescribe antibiotics', 'Isolate the patient (quarantine)',
        'Order a chest X-ray', 'Measure blood pressure'],
       1),
      ('tf',
       'Вакцинация является эффективным методом профилактики инфекционных заболеваний.',
       'Vaccination is an effective method of preventing infectious diseases.',
       None, None, 'T'),
    ]
  },

  # ── Topic 6: Inpatient Treatment ─────────────────────────────────────────
  { 'num': 6,
    'ru': 'Стационарное лечение', 'en': 'Inpatient Treatment (Hospital)',
    'color': '#1a3a5c',
    'qs': [
      ('mc',
       'Какое ГЛАВНОЕ преимущество стационарного лечения?',
       'What is the MAIN advantage of inpatient (hospital) treatment?',
       ['Дешевле домашнего лечения', 'Круглосуточное наблюдение врачей',
        'Нет риска инфекций', 'Пациент рядом с семьёй'],
       ['Cheaper than home treatment', '24/7 medical monitoring',
        'No infection risk', 'Patient stays close to family'],
       1),
      ('mc',
       'Что является НЕДОСТАТКОМ стационарного лечения?',
       'Which of the following is a DISADVANTAGE of hospital treatment?',
       ['Доступность процедур на месте', 'Риск внутрибольничных инфекций',
        'Бесплатные лекарства', 'Постоянное наблюдение'],
       ['Availability of on-site procedures', 'Risk of nosocomial (hospital-acquired) infections',
        'Free medications', 'Continuous monitoring'],
       1),
      ('mc',
       'В каком случае стационарное лечение наиболее обосновано?',
       'In which situation is inpatient treatment most justified?',
       ['Лёгкий насморк', 'Плановый осмотр', 'Угроза жизни или сложные процедуры', 'Хроническая болезнь в ремиссии'],
       ['Mild cold', 'Routine check-up', 'Life-threatening condition or complex procedures', 'Chronic disease in remission'],
       2),
      ('tf',
       'Стационарное лечение рекомендуется для всех пациентов с хроническими заболеваниями.',
       'Inpatient treatment is recommended for all patients with chronic diseases.',
       None, None, 'F'),
    ]
  },

  # ── Topic 7: Outpatient Treatment ────────────────────────────────────────
  { 'num': 7,
    'ru': 'Амбулаторное лечение (Дома)', 'en': 'Outpatient Treatment (Home-Based)',
    'color': '#555555',
    'qs': [
      ('mc',
       'Какое ГЛАВНОЕ преимущество амбулаторного лечения?',
       'What is the MAIN advantage of outpatient (home-based) treatment?',
       ['Круглосуточный врач рядом', 'Домашний комфорт и поддержка семьи',
        'Бесплатные лекарства', 'Изоляция от инфекций'],
       ['24/7 doctor available', 'Home comfort and family support',
        'Free medications', 'Isolation from infections'],
       1),
      ('mc',
       'Для каких пациентов наиболее подходит амбулаторное лечение?',
       'For which patients is outpatient treatment most appropriate?',
       ['Пациенты в критическом состоянии', 'Пациенты после инфаркта',
        'Стабильные пациенты с лёгкими заболеваниями', 'Пациенты с открытым переломом'],
       ['Critically ill patients', 'Post-heart attack patients',
        'Stable patients with mild illnesses', 'Patients with open fractures'],
       2),
      ('mc',
       'Когда пациент на домашнем лечении должен немедленно вызвать скорую?',
       'When should a patient receiving home treatment immediately call an ambulance?',
       ['При небольшой усталости', 'При появлении боли или кровотечения',
        'Если закончились таблетки', 'Раз в неделю для проверки'],
       ['When mildly tired', 'When pain or bleeding appears',
        'When pills run out', 'Once a week for routine checks'],
       1),
      ('tf',
       'При амбулаторном лечении нет риска заражения больничными инфекциями.',
       'With outpatient treatment, there is no risk of hospital-acquired infection.',
       None, None, 'T'),
    ]
  },

  # ── Topic 8: Personal Hygiene ─────────────────────────────────────────────
  { 'num': 8,
    'ru': 'Личная гигиена', 'en': 'Personal Hygiene',
    'color': '#006b8f',
    'qs': [
      ('mc',
       'Когда ОБЯЗАТЕЛЬНО нужно мыть руки?',
       'When is it MANDATORY to wash your hands?',
       ['После сна', 'После туалета и перед едой',
        'После просмотра телевизора', 'Только если руки видимо грязные'],
       ['After sleeping', 'After using the toilet and before eating',
        'After watching TV', 'Only if visibly dirty'],
       1),
      ('mc',
       'Какой предмет личной гигиены НЕЛЬЗЯ использовать совместно с другими?',
       'Which personal hygiene item should NEVER be shared with others?',
       ['Мыло', 'Полотенце', 'Шампунь', 'Зеркало'],
       ['Soap', 'Towel', 'Shampoo', 'Mirror'],
       1),
      ('mc',
       'Какая оптимальная температура воды для ежедневного душа?',
       'What is the optimal water temperature for a daily shower?',
       ['20–25°C', '30–32°C', '37–38°C', '42–45°C'],
       ['20–25°C', '30–32°C', '37–38°C', '42–45°C'],
       2),
      ('tf',
       'Постельное бельё рекомендуется менять раз в месяц.',
       'Bed linen is recommended to be changed once a month.',
       None, None, 'F'),
    ]
  },

  # ── Topic 9: Gastritis & Ulcer ────────────────────────────────────────────
  { 'num': 9,
    'ru': 'Гастрит и Язва', 'en': 'Gastritis and Peptic Ulcer',
    'color': '#8b4500',
    'qs': [
      ('mc',
       'Какой препарат из перечисленных может ВЫЗВАТЬ гастрит или язву?',
       'Which of the following drugs can CAUSE gastritis or an ulcer?',
       ['Парацетамол', 'НПВС (ибупрофен, аспирин)', 'Антигистамины', 'Витамин C'],
       ['Paracetamol', 'NSAIDs (ibuprofen, aspirin)', 'Antihistamines', 'Vitamin C'],
       1),
      ('mc',
       'Самое опасное осложнение язвенной болезни:',
       'The most dangerous complication of peptic ulcer disease is:',
       ['Тошнота', 'Изжога', 'Прободение (перфорация) язвы', 'Потеря аппетита'],
       ['Nausea', 'Heartburn', 'Ulcer perforation (peritonitis)', 'Loss of appetite'],
       2),
      ('mc',
       'Какой метод диагностики применяется для подтверждения язвы желудка?',
       'Which diagnostic method is used to confirm a stomach ulcer?',
       ['УЗИ органов малого таза', 'Эндоскопия (ЭГДС)', 'Флюорография', 'Анализ мочи'],
       ['Pelvic ultrasound', 'Endoscopy (EGDS)', 'Chest X-ray (fluorography)', 'Urine test'],
       1),
      ('tf',
       'При боли в желудке можно безопасно лечиться самостоятельно без врача.',
       'Stomach pain can be safely self-treated without seeing a doctor.',
       None, None, 'F'),
    ]
  },

  # ── Topic 10: Tuberculosis ────────────────────────────────────────────────
  { 'num': 10,
    'ru': 'Туберкулёз (ТБ)', 'en': 'Tuberculosis (TB)',
    'color': '#3a3a00',
    'qs': [
      ('mc',
       'Какой микроорганизм является возбудителем туберкулёза?',
       'Which microorganism causes tuberculosis?',
       ['Вирус гриппа', 'Палочка Коха (Mycobacterium tuberculosis)',
        'Стрептококк', 'Кандида'],
       ['Influenza virus', 'Koch\'s bacillus (Mycobacterium tuberculosis)',
        'Streptococcus', 'Candida'],
       1),
      ('mc',
       'Какая форма туберкулёза является заразной?',
       'Which form of tuberculosis is contagious?',
       ['Латентная / Latent', 'Активная / Active', 'Обе формы / Both', 'Ни одна / Neither'],
       ['Latent', 'Active', 'Both', 'Neither'],
       1),
      ('mc',
       'Какой из симптомов является характерным для активного туберкулёза?',
       'Which symptom is characteristic of active tuberculosis?',
       ['Сыпь на коже', 'Боль в суставах', 'Кашель с кровью и ночная потливость', 'Отёки ног'],
       ['Skin rash', 'Joint pain', 'Bloody cough and night sweats', 'Leg oedema'],
       2),
      ('tf',
       'Латентная форма туберкулёза заразна и требует немедленной изоляции.',
       'Latent tuberculosis is contagious and requires immediate isolation.',
       None, None, 'F'),
    ]
  },

]

# ── Answer key data (collected while building) ────────────────────────────────
answer_key = []

# ── Helper: topic header bar ──────────────────────────────────────────────────
def topic_header(num, ru_title, en_title, color):
    data = [[
        Paragraph(f'<b>Тема {num}: {ru_title}</b>',
                  S('th_ru', fontSize=10.5, fontName='DV-B', textColor=colors.white, leading=14)),
        Paragraph(f'<i>Topic {num}: {en_title}</i>',
                  S('th_en', fontSize=9, fontName='DV-Ser', textColor=colors.HexColor('#ddeecc'), leading=13)),
    ]]
    t = Table(data, colWidths=[W*0.52, W*0.48])
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), colors.HexColor(color)),
        ('TOPPADDING', (0,0), (-1,-1), 7),
        ('BOTTOMPADDING', (0,0), (-1,-1), 7),
        ('LEFTPADDING', (0,0), (0,-1), 8),
        ('RIGHTPADDING', (-1,0), (-1,-1), 8),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ]))
    return t

LETTERS = ['A', 'B', 'C', 'D']

# ── Build story ───────────────────────────────────────────────────────────────
story = []
q_global = 0

# ── Title ──────────────────────────────────────────────────────────────────────
story.append(Spacer(1, 0.8*cm))
story.append(Paragraph('Тест по Медицинской Симуляции', doc_title))
story.append(Paragraph('Medical Simulation Quiz', doc_title))
story.append(Paragraph('Темы 1–10  |  Topics 1–10', doc_sub))
story.append(HRFlowable(width=W, thickness=2, color=colors.HexColor('#1a3a5c')))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
    'Дата: 15 июня 2026 г.  |  Date: June 15, 2026  |  '
    'Учебный материал — НЕ для клинического использования  |  '
    'Educational material — NOT for clinical use',
    doc_meta))

# Instructions
instr_box_data = [[
    Paragraph(
        '<b>Инструкции:</b> Для каждого вопроса выберите правильный ответ. '
        'В вопросах Верно/Неверно обведите «В» (Верно) или «Н» (Неверно). '
        'Ответы — в конце документа.',
        S('IB_ru', fontSize=9.5, leading=13, fontName='DV-B', textColor=colors.HexColor('#1a3a5c'))),
    Paragraph(
        '<i><b>Instructions:</b> For each question, select the correct answer. '
        'For True/False questions, circle "T" (True) or "F" (False). '
        'Answer key is at the end of the document.</i>',
        S('IB_en', fontSize=9, leading=12, fontName='DV-Ser', textColor=colors.HexColor('#2d6a2d'))),
]]
instr_box = Table(instr_box_data, colWidths=[W*0.5, W*0.5])
instr_box.setStyle(TableStyle([
    ('BACKGROUND', (0,0), (-1,-1), colors.HexColor('#f0f4fa')),
    ('BOX', (0,0), (-1,-1), 1, colors.HexColor('#1a3a5c')),
    ('TOPPADDING', (0,0), (-1,-1), 7),
    ('BOTTOMPADDING', (0,0), (-1,-1), 7),
    ('LEFTPADDING', (0,0), (-1,-1), 8),
    ('RIGHTPADDING', (0,0), (-1,-1), 8),
    ('VALIGN', (0,0), (-1,-1), 'TOP'),
]))
story.append(instr_box)
story.append(Spacer(1, 0.3*cm))

# Score box
score_data = [[
    Paragraph('Имя / Name: ___________________________',
              S('sb', fontSize=9.5, leading=13)),
    Paragraph('Результат / Score: ______ / 40',
              S('sb2', fontSize=9.5, leading=13, fontName='DV-B')),
]]
score_t = Table(score_data, colWidths=[W*0.55, W*0.45])
score_t.setStyle(TableStyle([
    ('BOX', (0,0), (-1,-1), 0.5, colors.HexColor('#888888')),
    ('TOPPADDING', (0,0), (-1,-1), 6),
    ('BOTTOMPADDING', (0,0), (-1,-1), 6),
    ('LEFTPADDING', (0,0), (-1,-1), 8),
]))
story.append(score_t)
story.append(Spacer(1, 0.4*cm))

# ── Questions ─────────────────────────────────────────────────────────────────
for topic in TOPICS:
    block = []
    block.append(topic_header(topic['num'], topic['ru'], topic['en'], topic['color']))
    block.append(Spacer(1, 0.2*cm))

    q_in_topic = 0
    for (qtype, q_ru_text, q_en_text, opts_ru, opts_en, correct) in topic['qs']:
        q_global += 1
        q_in_topic += 1

        # Record answer
        if qtype == 'mc':
            label = LETTERS[correct]
            answer_key.append((q_global, topic['num'], qtype, label,
                                opts_ru[correct], opts_en[correct]))
        else:
            answer_key.append((q_global, topic['num'], qtype, correct, None, None))

        # Question number + type badge
        badge_color = '#1a3a5c' if qtype == 'mc' else '#7b3f00'
        badge_ru = 'Выбор ответа' if qtype == 'mc' else 'Верно / Неверно'
        badge_en = 'Multiple Choice' if qtype == 'mc' else 'True / False'

        q_data = [[
            Paragraph(f'<b>Вопрос {q_global}</b>  <i>Question {q_global}</i>',
                      S('qn', fontSize=9.5, fontName='DV-B', textColor=colors.HexColor(badge_color), leading=13)),
            Paragraph(f'<b>{badge_ru}</b> | <i>{badge_en}</i>',
                      S('qt', fontSize=8, fontName='DV-B', textColor=colors.white, leading=12,
                        alignment=TA_CENTER)),
        ]]
        qt = Table(q_data, colWidths=[W*0.62, W*0.38])
        qt.setStyle(TableStyle([
            ('BACKGROUND', (1,0), (1,0), colors.HexColor(badge_color)),
            ('TOPPADDING', (0,0), (-1,-1), 4),
            ('BOTTOMPADDING', (0,0), (-1,-1), 4),
            ('LEFTPADDING', (0,0), (0,0), 0),
            ('LEFTPADDING', (1,0), (1,0), 5),
            ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ]))
        block.append(qt)

        # Question text
        block.append(Paragraph(q_ru_text, q_ru))
        block.append(Paragraph(q_en_text, q_en))

        if qtype == 'mc':
            for i, (o_ru, o_en) in enumerate(zip(opts_ru, opts_en)):
                letter = LETTERS[i]
                block.append(Paragraph(
                    f'<b>{letter})</b> {o_ru}  <font color="#2d6a2d"><i>/ {o_en}</i></font>',
                    S(f'opt_{q_global}_{i}', fontSize=9, leading=13,
                      leftIndent=0.8*cm, spaceAfter=2)))
        else:
            block.append(Paragraph(
                '<b>В (True)</b>  ○     <b>Н (False)</b>  ○',
                S(f'tf_{q_global}', fontSize=10, leading=14,
                  leftIndent=1*cm, spaceAfter=6, fontName='DV-B')))

        block.append(Spacer(1, 0.25*cm))

    story.append(KeepTogether(block[:6]))  # keep header + first Q together
    for item in block[6:]:
        story.append(item)
    story.append(Spacer(1, 0.1*cm))

# ── Answer Key ────────────────────────────────────────────────────────────────
story.append(PageBreak())
story.append(Spacer(1, 0.3*cm))

ak_hdr_data = [[
    Paragraph('<b>КЛЮЧ К ОТВЕТАМ</b>', S('akh_ru', fontSize=14, fontName='DV-B',
              textColor=colors.white, leading=18)),
    Paragraph('<i>ANSWER KEY</i>', S('akh_en', fontSize=12, fontName='DV-Ser',
              textColor=colors.HexColor('#ddeecc'), leading=16)),
]]
ak_hdr = Table(ak_hdr_data, colWidths=[W*0.45, W*0.55])
ak_hdr.setStyle(TableStyle([
    ('BACKGROUND', (0,0), (-1,-1), colors.HexColor('#1a3a5c')),
    ('TOPPADDING', (0,0), (-1,-1), 10),
    ('BOTTOMPADDING', (0,0), (-1,-1), 10),
    ('LEFTPADDING', (0,0), (-1,-1), 10),
]))
story.append(ak_hdr)
story.append(Spacer(1, 0.4*cm))

# Table header
ak_col_hdrs = [
    Paragraph('<b>№</b>', S('akh', fontSize=9, fontName='DV-B', textColor=colors.white, alignment=TA_CENTER)),
    Paragraph('<b>Тема / Topic</b>', S('akh', fontSize=9, fontName='DV-B', textColor=colors.white)),
    Paragraph('<b>Тип / Type</b>', S('akh', fontSize=9, fontName='DV-B', textColor=colors.white)),
    Paragraph('<b>Ответ / Answer</b>', S('akh', fontSize=9, fontName='DV-B', textColor=colors.white)),
    Paragraph('<b>Правильный ответ (RU / EN)</b>', S('akh', fontSize=9, fontName='DV-B', textColor=colors.white)),
]

ak_rows = [ak_col_hdrs]

alt_colors = [colors.HexColor('#f0f4fa'), colors.HexColor('#ffffff')]
for idx, (qn, tn, qt, ans, ans_ru, ans_en) in enumerate(answer_key):
    type_str_ru = 'Выбор' if qt == 'mc' else 'В/Н'
    type_str_en = 'MC' if qt == 'mc' else 'T/F'
    if qt == 'mc':
        ans_text = f'<b>{ans}</b>'
        detail = f'{ans_ru} / {ans_en}' if ans_ru else ''
    else:
        full_ans = 'В (True)' if ans == 'T' else 'Н (False)'
        ans_text = f'<b>{full_ans}</b>'
        detail = ''

    row = [
        Paragraph(str(qn), S(f'ak_qn_{qn}', fontSize=9, alignment=TA_CENTER)),
        Paragraph(str(tn), S(f'ak_tn_{qn}', fontSize=9, alignment=TA_CENTER)),
        Paragraph(f'{type_str_ru} / {type_str_en}', S(f'ak_tp_{qn}', fontSize=8.5)),
        Paragraph(ans_text, S(f'ak_ans_{qn}', fontSize=9.5, fontName='DV-B',
                               textColor=colors.HexColor('#8b0000'))),
        Paragraph(detail, S(f'ak_det_{qn}', fontSize=8.5, fontName='DV-Ser',
                              textColor=colors.HexColor('#2d6a2d'))),
    ]
    ak_rows.append(row)

ak_table = Table(ak_rows, colWidths=[W*0.07, W*0.08, W*0.15, W*0.17, W*0.53])
ak_table_style = [
    ('BACKGROUND', (0,0), (-1,0), colors.HexColor('#1a3a5c')),
    ('GRID', (0,0), (-1,-1), 0.4, colors.HexColor('#cccccc')),
    ('TOPPADDING', (0,0), (-1,-1), 4),
    ('BOTTOMPADDING', (0,0), (-1,-1), 4),
    ('LEFTPADDING', (0,0), (-1,-1), 5),
    ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
]
for i in range(1, len(ak_rows)):
    bg = alt_colors[(i-1) % 2]
    ak_table_style.append(('BACKGROUND', (0,i), (-1,i), bg))

ak_table.setStyle(TableStyle(ak_table_style))
story.append(ak_table)

story.append(Spacer(1, 0.5*cm))
story.append(HRFlowable(width=W, thickness=1, color=colors.HexColor('#888888')))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
    '<b>DISCLAIMER:</b> Данный тест предназначен исключительно для учебных целей и медицинской симуляции. '
    'Не является медицинской консультацией. | '
    '<i>This quiz is for educational and simulation purposes only. Not medical advice.</i>',
    S('disc', fontSize=8, leading=12, textColor=colors.HexColor('#666666'),
      fontName='DV-Ser', alignment=TA_JUSTIFY)
))

# ── Build ─────────────────────────────────────────────────────────────────────
doc.build(story)
print(f'PDF created: {OUTPUT}')
print(f'Total questions: {q_global}')
Running Command

python3 /home/daytona/workspace/med-sim-handbook/generate_quiz.py 2>&1

Running Command

ls -lh /home/daytona/workspace/med-sim-handbook/Medical_Simulation_Quiz_RU_EN.pdf

Your quiz PDF is ready - 105KB, 40 questions total. Download it here:

Medical Simulation Quiz RU EN

PDF Document · PDF


What's inside:
40 questions - 4 per topic (Topics 1-10):
  • 3 Multiple Choice questions per topic (4 options each, A-B-C-D)
  • 1 True/False question per topic (В/Н in Russian, T/F in English)
Bilingual format throughout:
  • Every question appears in Russian first, then English directly below in green italic
  • Every answer option shows Russian / English side-by-side
  • Type badge on each question shows "Выбор ответа / Multiple Choice" or "Верно/Неверно / True/False"
Answer Key (last page):
  • Full 40-row table: Question #, Topic #, Type, Answer letter, and the full correct answer text in both Russian and English
  • Alternating row shading for easy reading
Score box at the top: Name field + Score out of 40
Topics covered: Diabetes, Cardiovascular Diseases, Oncology, Healthy Lifestyle, Infectious Diseases, Inpatient Treatment, Outpatient Treatment, Personal Hygiene, Gastritis/Ulcer, Tuberculosis
This is a shared conversation. Sign in to Orris to start your own chat.