~/bhms-schedule/generate_schedule.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.pdfgen import canvas
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate
OUTPUT = "/tmp/workspace/bhms-schedule/BHMS_4th_Year_20Day_Schedule.pdf"
# โโ Colour Palette โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
C_HEADER = colors.HexColor("#1A1A2E") # deep navy
C_POM = colors.HexColor("#C0392B") # red
C_MM = colors.HexColor("#8E44AD") # purple
C_ORG = colors.HexColor("#1A5276") # dark blue
C_REP = colors.HexColor("#117A65") # teal
C_PSM = colors.HexColor("#B7950B") # gold
C_REV = colors.HexColor("#2E4053") # charcoal
C_LIGHT = colors.HexColor("#F8F9FA") # near-white
C_ALT = colors.HexColor("#EAF2FF") # light blue tint
C_NIGHT = colors.HexColor("#FFF3E0") # warm cream for night session
C_STRIPE = colors.HexColor("#F0F0F0")
C_WHITE = colors.white
C_BLACK = colors.HexColor("#1C1C1C")
SUBJECT_COLORS = {
"POM": C_POM, "MM": C_MM, "ORG": C_ORG,
"REP": C_REP, "PSM": C_PSM, "REV": C_REV,
}
def subject_color(tag):
return SUBJECT_COLORS.get(tag, C_HEADER)
# โโ Page Setup โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
PAGE_W, PAGE_H = A4 # 595 x 842 pts
MARGIN = 1.5 * cm
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=MARGIN, rightMargin=MARGIN,
topMargin=1.8*cm, bottomMargin=1.5*cm,
title="BHMS 4th Year โ 20-Day Study Schedule",
author="Orris Study Planner",
)
# โโ Styles โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
styles = getSampleStyleSheet()
def sty(name, **kw):
return ParagraphStyle(name, **kw)
TITLE = sty("Title2", fontName="Helvetica-Bold", fontSize=18, textColor=C_WHITE,
alignment=TA_CENTER, leading=22, spaceAfter=2)
SUBTITLE = sty("Sub", fontName="Helvetica", fontSize=9, textColor=colors.HexColor("#AAAACC"),
alignment=TA_CENTER, leading=12, spaceAfter=4)
PHASE_TITLE = sty("PhaseT", fontName="Helvetica-Bold", fontSize=11, textColor=C_WHITE,
alignment=TA_LEFT, leading=14)
DAY_HEAD = sty("DayH", fontName="Helvetica-Bold", fontSize=8.5, textColor=C_WHITE,
alignment=TA_LEFT, leading=11)
CELL_BOLD = sty("CellB", fontName="Helvetica-Bold", fontSize=7.5, textColor=C_BLACK, leading=10)
CELL_NORM = sty("CellN", fontName="Helvetica", fontSize=7, textColor=C_BLACK, leading=9.5)
TIME_STY = sty("TimeS", fontName="Helvetica-Bold", fontSize=7, textColor=colors.HexColor("#555555"), leading=9)
TIP_STY = sty("TipS", fontName="Helvetica-Oblique", fontSize=7, textColor=C_BLACK, leading=10)
SMALL_HDR = sty("SmHdr", fontName="Helvetica-Bold", fontSize=8, textColor=C_WHITE,
alignment=TA_CENTER, leading=10)
FOOTER_STY= sty("Footer", fontName="Helvetica-Oblique", fontSize=6.5,
textColor=colors.HexColor("#888888"), alignment=TA_CENTER, leading=9)
# โโ Helper: coloured section header โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def phase_header(label, tag, date_range, days):
col = subject_color(tag)
data = [[
Paragraph(f"<b>{label}</b>", PHASE_TITLE),
Paragraph(f"<b>{date_range} | {days}</b>", PHASE_TITLE),
]]
t = Table(data, colWidths=[10*cm, 7.4*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), col),
("TEXTCOLOR", (0,0), (-1,-1), C_WHITE),
("ALIGN", (1,0), (1,0), "RIGHT"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING",(0,0), (-1,-1), 8),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0),(-1,-1), 5),
("ROUNDEDCORNERS", [4]),
]))
return t
def day_header_row(day_num, date_str, tag):
col = subject_color(tag)
lighter = colors.HexColor("%02x%02x%02x" % (
min(255, col.red*255 + 40),
min(255, col.green*255 + 40),
min(255, col.blue*255 + 40),
))
data = [[Paragraph(f"<b>Day {day_num} โ {date_str}</b>", DAY_HEAD)]]
t = Table(data, colWidths=[17.4*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), col),
("LEFTPADDING", (0,0),(-1,-1), 8),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING",(0,0),(-1,-1), 3),
("ROUNDEDCORNERS",[3]),
]))
return t
def session_table(rows, tag):
"""rows: list of (session_label, time, topics_str)"""
col = subject_color(tag)
table_data = [[
Paragraph("<b>Session</b>", SMALL_HDR),
Paragraph("<b>Time</b>", SMALL_HDR),
Paragraph("<b>Topics</b>", SMALL_HDR),
]]
for i, (sess, time_, topics) in enumerate(rows):
bg = C_LIGHT if i % 2 == 0 else C_STRIPE
if "Night" in sess or "Revision" in sess.lower():
bg = C_NIGHT
table_data.append([
Paragraph(f"<b>{sess}</b>", CELL_BOLD),
Paragraph(time_, TIME_STY),
Paragraph(topics, CELL_NORM),
])
t = Table(table_data, colWidths=[2.8*cm, 2.5*cm, 12.1*cm])
style = [
# Header row
("BACKGROUND", (0,0),(-1,0), col),
("TEXTCOLOR", (0,0),(-1,0), C_WHITE),
("ALIGN", (0,0),(-1,0), "CENTER"),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,0), 7.5),
("TOPPADDING", (0,0),(-1,0), 4),
("BOTTOMPADDING",(0,0),(-1,0), 4),
# Data rows
("FONTSIZE", (0,1),(-1,-1), 7),
("TOPPADDING", (0,1),(-1,-1), 3),
("BOTTOMPADDING",(0,1),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 5),
("RIGHTPADDING", (0,0),(-1,-1), 5),
("VALIGN", (0,0),(-1,-1), "TOP"),
("GRID", (0,0),(-1,-1), 0.3, colors.HexColor("#CCCCCC")),
("ROWBACKGROUNDS",(0,1),(-1,-1), [C_LIGHT, C_STRIPE]),
]
# Night session highlight
for i, (sess, _, _) in enumerate(rows, 1):
if "Night" in sess:
style.append(("BACKGROUND", (0,i),(-1,i), C_NIGHT))
t.setStyle(TableStyle(style))
return t
# โโ Build content โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
story = []
# ---- COVER BANNER ----
cover_data = [[Paragraph("BHMS 4th Year Theory Exams", TITLE)],
[Paragraph("20-Day Intensive Study Schedule | July 25 โ August 13, 2026", SUBTITLE)],
[Paragraph("Subjects: Practice of Medicine โข Materia Medica โข Organon โข Repertory โข PSM", SUBTITLE)]]
cover_tbl = Table(cover_data, colWidths=[17.4*cm])
cover_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), C_HEADER),
("LEFTPADDING", (0,0),(-1,-1), 10),
("RIGHTPADDING", (0,0),(-1,-1), 10),
("TOPPADDING", (0,0),(0,0), 12),
("TOPPADDING", (0,1),(-1,-1), 2),
("BOTTOMPADDING",(0,0),(-1,-2), 2),
("BOTTOMPADDING",(0,-1),(-1,-1), 12),
("ROUNDEDCORNERS",[6]),
]))
story.append(cover_tbl)
story.append(Spacer(1, 8))
# ---- OVERVIEW TABLE ----
ov_header = [
Paragraph("<b>Subject</b>", SMALL_HDR),
Paragraph("<b>Days</b>", SMALL_HDR),
Paragraph("<b>Dates</b>", SMALL_HDR),
Paragraph("<b>Focus</b>", SMALL_HDR),
]
ov_rows = [
("Practice of Medicine", "5 days", "July 25โ29", "Systems, Therapeutics, PYQs"),
("Materia Medica", "5 days", "July 30 โ Aug 3", "Polychrests, Nosodes, Drug Relations"),
("Organon of Medicine", "4 days", "Aug 4โ7", "Aphorisms, Philosophy, Posology"),
("Repertory", "3 days", "Aug 8โ10", "Kent, Boger, Rubric Selection"),
("PSM", "3 days", "Aug 11โ13", "Epidemiology, Programs, Biostats"),
("Revision (Weak Focus)", "6 days", "Aug 14โ19", "PYQs, Comparisons, Mock Practice"),
]
ov_colors_list = [C_POM, C_MM, C_ORG, C_REP, C_PSM, C_REV]
ov_data = [ov_header]
for row in ov_rows:
ov_data.append([Paragraph(row[i], CELL_BOLD if i==0 else CELL_NORM) for i in range(4)])
ov_tbl = Table(ov_data, colWidths=[4.5*cm, 2.2*cm, 4.5*cm, 6.2*cm])
ov_style = [
("BACKGROUND", (0,0),(-1,0), C_HEADER),
("TEXTCOLOR", (0,0),(-1,0), C_WHITE),
("ALIGN", (0,0),(-1,0), "CENTER"),
("GRID", (0,0),(-1,-1), 0.3, colors.HexColor("#CCCCCC")),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 5),
("FONTSIZE", (0,0),(-1,-1), 7.5),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]
for i, col_c in enumerate(ov_colors_list, 1):
ov_style.append(("LEFTBORDERPADDING", (0,i),(-1,i), 0))
ov_style.append(("LINEAFTER", (-1,i),(-1,i), 2, col_c))
ov_style.append(("LINEBEFORE", (0,i),(0,i), 3, col_c))
light = colors.Color(col_c.red, col_c.green, col_c.blue, alpha=0.08)
ov_style.append(("BACKGROUND", (0,i),(-1,i), light))
ov_tbl.setStyle(TableStyle(ov_style))
story.append(ov_tbl)
story.append(Spacer(1, 10))
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# PHASE 1 โ PRACTICE OF MEDICINE
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
story.append(phase_header("๐ PHASE 1 โ PRACTICE OF MEDICINE", "POM", "July 25โ29", "5 Days"))
story.append(Spacer(1, 4))
days_pom = [
(1, "July 25 (Sat)", [
("Morning", "6:00โ10:00 AM", "Cardiovascular: Heart failure, Hypertension, IHD, Rheumatic fever"),
("Afternoon","11:00 AMโ3:00 PM","Respiratory: Pneumonia, Bronchitis, COPD, Asthma, Tuberculosis"),
("Evening", "4:00โ7:00 PM", "GIT: Typhoid, Cholera, Dysentery, Peptic ulcer, Hepatitis"),
("Night Rev","9:00โ10:00 PM", "Quick re-read CV + Resp key points; write remedies for each disease"),
]),
(2, "July 26 (Sun)", [
("Morning", "6:00โ10:00 AM", "Nervous system: Meningitis, Encephalitis, Epilepsy, Paralysis, Migraine"),
("Afternoon","11:00 AMโ3:00 PM","Renal: UTI, Nephritis, Nephrotic syndrome, Renal failure"),
("Evening", "4:00โ7:00 PM", "Endocrine: Diabetes mellitus, Thyroid disorders, Addison's, Cushing's"),
("Night Rev","9:00โ10:00 PM", "Nervous + Renal revision โ focus on clinical features"),
]),
(3, "July 27 (Mon)", [
("Morning", "6:00โ10:00 AM", "Fevers: Malaria, Dengue, Typhoid revisit, Viral fevers, Septicemia"),
("Afternoon","11:00 AMโ3:00 PM","Blood: Anaemia types, Leukemia, Thrombocytopenia, Bleeding disorders"),
("Evening", "4:00โ7:00 PM", "Musculoskeletal: Rheumatoid arthritis, Gout, Osteoarthritis, SLE"),
("Night Rev","9:00โ10:00 PM", "Fever management + important investigations for blood disorders"),
]),
(4, "July 28 (Tue)", [
("Morning", "6:00โ10:00 AM", "Skin: Psoriasis, Eczema, Urticaria, Acne, Vitiligo"),
("Afternoon","11:00 AMโ3:00 PM","Paediatrics: Diarrhoea, Kwashiorkor, Marasmus, Worm infestations, Vaccination"),
("Evening", "4:00โ7:00 PM", "Gynaecological: Menstrual disorders, PCOD, PID"),
("Night Rev","9:00โ10:00 PM", "PYQ practice โ write 10-mark answers on PoM topics"),
]),
(5, "July 29 (Wed)", [
("Morning", "6:00โ10:00 AM", "Miasmatic understanding of diseases + Homoeopathic emergencies"),
("Afternoon","11:00 AMโ3:00 PM","PoM PYQs โ last 5 years, focus on case-based questions"),
("Evening", "4:00โ7:00 PM", "Homoeopathic therapeutics: Specific remedies for all major diseases"),
("Night Rev","9:00โ10:00 PM", "Full PoM revision โ make one-page summary per system"),
]),
]
for day_num, date_str, sessions in days_pom:
story.append(day_header_row(day_num, date_str, "POM"))
story.append(session_table(sessions, "POM"))
story.append(Spacer(1, 5))
story.append(Spacer(1, 6))
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# PHASE 2 โ MATERIA MEDICA
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
story.append(phase_header("๐ PHASE 2 โ MATERIA MEDICA", "MM", "July 30 โ Aug 3", "5 Days"))
story.append(Spacer(1, 4))
days_mm = [
(6, "July 30 (Thu)", [
("Morning", "6:00โ10:00 AM", "Polychrests: Sulphur, Calcarea carb, Lycopodium โ full drug pictures"),
("Afternoon","11:00 AMโ3:00 PM","Polychrests: Natrum mur, Pulsatilla, Sepia, Silicea"),
("Evening", "4:00โ7:00 PM", "Polychrests: Nux vomica, Arsenicum album, Phosphorus"),
("Night Rev","9:00โ10:00 PM", "Compare Sulphur vs Calcarea carb vs Lycopodium mentals"),
]),
(7, "July 31 (Fri)", [
("Morning", "6:00โ10:00 AM", "Minerals: Kali carb, Kali bich, Kali phos, Natrum sulph, Natrum ars"),
("Afternoon","11:00 AMโ3:00 PM","Minerals: Magnesia carb, Magnesia mur, Calcarea phos, Calcarea sulph"),
("Evening", "4:00โ7:00 PM", "Acids: Acid phos, Phosphoric acid, Nitric acid, Muriatic acid"),
("Night Rev","9:00โ10:00 PM", "Acid group comparison โ common exam differentials"),
]),
(8, "Aug 1 (Sat)", [
("Morning", "6:00โ10:00 AM", "Plants: Belladonna, Aconite, Chamomilla, Ignatia, Staphysagria"),
("Afternoon","11:00 AMโ3:00 PM","Plants: Rhus tox, Bryonia, Colocynth, Drosera, Ipecac"),
("Evening", "4:00โ7:00 PM", "Plants: Gelsemium, Veratrum alb, Spigelia, Cactus, Digitalis"),
("Night Rev","9:00โ10:00 PM", "Aconite vs Belladonna vs Chamomilla โ classic comparison"),
]),
(9, "Aug 2 (Sun)", [
("Morning", "6:00โ10:00 AM", "Animal remedies: Apis mel, Lachesis, Naja, Crotalus, Tarentula"),
("Afternoon","11:00 AMโ3:00 PM","Nosodes: Psorinum, Medorrhinum, Syphilinum, Tuberculinum, Carcinosin"),
("Evening", "4:00โ7:00 PM", "Bowel nosodes + small remedies: Morgan, Gaertner, Bach"),
("Night Rev","9:00โ10:00 PM", "Nosodes comparison โ miasmatic relations"),
]),
(10, "Aug 3 (Mon)", [
("Morning", "6:00โ10:00 AM", "MM PYQs โ essay: drug pictures, compare remedies, drug relationships"),
("Afternoon","11:00 AMโ3:00 PM","Thermal relations + miasmatic classification of all drugs studied"),
("Evening", "4:00โ7:00 PM", "Drug relationships: Complementary, inimical, antidotes for major drugs"),
("Night Rev","9:00โ10:00 PM", "MM one-liners and keynotes revision"),
]),
]
for day_num, date_str, sessions in days_mm:
story.append(day_header_row(day_num, date_str, "MM"))
story.append(session_table(sessions, "MM"))
story.append(Spacer(1, 5))
story.append(Spacer(1, 6))
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# PHASE 3 โ ORGANON
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
story.append(phase_header("๐ PHASE 3 โ ORGANON OF MEDICINE", "ORG", "Aug 4โ7", "4 Days"))
story.append(Spacer(1, 4))
days_org = [
(11, "Aug 4 (Tue)", [
("Morning", "6:00โ10:00 AM", "Aphorisms 1-70: Concept of health, disease, cure, vital force, susceptibility"),
("Afternoon","11:00 AMโ3:00 PM","Aphorisms 71-104: Classification of diseases, chronic diseases, miasms"),
("Evening", "4:00โ7:00 PM", "Aphorisms 105-145: Drug proving, pure experiments, remedy selection"),
("Night Rev","9:00โ10:00 PM", "Write 10 important aphorisms with explanations from memory"),
]),
(12, "Aug 5 (Wed)", [
("Morning", "6:00โ10:00 AM", "Aphorisms 146-203: Homoeopathic aggravation, direction of cure, accessory symptoms"),
("Afternoon","11:00 AMโ3:00 PM","Aphorisms 204-260: Obstacles to cure, diet & regimen, management"),
("Evening", "4:00โ7:00 PM", "Aphorisms 261-291: Posology โ dose, potency, repetition, LM potencies"),
("Night Rev","9:00โ10:00 PM", "Potency selection rules โ important for exam short notes"),
]),
(13, "Aug 6 (Thu)", [
("Morning", "6:00โ10:00 AM", "Case taking: Aph 83-104 in detail โ totality, characteristic symptoms, PQRS"),
("Afternoon","11:00 AMโ3:00 PM","Second prescription: Hering's law, Kentian vs Hahnemannian philosophy"),
("Evening", "4:00โ7:00 PM", "Comparisons: Psora vs Sycosis vs Syphilis; Acute vs Chronic disease"),
("Night Rev","9:00โ10:00 PM", "Important definitions from Organon โ for one-word/short answers"),
]),
(14, "Aug 7 (Fri)", [
("Morning", "6:00โ10:00 AM", "Organon PYQs โ 5 years paper practice"),
("Afternoon","11:00 AMโ3:00 PM","Essay topics: Vital force, Ideal cure, Miasms, Drug proving, LM potency"),
("Evening", "4:00โ7:00 PM", "Footnotes of Organon (6th edition) โ commonly asked in exams"),
("Night Rev","9:00โ10:00 PM", "Quick revision: Aphorism number + keywords mapping"),
]),
]
for day_num, date_str, sessions in days_org:
story.append(day_header_row(day_num, date_str, "ORG"))
story.append(session_table(sessions, "ORG"))
story.append(Spacer(1, 5))
story.append(Spacer(1, 6))
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# PHASE 4 โ REPERTORY
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
story.append(phase_header("๐ PHASE 4 โ REPERTORY", "REP", "Aug 8โ10", "3 Days"))
story.append(Spacer(1, 4))
days_rep = [
(15, "Aug 8 (Sat)", [
("Morning", "6:00โ10:00 AM", "Introduction: Kent, Boger, Boenninghausen, Murphy โ structure & comparison"),
("Afternoon","11:00 AMโ3:00 PM","Kent's Repertory: Mind chapter โ important rubrics, marking system"),
("Evening", "4:00โ7:00 PM", "Kent's chapters: Head, Eye, Ear, Nose โ important rubrics + remedies"),
("Night Rev","9:00โ10:00 PM", "Rubric selection practice โ convert symptoms to rubrics"),
]),
(16, "Aug 9 (Sun)", [
("Morning", "6:00โ10:00 AM", "Kent's Repertory: Chest, Heart, Stomach, Abdomen chapters"),
("Afternoon","11:00 AMโ3:00 PM","Repertorization methods: Kent's, Boenninghausen's, Card, Computer"),
("Evening", "4:00โ7:00 PM", "Totality of symptoms: Complete symptom (location, sensation, modality, concomitant)"),
("Night Rev","9:00โ10:00 PM", "Solve 5 cases using repertorization"),
]),
(17, "Aug 10 (Mon)", [
("Morning", "6:00โ10:00 AM", "Boger's Repertory + Boenninghausen's TTBCM โ structure and use"),
("Afternoon","11:00 AMโ3:00 PM","Repertory PYQs โ rubric finding, case repertorization, comparison questions"),
("Evening", "4:00โ7:00 PM", "Clinical repertories: Murphy's, Phatak's โ common exam questions"),
("Night Rev","9:00โ10:00 PM", "Important rubrics by heart: Suicidal, Fear, Jealousy, Sadness, Anger"),
]),
]
for day_num, date_str, sessions in days_rep:
story.append(day_header_row(day_num, date_str, "REP"))
story.append(session_table(sessions, "REP"))
story.append(Spacer(1, 5))
story.append(Spacer(1, 6))
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# PHASE 5 โ PSM
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
story.append(phase_header("๐ PHASE 5 โ PREVENTIVE & SOCIAL MEDICINE (PSM)", "PSM", "Aug 11โ13", "3 Days"))
story.append(Spacer(1, 4))
days_psm = [
(18, "Aug 11 (Tue)", [
("Morning", "6:00โ10:00 AM", "Epidemiology: Basic concepts, modes of transmission, herd immunity, prevention levels"),
("Afternoon","11:00 AMโ3:00 PM","Communicable diseases: Malaria, TB, HIV, Polio, Measles, Cholera โ control measures"),
("Evening", "4:00โ7:00 PM", "Immunization schedule (UIP), Cold chain, National Health Mission"),
("Night Rev","9:00โ10:00 PM", "Important definitions: Incidence, Prevalence, R0, NMR, IMR, MMR"),
]),
(19, "Aug 12 (Wed)", [
("Morning", "6:00โ10:00 AM", "Biostatistics: Data types, mean/median/mode, SD, normal distribution, significance tests"),
("Afternoon","11:00 AMโ3:00 PM","National programs: RNTCP, NVBDCP, NPCDCS, RCH, Janani Suraksha, Ayushman Bharat"),
("Evening", "4:00โ7:00 PM", "Environment health: Water, Air, Sanitation standards. Occupational diseases"),
("Night Rev","9:00โ10:00 PM", "PSM abbreviations and schemes โ rapid fire revision"),
]),
(20, "Aug 13 (Thu)", [
("Morning", "6:00โ10:00 AM", "PSM PYQs โ last 5 years, focus on MCQ patterns + essay topics"),
("Afternoon","11:00 AMโ3:00 PM","Nutrition: PEM, vitamin deficiencies, food adulteration, ICDS scheme"),
("Evening", "4:00โ7:00 PM", "FULL EXAM REVISION โ All 5 subjects: one-page summary each"),
("Night Rev","9:00โ10:00 PM", "Mental prep + organise notes for remaining 6 days"),
]),
]
for day_num, date_str, sessions in days_psm:
story.append(day_header_row(day_num, date_str, "PSM"))
story.append(session_table(sessions, "PSM"))
story.append(Spacer(1, 5))
story.append(Spacer(1, 6))
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# PHASE 6 โ 6-DAY REVISION
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
story.append(phase_header("๐ 6-DAY WEAK SUBJECT INTENSIVE REVISION", "REV", "Aug 14โ19", "6 Days"))
story.append(Spacer(1, 4))
rev_data = [
[Paragraph("<b>Days</b>", SMALL_HDR), Paragraph("<b>Dates</b>", SMALL_HDR),
Paragraph("<b>Subject Focus</b>", SMALL_HDR), Paragraph("<b>What to Do</b>", SMALL_HDR)],
[Paragraph("Day 21-22", CELL_BOLD), Paragraph("Aug 14โ15", CELL_NORM),
Paragraph("Practice of Medicine", CELL_BOLD), Paragraph("All PYQs + therapeutics quick revision + write model answers", CELL_NORM)],
[Paragraph("Day 23-24", CELL_BOLD), Paragraph("Aug 16โ17", CELL_NORM),
Paragraph("Materia Medica + Organon", CELL_BOLD), Paragraph("Drug comparisons + aphorisms recall test + footnotes", CELL_NORM)],
[Paragraph("Day 25-26", CELL_BOLD), Paragraph("Aug 18โ19", CELL_NORM),
Paragraph("Repertory + PSM", CELL_BOLD), Paragraph("Case repertorization practice + PSM schemes + mock test", CELL_NORM)],
]
rev_tbl = Table(rev_data, colWidths=[2.2*cm, 2.5*cm, 5.0*cm, 7.7*cm])
rev_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), C_REV),
("TEXTCOLOR", (0,0),(-1,0), C_WHITE),
("GRID", (0,0),(-1,-1), 0.3, colors.HexColor("#CCCCCC")),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 5),
("FONTSIZE", (0,0),(-1,-1), 7.5),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("ROWBACKGROUNDS",(0,1),(-1,-1), [C_LIGHT, C_STRIPE]),
]))
story.append(rev_tbl)
story.append(Spacer(1, 8))
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# DAILY TIMETABLE + TIPS (side by side)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
timetable_items = [
("5:30 AM", "Wake up, freshen up, light exercise"),
("6:00 AM", "Session 1 โ Major topic block (4 hrs)"),
("10:00 AM","Breakfast + 30-min break"),
("10:30 AM","Light review / make index cards"),
("11:00 AM","Session 2 โ Major topic block (4 hrs)"),
("3:00 PM", "Lunch + rest (60 min)"),
("4:00 PM", "Session 3 โ Third topic block (3 hrs)"),
("7:00 PM", "Dinner + walk (60 min)"),
("8:00 PM", "PYQ practice / Answer writing (1 hr)"),
("9:00 PM", "Night revision (1 hr)"),
("10:00 PM","Sleep โ 7 hrs minimum"),
]
tips = [
"Write 10-mark & 5-mark answers daily from Day 4",
"Solve last 5 years PYQs for every subject",
"MM: Use Kent's MM + Boericke; focus on BOLD symptoms",
"Organon: Memorise ยง1, ยง9, ยง10, ยง11, ยง29, ยง70, ยง153, ยง269",
"Repertory: Always convert clinical Sx to rubrics",
"PSM: National programs + epidemiology defs = high yield",
"Never skip Night Revision โ 1 hr of review beats 2 hrs next day",
"Sleep 7 hrs minimum โ memory consolidation is not optional",
"Drink water, take 5-min breaks every hour",
"Sticky notes on wall for keynotes & aphorisms",
]
tt_data = [[Paragraph("<b>Time</b>", SMALL_HDR), Paragraph("<b>Activity</b>", SMALL_HDR)]]
for t, a in timetable_items:
tt_data.append([Paragraph(t, CELL_BOLD), Paragraph(a, CELL_NORM)])
tt_tbl = Table(tt_data, colWidths=[2.2*cm, 5.8*cm])
tt_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), C_HEADER),
("TEXTCOLOR", (0,0),(-1,0), C_WHITE),
("GRID", (0,0),(-1,-1), 0.3, colors.HexColor("#CCCCCC")),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 5),
("FONTSIZE", (0,0),(-1,-1), 7),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("ROWBACKGROUNDS",(0,1),(-1,-1), [C_LIGHT, C_STRIPE]),
]))
tips_header = [[Paragraph("<b>Exam Strategy Tips</b>", SMALL_HDR)]]
tips_rows = [[Paragraph(f"โข {t}", TIP_STY)] for t in tips]
tips_data = tips_header + tips_rows
tips_tbl = Table(tips_data, colWidths=[8.8*cm])
tips_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), C_HEADER),
("TEXTCOLOR", (0,0),(-1,0), C_WHITE),
("GRID", (0,0),(-1,-1), 0.3, colors.HexColor("#CCCCCC")),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 6),
("FONTSIZE", (0,0),(-1,-1), 7),
("VALIGN", (0,0),(-1,-1), "TOP"),
("ROWBACKGROUNDS",(0,1),(-1,-1), [C_LIGHT, C_STRIPE]),
]))
bottom_row = Table([[tt_tbl, tips_tbl]], colWidths=[8.4*cm, 9*cm])
bottom_row.setStyle(TableStyle([
("VALIGN", (0,0),(-1,-1), "TOP"),
("LEFTPADDING", (0,0),(-1,-1), 0),
("RIGHTPADDING", (0,0),(-1,-1), 0),
("TOPPADDING", (0,0),(-1,-1), 0),
("BOTTOMPADDING",(0,0),(-1,-1), 0),
("INNERGRID", (0,0),(-1,-1), 0, colors.white),
("BOX", (0,0),(-1,-1), 0, colors.white),
]))
section_label = Paragraph("<b>DAILY TIMETABLE & EXAM STRATEGY TIPS</b>",
sty("secL", fontName="Helvetica-Bold", fontSize=8.5, textColor=C_WHITE,
alignment=TA_CENTER, leading=12))
sec_hdr = Table([[section_label]], colWidths=[17.4*cm])
sec_hdr.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), C_HEADER),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING",(0,0),(-1,-1), 5),
("ROUNDEDCORNERS",[4]),
]))
story.append(sec_hdr)
story.append(Spacer(1, 4))
story.append(bottom_row)
story.append(Spacer(1, 8))
# โโ Footer โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
story.append(HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#CCCCCC")))
story.append(Spacer(1, 4))
story.append(Paragraph(
"BHMS 4th Year | 20-Day Study Schedule | Prepared by Orris Study Planner | July 2026 | You've got this!",
FOOTER_STY))
# โโ Build PDF โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
doc.build(story)
print(f"PDF saved to: {OUTPUT}")