~/english-plan/generate_plan.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import PageBreak
OUTPUT = "/home/daytona/workspace/english-plan/7Day_English_Plan_MBBS.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
rightMargin=2*cm, leftMargin=2*cm,
topMargin=2*cm, bottomMargin=2*cm
)
# โโ Colour palette โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
NAVY = colors.HexColor("#1B3A6B")
TEAL = colors.HexColor("#0D7C8C")
LIGHT = colors.HexColor("#E8F4F8")
GOLD = colors.HexColor("#F5A623")
WHITE = colors.white
LGREY = colors.HexColor("#F2F2F2")
DGREY = colors.HexColor("#444444")
# โโ Styles โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
styles = getSampleStyleSheet()
title_style = ParagraphStyle("Title",
fontName="Helvetica-Bold", fontSize=22,
textColor=WHITE, alignment=TA_CENTER, spaceAfter=4)
subtitle_style = ParagraphStyle("Subtitle",
fontName="Helvetica", fontSize=12,
textColor=LIGHT, alignment=TA_CENTER, spaceAfter=2)
tagline_style = ParagraphStyle("Tagline",
fontName="Helvetica-Oblique", fontSize=10,
textColor=GOLD, alignment=TA_CENTER, spaceAfter=0)
day_header_style = ParagraphStyle("DayHeader",
fontName="Helvetica-Bold", fontSize=13,
textColor=WHITE, alignment=TA_LEFT, leftIndent=6)
section_style = ParagraphStyle("Section",
fontName="Helvetica-Bold", fontSize=10,
textColor=TEAL, spaceAfter=2, spaceBefore=6)
body_style = ParagraphStyle("Body",
fontName="Helvetica", fontSize=9,
textColor=DGREY, leading=13, spaceAfter=3)
bullet_style = ParagraphStyle("Bullet",
fontName="Helvetica", fontSize=9,
textColor=DGREY, leading=13, leftIndent=12,
bulletIndent=4, spaceAfter=2)
note_style = ParagraphStyle("Note",
fontName="Helvetica-Oblique", fontSize=8.5,
textColor=colors.HexColor("#666666"), leading=12)
tip_style = ParagraphStyle("Tip",
fontName="Helvetica-Bold", fontSize=9,
textColor=NAVY, leading=13)
# โโ Helper โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def bullet(text):
return Paragraph(f"โข {text}", bullet_style)
def section(text):
return Paragraph(text, section_style)
def body(text):
return Paragraph(text, body_style)
def space(h=0.2):
return Spacer(1, h*cm)
def hr(color=TEAL, thickness=0.5):
return HRFlowable(width="100%", thickness=thickness, color=color, spaceAfter=4, spaceBefore=4)
# โโ Cover Banner โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def make_cover_banner():
banner_data = [[
Paragraph("7-Day Beginner English Practice Plan", title_style),
]]
banner = Table(banner_data, colWidths=[17*cm])
banner.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 18),
("BOTTOMPADDING",(0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 12),
("RIGHTPADDING", (0,0), (-1,-1), 12),
("ROUNDEDCORNERS", [8]),
]))
sub_data = [[
Paragraph("Specially Designed for MBBS Students Who Are Beginning Their English Journey", subtitle_style),
]]
sub = Table(sub_data, colWidths=[17*cm])
sub.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), TEAL),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING",(0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 12),
("RIGHTPADDING", (0,0), (-1,-1), 12),
]))
tag_data = [[
Paragraph('"Dar mat - Roz thoda, lekin roz karo." (Don\'t fear - a little daily goes a long way)', tagline_style),
]]
tag = Table(tag_data, colWidths=[17*cm])
tag.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING",(0,0), (-1,-1), 12),
("LEFTPADDING", (0,0), (-1,-1), 12),
("RIGHTPADDING", (0,0), (-1,-1), 12),
]))
return [banner, sub, tag]
# โโ Info Box โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def info_box():
rows = [
[Paragraph("<b>Who is this for?</b>", tip_style),
Paragraph("MBBS 3rd year (or any year) students who feel nervous speaking English and want to start from scratch.", body_style)],
[Paragraph("<b>Daily time needed</b>", tip_style),
Paragraph("Only 20-30 minutes per day. No extra classes needed.", body_style)],
[Paragraph("<b>Golden Rule</b>", tip_style),
Paragraph("Never skip two days in a row. Consistency beats intensity.", body_style)],
[Paragraph("<b>Mindset</b>", tip_style),
Paragraph("Mistakes are proof you are trying. Speak wrong, speak often.", body_style)],
]
t = Table(rows, colWidths=[4*cm, 13*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LGREY),
("BACKGROUND", (0,0), (0,-1), LIGHT),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING",(0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
return t
# โโ Day Block โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def day_block(day_num, day_name, theme, emoji, tasks, sentences, tip_text):
day_colors = [
colors.HexColor("#1B3A6B"), # D1 Navy
colors.HexColor("#0D7C8C"), # D2 Teal
colors.HexColor("#2E7D32"), # D3 Green
colors.HexColor("#6A1B9A"), # D4 Purple
colors.HexColor("#BF360C"), # D5 Deep Orange
colors.HexColor("#00695C"), # D6 Dark Teal
colors.HexColor("#C62828"), # D7 Red
]
dc = day_colors[(day_num - 1) % len(day_colors)]
# Header row
header_data = [[
Paragraph(f"Day {day_num} {emoji} {day_name}", day_header_style),
Paragraph(f"Theme: {theme}", ParagraphStyle("ThemeRight",
fontName="Helvetica-Oblique", fontSize=9,
textColor=LIGHT, alignment=TA_LEFT)),
]]
header = Table(header_data, colWidths=[9*cm, 8*cm])
header.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), dc),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING",(0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
# Tasks
task_items = [Paragraph("<b>Today's Tasks:</b>", section_style)]
for t in tasks:
task_items.append(bullet(t))
# Practice sentences
sent_items = [Paragraph("<b>Practice These Sentences (say them 5x aloud):</b>", section_style)]
for s in sentences:
sent_items.append(Paragraph(f'<i>"{s}"</i>', ParagraphStyle("Sent",
fontName="Helvetica-Oblique", fontSize=9,
textColor=colors.HexColor("#333333"),
leftIndent=10, spaceAfter=3, leading=13)))
# Tip
tip_box_data = [[
Paragraph(f"๐ก Tip: {tip_text}", ParagraphStyle("TipBox",
fontName="Helvetica", fontSize=9,
textColor=NAVY, leading=13))
]]
tip_box = Table(tip_box_data, colWidths=[17*cm])
tip_box.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#FFF9E6")),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING",(0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
("BOX", (0,0), (-1,-1), 0.8, GOLD),
]))
left_col = task_items + [space(0.15)] + sent_items
right_col = [space(0.1), tip_box]
content_data = [[
left_col,
right_col,
]]
# We'll render them in a 2-col layout
left_items = task_items + [space(0.15)] + sent_items
right_items = [space(0.2), tip_box]
# Build as single column for cleanliness
block = [header]
body_rows = []
for item in left_items:
body_rows.append(item)
body_rows.append(space(0.1))
body_rows.append(tip_box)
body_table_data = [[ body_rows ]]
body_table = Table([["\n".join([])]], colWidths=[17*cm])
# Assemble all flowables for this day
flowables = [space(0.1), header]
for item in left_items:
flowables.append(item)
flowables.append(space(0.1))
flowables.append(tip_box)
flowables.append(space(0.3))
return KeepTogether(flowables)
# โโ Day Data โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
days = [
{
"num": 1, "name": "Self Introduction", "theme": "Speaking Basics",
"emoji": "๐ค",
"tasks": [
"Mirror Practice (5 min): Say your name, college, and year in English",
"Write 3 sentences about yourself in a notebook",
"Learn 5 new words: introduce, student, medicine, hospital, learn",
"Listen: Watch 1 short English video (5 min) - BBC Learning English on YouTube",
],
"sentences": [
"My name is [your name]. I am an MBBS student in 3rd year.",
"I study at [college name]. I want to become a good doctor.",
"I am learning English. I will improve day by day.",
],
"tip": "Do NOT worry about accent. Indian English is perfectly fine. Clarity matters more than accent.",
},
{
"num": 2, "name": "Patient Greeting", "theme": "Clinical Communication",
"emoji": "๐ฉบ",
"tasks": [
"Learn the 5 basic patient greeting phrases by heart",
"Role-play: Pretend a pillow or object is a patient and greet them",
"Write a 3-line patient introduction script in your notebook",
"New vocabulary: complaint, duration, onset, history, examine",
],
"sentences": [
"Good morning. Please have a seat. How can I help you?",
"Since how many days are you having this problem?",
"Do not worry. I will examine you and we will find out what is wrong.",
"Can you point to where the pain is?",
],
"tip": "In clinical English, simple sentences work best. Patients prefer easy words over medical jargon.",
},
{
"num": 3, "name": "Describing Symptoms", "theme": "Medical Vocabulary",
"emoji": "๐",
"tasks": [
"Learn 10 symptom words: fever, cough, breathlessness, vomiting, diarrhea, headache, fatigue, swelling, pain, burning",
"Practice asking about each symptom in 1 sentence",
"Write a short case history of a fake patient with fever",
"Read 1 paragraph from your Harrison's or Davidson's in English (don't worry about understanding every word)",
],
"sentences": [
"The patient is a 30-year-old male presenting with fever for 3 days.",
"He also complains of headache and body ache.",
"There is no history of vomiting or diarrhea.",
"On examination, temperature is 102ยฐF.",
],
"tip": "Case history writing is the FASTEST way to improve medical English - it uses a fixed template every time.",
},
{
"num": 4, "name": "Small Talk + Confidence", "theme": "Overcoming Fear",
"emoji": "๐ฌ",
"tasks": [
"Send at least 3 WhatsApp messages to classmates in English today",
"Talk to ONE friend in English for just 5 minutes about anything",
"Write in English what you did today - 5-6 simple sentences",
"Vocabulary: explain, understand, repeat, describe, mention",
],
"sentences": [
"I studied cardiology today. It was difficult but interesting.",
"Can you please repeat that? I did not understand.",
"I think the diagnosis is... What do you think?",
"Let us discuss this case together.",
],
"tip": "Fear of judgment reduces when you realize your classmates are also struggling. Everyone is in the same boat.",
},
{
"num": 5, "name": "Viva & Exam English", "theme": "Academic Speaking",
"emoji": "๐",
"tasks": [
"Practice answering 3 common viva questions in English (see below)",
"Learn connecting words: furthermore, however, therefore, in addition, in contrast",
"Record yourself answering one question on your phone - listen back",
"Read your class notes and try to explain one topic aloud in English for 2 minutes",
],
"sentences": [
"The most common cause of this condition is...",
"The treatment of choice is... because...",
"On auscultation, we can hear... which suggests...",
"Sir, I would like to add that...",
],
"tip": "In vivas, starting your answer confidently matters. Even if you pause, a clear start impresses the examiner.",
},
{
"num": 6, "name": "Reading + Writing", "theme": "Written English",
"emoji": "๐",
"tasks": [
"Read one page of an English medical article or textbook - mark any word you don't know",
"Look up 5 unknown words and write a sentence using each",
"Write a full case presentation (10-12 lines) of a patient you saw or imagined",
"Email or message your professor one question in English",
],
"sentences": [
"Regarding the patient admitted on [date], I would like to present...",
"The chief complaint is... with a history of... days.",
"Past history includes... and family history is not significant.",
"My impression is... and I recommend...",
],
"tip": "Writing slows you down and forces you to think in English - it is the secret weapon for speaking fluency.",
},
{
"num": 7, "name": "Review + Celebrate", "theme": "Consolidation",
"emoji": "๐",
"tasks": [
"Review all 6 days - re-read your notebook sentences",
"Do a 5-minute self-introduction again (compare to Day 1 - you HAVE improved)",
"Teach one medical concept to a friend entirely in English",
"Plan your next 7 days: pick 1 topic per day to practice",
],
"sentences": [
"I have been practicing English for 7 days and I can feel the difference.",
"Today I will present a case: a 45-year-old female with chest pain...",
"I am not perfect yet, but I am much better than Day 1.",
"Every doctor needs English - I am building this skill step by step.",
],
"tip": "Progress in English is not visible daily - but look back at Day 1 and you will be surprised how far you have come.",
},
]
# โโ Build Document โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
story = []
# Cover
story += make_cover_banner()
story.append(space(0.4))
story.append(info_box())
story.append(space(0.5))
story.append(hr(NAVY, 1.5))
story.append(space(0.2))
# Days
for d in days:
story.append(day_block(
d["num"], d["name"], d["theme"], d["emoji"],
d["tasks"], d["sentences"], d["tip"]
))
# โโ Bonus Section โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
story.append(hr(TEAL, 1))
story.append(space(0.2))
bonus_header = Table([[Paragraph("BONUS: Essential Medical English Phrases", ParagraphStyle(
"BonusH", fontName="Helvetica-Bold", fontSize=12, textColor=WHITE, alignment=TA_CENTER))]],
colWidths=[17*cm])
bonus_header.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), TEAL),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING",(0,0), (-1,-1), 8),
]))
story.append(bonus_header)
story.append(space(0.2))
phrases = [
("Starting a History", ["What brings you in today?", "Since when are you having this problem?", "Does anything make it better or worse?"]),
("Examination", ["I am going to examine you now.", "Please take a deep breath.", "Does it hurt when I press here?"]),
("Explaining to Patient", ["You have a condition called...", "I will prescribe some medicines.", "Please come back after 5 days."]),
("In the Ward/Rounds", ["This patient was admitted for...", "Labs show elevated...", "We plan to start... and monitor..."]),
("Viva Key Phrases", ["The pathophysiology is...", "Complications include...", "The investigation of choice is..."]),
]
for cat, ph_list in phrases:
story.append(Paragraph(f"<b>{cat}</b>", section_style))
for ph in ph_list:
story.append(bullet(ph))
story.append(space(0.1))
# Footer note
story.append(hr(GOLD, 1))
story.append(space(0.1))
story.append(Paragraph(
"Remember: Every great doctor once struggled with English too. "
"You are not behind - you are on your way. "
"Practice daily, be kind to yourself, and keep going.",
ParagraphStyle("Footer", fontName="Helvetica-Oblique", fontSize=9,
textColor=NAVY, alignment=TA_CENTER, leading=14)
))
doc.build(story)
print(f"PDF created: {OUTPUT}")