According to coaching centers like DAMS and, uh, uh, and ABR like that, if they are taking the 14 hours class of biochemistry means, how long days they will take? Because I'm going to, uh, see the same content, uh, in a different platform, but it's not online or face-- offline class. I'm learning on my own way. So give me a sample of that days so that I will cover in a faster way or the correct way.
DAMS ABR coaching biochemistry schedule hours per day medical PG preparation
For every 1 hour of class/lecture = add 1.5x to 2x time for self-study (reading + notes + MCQs)
| Day | Topics | Study Hours/Day |
|---|---|---|
| Day 1 | Carbohydrates (glycolysis, TCA, glycogen) | 3-4 hrs |
| Day 2 | Lipid metabolism (fatty acids, ketone bodies, cholesterol) | 3-4 hrs |
| Day 3 | Protein metabolism + amino acids + urea cycle | 3-4 hrs |
| Day 4 | Enzymes + vitamins | 3-4 hrs |
| Day 5 | Nucleotides, DNA replication, transcription, translation | 3-4 hrs |
| Day 6 | Molecular biology (PCR, recombinant DNA, mutations) | 3-4 hrs |
| Day 7 | Revision + MCQ practice (all topics) | 3-4 hrs |
| Day | Topics | Study Hours/Day |
|---|---|---|
| Day 1 | Carbohydrate metabolism Part 1 (glycolysis, Krebs, ETC) | 2.5 hrs |
| Day 2 | Carbohydrate metabolism Part 2 (gluconeogenesis, glycogen, HMP shunt) | 2.5 hrs |
| Day 3 | Lipid metabolism Part 1 (fatty acid oxidation, synthesis) | 2.5 hrs |
| Day 4 | Lipid metabolism Part 2 (cholesterol, lipoproteins, ketone bodies) | 2.5 hrs |
| Day 5 | Protein + amino acid metabolism, urea cycle | 2.5 hrs |
| Day 6 | Enzymes (kinetics, inhibition, clinical relevance) | 2.5 hrs |
| Day 7 | Vitamins (water + fat soluble, deficiency diseases) | 2.5 hrs |
| Day 8 | Nucleotides + DNA structure + replication | 2.5 hrs |
| Day 9 | Transcription + translation + genetic code | 2.5 hrs |
| Day 10 | Molecular biology + full revision + MCQs | 2.5 hrs |
No, I will upload the topic. I need to complete this within three days. Give me a perfect timetable for that. I will study for up to 10 to 12 hours with break. Okay.
With this one more topic graph for 1 hr
| # | Topic | Duration |
|---|---|---|
| 19 | Rapid Revision Part 1 | 1 hr 29 min |
| 20 | Rapid Revision Part 2 | 1 hr 07 min |
| 21 | Rapid Revision Part 3 | 2 hr 10 min |
| 22 | Rapid Revision Part 4 | 1 hr 51 min |
| 23 | ETC and Protein | 1 hr 56 min |
| 24 | Vitamins | 1 hr 50 min |
| 25 | Clinical Biochemistry | 2 hr 00 min |
| 26 | Genetics | 2 hr 43 min |
| + | Graph | 1 hr 00 min |
| TOTAL | ~16 hrs 06 min |
| Time | Activity | Duration |
|---|---|---|
| 6:00 AM | Wake up + freshen up | - |
| 6:30 AM | Graph (extra topic) | 1 hr |
| 7:30 AM | Rapid Revision Part 1 | 1 hr 29 min |
| 9:00 AM | Short break + snack | 20 min |
| 9:20 AM | Rapid Revision Part 2 | 1 hr 07 min |
| 10:30 AM | Rapid Revision Part 3 (first half) | 1 hr |
| 11:30 AM | Lunch break | 45 min |
| 12:15 PM | Rapid Revision Part 3 (second half) | 1 hr 10 min |
| 1:25 PM | Quick notes revision - Day 1 topics | 30 min |
| 1:55 PM | MCQ practice - Day 1 topics | 45 min |
| 2:40 PM | END OF DAY 1 ✅ | - |
| Time | Activity | Duration |
|---|---|---|
| 7:00 AM | Wake up + quick Day 1 flashback (10 min recap) | 15 min |
| 7:15 AM | Rapid Revision Part 4 | 1 hr 51 min |
| 9:10 AM | Short break | 20 min |
| 9:30 AM | ETC and Protein | 1 hr 56 min |
| 11:30 AM | Lunch break | 45 min |
| 12:15 PM | Vitamins | 1 hr 50 min |
| 2:05 PM | Short break + tea | 20 min |
| 2:25 PM | Quick notes revision - Day 2 topics | 30 min |
| 2:55 PM | MCQ practice - Day 2 topics | 45 min |
| 3:40 PM | END OF DAY 2 ✅ | - |
| Time | Activity | Duration |
|---|---|---|
| 7:00 AM | Wake up + Day 2 quick recap | 15 min |
| 7:15 AM | Clinical Biochemistry | 2 hr 00 min |
| 9:15 AM | Short break | 20 min |
| 9:35 AM | Genetics | 2 hr 43 min |
| 12:20 PM | Lunch break | 45 min |
| 1:05 PM | FULL REVISION - All 9 topics (notes only, no video) | 2 hrs |
| 3:05 PM | Grand MCQ Session - Mixed topics | 1 hr |
| 4:05 PM | Weak areas re-check | 30 min |
| 4:35 PM | DONE - All topics complete ✅ | - |
| Day | Content Hours | Total Study Time |
|---|---|---|
| Day 1 | 5 hr 26 min | ~7 hrs |
| Day 2 | 5 hr 37 min | ~8 hrs |
| Day 3 | 4 hr 43 min + Revision | ~9 hrs |
| Total | 16 hr 06 min | ~24 hrs |
No remove that graph from first day
| Time | Activity | Duration |
|---|---|---|
| 6:30 AM | Rapid Revision Part 1 | 1 hr 29 min |
| 8:00 AM | Short break | 15 min |
| 8:15 AM | Rapid Revision Part 2 | 1 hr 07 min |
| 9:22 AM | Short break + snack | 20 min |
| 9:42 AM | Rapid Revision Part 3 (first half) | 1 hr |
| 10:42 AM | Rapid Revision Part 3 (second half) | 1 hr 10 min |
| 11:52 AM | Lunch break | 45 min |
| 12:37 PM | Quick notes revision - Day 1 topics | 30 min |
| 1:07 PM | MCQ practice - Day 1 topics | 45 min |
| 1:52 PM | END OF DAY 1 ✅ |
| Time | Activity | Duration |
|---|---|---|
| 7:00 AM | Day 1 quick recap | 15 min |
| 7:15 AM | Rapid Revision Part 4 | 1 hr 51 min |
| 9:06 AM | Short break | 20 min |
| 9:26 AM | ETC and Protein | 1 hr 56 min |
| 11:22 AM | Lunch break | 45 min |
| 12:07 PM | Vitamins | 1 hr 50 min |
| 1:57 PM | Short break | 20 min |
| 2:17 PM | Quick notes revision - Day 2 topics | 30 min |
| 2:47 PM | MCQ practice - Day 2 topics | 45 min |
| 3:32 PM | END OF DAY 2 ✅ |
| Time | Activity | Duration |
|---|---|---|
| 7:00 AM | Day 2 quick recap | 15 min |
| 7:15 AM | Graph | 1 hr 00 min |
| 8:15 AM | Short break | 15 min |
| 8:30 AM | Clinical Biochemistry | 2 hr 00 min |
| 10:30 AM | Short break + snack | 20 min |
| 10:50 AM | Genetics | 2 hr 43 min |
| 1:33 PM | Lunch break | 45 min |
| 2:18 PM | FULL REVISION - All 9 topics (notes only) | 2 hrs |
| 4:18 PM | Grand MCQ Session - Mixed topics | 1 hr |
| 5:18 PM | Weak areas re-check | 30 min |
| 5:48 PM | ALL DONE ✅ |
| Day | Content | Total Study |
|---|---|---|
| Day 1 | 4 hr 46 min | ~6.5 hrs |
| Day 2 | 5 hr 37 min | ~8 hrs |
| Day 3 | 5 hr 43 min + Revision | ~10 hrs |
| Total | 16 hr 06 min | ~24.5 hrs |
Put time table till night 11.00
| Time | Activity | Duration |
|---|---|---|
| 6:00 AM | Wake up + freshen up + light breakfast | 30 min |
| 6:30 AM | Rapid Revision Part 1 | 1 hr 29 min |
| 8:00 AM | Short break + snack | 15 min |
| 8:15 AM | Rapid Revision Part 2 | 1 hr 07 min |
| 9:22 AM | Short break | 15 min |
| 9:37 AM | Rapid Revision Part 3 (first half ~1 hr) | 1 hr |
| 10:37 AM | Short break | 10 min |
| 10:47 AM | Rapid Revision Part 3 (second half ~1 hr 10 min) | 1 hr 10 min |
| 11:57 AM | Lunch break | 45 min |
| 12:42 PM | Day 1 Notes Revision (go through what you watched) | 1 hr |
| 1:42 PM | MCQ Practice - Day 1 topics | 1 hr |
| 2:42 PM | Short break + tea | 20 min |
| 3:02 PM | Weak point re-study (topics you found hard in Part 1-3) | 1 hr |
| 4:02 PM | Second round MCQs - Day 1 | 45 min |
| 4:47 PM | Evening break + walk + refresh | 45 min |
| 5:32 PM | Flash revision - Day 1 key points (notes only, no video) | 1 hr |
| 6:32 PM | Dinner break | 45 min |
| 7:17 PM | Difficult concepts deep dive (whatever is unclear) | 1 hr 30 min |
| 8:47 PM | Short break | 15 min |
| 9:02 PM | Day 1 Final MCQ round (timed, 30 Qs) | 45 min |
| 9:47 PM | Write down key formulas / mnemonics from Day 1 | 30 min |
| 10:17 PM | Light review / relax reading | 30 min |
| 10:47 PM | Wind down, prep for tomorrow | 13 min |
| 11:00 PM | SLEEP 😴 |
| Time | Activity | Duration |
|---|---|---|
| 6:00 AM | Wake up + freshen up + breakfast | 30 min |
| 6:30 AM | Day 1 Quick Recap (notes only, 20 min) | 20 min |
| 6:50 AM | Rapid Revision Part 4 | 1 hr 51 min |
| 8:41 AM | Short break + snack | 20 min |
| 9:01 AM | ETC and Protein | 1 hr 56 min |
| 10:57 AM | Short break | 15 min |
| 11:12 AM | Vitamins | 1 hr 50 min |
| 1:02 PM | Lunch break | 45 min |
| 1:47 PM | Day 2 Notes Revision | 1 hr |
| 2:47 PM | MCQ Practice - Day 2 topics | 1 hr |
| 3:47 PM | Short break + tea | 20 min |
| 4:07 PM | Weak point re-study (ETC, protein, vitamins hard points) | 1 hr |
| 5:07 PM | Evening break + walk | 45 min |
| 5:52 PM | Second round MCQs - Day 2 | 45 min |
| 6:37 PM | Combined revision - Day 1 + Day 2 (notes only) | 1 hr |
| 7:37 PM | Dinner break | 45 min |
| 8:22 PM | Vitamins special focus (most asked in exams - go deep) | 1 hr |
| 9:22 PM | Short break | 15 min |
| 9:37 PM | Day 2 Final MCQ round (timed, 30 Qs) | 45 min |
| 10:22 PM | Write key mnemonics - Day 2 | 30 min |
| 10:52 PM | Wind down | 8 min |
| 11:00 PM | SLEEP 😴 |
| Time | Activity | Duration |
|---|---|---|
| 6:00 AM | Wake up + freshen up + breakfast | 30 min |
| 6:30 AM | Day 1 + Day 2 Combined Recap (notes only) | 30 min |
| 7:00 AM | Graph | 1 hr 00 min |
| 8:00 AM | Short break + snack | 20 min |
| 8:20 AM | Clinical Biochemistry | 2 hr 00 min |
| 10:20 AM | Short break | 20 min |
| 10:40 AM | Genetics | 2 hr 43 min |
| 1:23 PM | Lunch break | 45 min |
| 2:08 PM | MCQ Practice - Day 3 topics | 1 hr |
| 3:08 PM | Short break + tea | 20 min |
| 3:28 PM | FULL REVISION - All 9 topics (notes only, no video) | 2 hrs |
| 5:28 PM | Evening break + walk | 45 min |
| 6:13 PM | Grand Mixed MCQ Session (all topics, 50 Qs timed) | 1 hr 15 min |
| 7:28 PM | Dinner break | 45 min |
| 8:13 PM | Weak areas targeted re-study (from MCQ errors) | 1 hr 15 min |
| 9:28 PM | Short break | 15 min |
| 9:43 PM | Final Flash Revision - All key points, mnemonics, diagrams | 1 hr |
| 10:43 PM | Wrap up - write tomorrow's carry-forward points | 15 min |
| 11:00 PM | ALL DONE - SLEEP 🎉😴 |
| Day 1 | Day 2 | Day 3 | |
|---|---|---|---|
| Content watched | 4 hr 46 min | 5 hr 37 min | 5 hr 43 min |
| MCQ practice | ~2.5 hrs | ~2.5 hrs | ~2.25 hrs |
| Revision | ~2.5 hrs | ~2.5 hrs | ~3.25 hrs |
| Breaks/Meals | ~2.5 hrs | ~2.5 hrs | ~2.5 hrs |
| Total day | 17 hrs | 17 hrs | 17 hrs |
Generate a checklist to track daily completion
Generate an Excel tracker to log daily MCQ scores
mkdir -p /tmp/workspace/biochem-tracker
~/biochem-tracker/create_tracker.py
import openpyxl
from openpyxl.styles import (
Font, PatternFill, Alignment, Border, Side, GradientFill
)
from openpyxl.utils import get_column_letter
from openpyxl.chart import BarChart, Reference, LineChart
from openpyxl.chart.series import DataPoint
from openpyxl.formatting.rule import ColorScaleRule, DataBarRule, FormulaRule
from openpyxl.worksheet.datavalidation import DataValidation
wb = openpyxl.Workbook()
# ─── Color Palette ───────────────────────────────────────────────
DARK_BLUE = "1F3864"
MED_BLUE = "2E75B6"
LIGHT_BLUE = "D6E4F0"
GREEN = "1E8449"
LIGHT_GREEN = "D5F5E3"
ORANGE = "E67E22"
LIGHT_ORANGE= "FDEBD0"
RED = "C0392B"
LIGHT_RED = "FADBD8"
YELLOW = "F9E79F"
WHITE = "FFFFFF"
LIGHT_GREY = "F2F2F2"
DARK_GREY = "595959"
def hfill(hex_color):
return PatternFill("solid", fgColor=hex_color)
def font(bold=False, color="000000", size=11, italic=False):
return Font(bold=bold, color=color, size=size, italic=italic, name="Arial")
def border(style="thin"):
s = Side(style=style)
return Border(left=s, right=s, top=s, bottom=s)
def center():
return Alignment(horizontal="center", vertical="center", wrap_text=True)
def left():
return Alignment(horizontal="left", vertical="center", wrap_text=True)
# ══════════════════════════════════════════════════════════════════
# SHEET 1 - DASHBOARD
# ══════════════════════════════════════════════════════════════════
ws1 = wb.active
ws1.title = "Dashboard"
# Set column widths
col_widths = [3, 22, 14, 14, 14, 14, 14, 14, 5]
for i, w in enumerate(col_widths, 1):
ws1.column_dimensions[get_column_letter(i)].width = w
# Row heights
for r in range(1, 60):
ws1.row_dimensions[r].height = 18
ws1.row_dimensions[1].height = 10
ws1.row_dimensions[2].height = 36
ws1.row_dimensions[3].height = 14
# ── Title ──
ws1.merge_cells("B2:H2")
c = ws1["B2"]
c.value = "📚 BIOCHEMISTRY MCQ TRACKER — 3-DAY STUDY PLAN"
c.font = Font(bold=True, color=WHITE, size=18, name="Arial")
c.fill = hfill(DARK_BLUE)
c.alignment = center()
# ── Subtitle ──
ws1.merge_cells("B3:H3")
c = ws1["B3"]
c.value = "Rapid Revision V XI | July 2026 | Track Every Session"
c.font = font(italic=True, color=DARK_GREY, size=10)
c.fill = hfill(LIGHT_BLUE)
c.alignment = center()
# ── Section: How to use ──
ws1.merge_cells("B5:H5")
c = ws1["B5"]
c.value = "HOW TO USE THIS TRACKER"
c.font = font(bold=True, color=WHITE, size=11)
c.fill = hfill(MED_BLUE)
c.alignment = center()
instructions = [
("B6:H6", "➡ Go to each Day sheet (Day 1, Day 2, Day 3) and fill in your MCQ scores after each session."),
("B7:H7", "➡ Enter: Total Questions Attempted and Correct Answers — the tracker auto-calculates your % score."),
("B8:H8", "➡ The Summary table below pulls all scores automatically. Check your progress here at a glance."),
("B9:H9", "➡ Green = 70%+ | Orange = 50–69% | Red = Below 50%. Aim for GREEN on every session!"),
]
for rng, txt in instructions:
ws1.merge_cells(rng)
c = ws1[rng.split(":")[0]]
c.value = txt
c.font = font(size=10, color="000000")
c.fill = hfill(LIGHT_BLUE)
c.alignment = left()
# ── Summary Table Header ──
ws1.merge_cells("B11:H11")
c = ws1["B11"]
c.value = "OVERALL SCORE SUMMARY"
c.font = font(bold=True, color=WHITE, size=12)
c.fill = hfill(DARK_BLUE)
c.alignment = center()
# Table headers
headers = ["Day / Session", "Topic", "Round", "Total Qs", "Correct", "Score %", "Status"]
cols = ["B", "C", "D", "E", "F", "G", "H"]
for h, col in zip(headers, cols):
c = ws1[f"{col}12"]
c.value = h
c.font = font(bold=True, color=WHITE, size=10)
c.fill = hfill(MED_BLUE)
c.alignment = center()
c.border = border()
# Summary rows - pulling from day sheets
summary_rows = [
# (display_day, display_topic, round_name, total_ref, correct_ref)
("Day 1", "Rapid Rev 1,2,3", "Round 1", "'Day 1'!D5", "'Day 1'!E5"),
("Day 1", "Rapid Rev 1,2,3", "Round 2", "'Day 1'!D6", "'Day 1'!E6"),
("Day 1", "All Day 1", "Final", "'Day 1'!D7", "'Day 1'!E7"),
("Day 2", "Part 4,ETC,Vit", "Round 1", "'Day 2'!D5", "'Day 2'!E5"),
("Day 2", "Part 4,ETC,Vit", "Round 2", "'Day 2'!D6", "'Day 2'!E6"),
("Day 2", "All Day 2", "Final", "'Day 2'!D7", "'Day 2'!E7"),
("Day 3", "Graph,Clin,Gen", "Round 1", "'Day 3'!D5", "'Day 3'!E5"),
("Day 3", "All Topics", "Grand Mix","'Day 3'!D6", "'Day 3'!E6"),
("Day 3", "All Topics", "Final", "'Day 3'!D7", "'Day 3'!E7"),
]
row_fills = [LIGHT_BLUE, LIGHT_BLUE, LIGHT_ORANGE,
LIGHT_GREEN, LIGHT_GREEN, LIGHT_ORANGE,
LIGHT_BLUE, LIGHT_BLUE, LIGHT_ORANGE]
for i, (day, topic, rnd, tot_ref, cor_ref) in enumerate(summary_rows):
r = 13 + i
fill_c = row_fills[i]
ws1[f"B{r}"].value = day
ws1[f"C{r}"].value = topic
ws1[f"D{r}"].value = rnd
ws1[f"E{r}"].value = f"={tot_ref}"
ws1[f"F{r}"].value = f"={cor_ref}"
ws1[f"G{r}"].value = f"=IFERROR(IF(E{r}=0,\"\",F{r}/E{r}),\"\")"
ws1[f"H{r}"].value = f'=IFERROR(IF(E{r}=0,"—",IF(G{r}>=0.7,"✅ Good",IF(G{r}>=0.5,"⚠ Average","❌ Revise"))),"—")'
for col in ["B","C","D","E","F"]:
ws1[f"{col}{r}"].font = font(size=10)
ws1[f"{col}{r}"].fill = hfill(fill_c)
ws1[f"{col}{r}"].alignment = center()
ws1[f"{col}{r}"].border = border()
ws1[f"G{r}"].number_format = "0.0%"
ws1[f"G{r}"].font = font(bold=True, size=10)
ws1[f"G{r}"].fill = hfill(fill_c)
ws1[f"G{r}"].alignment = center()
ws1[f"G{r}"].border = border()
ws1[f"H{r}"].font = font(bold=True, size=10)
ws1[f"H{r}"].fill = hfill(fill_c)
ws1[f"H{r}"].alignment = center()
ws1[f"H{r}"].border = border()
# Conditional formatting for Score % column
from openpyxl.formatting.rule import CellIsRule
score_range = f"G13:G21"
ws1.conditional_formatting.add(score_range,
CellIsRule(operator="greaterThanOrEqual", formula=["0.7"],
fill=PatternFill("solid", fgColor="D5F5E3"),
font=Font(color="1E8449", bold=True, name="Arial")))
ws1.conditional_formatting.add(score_range,
CellIsRule(operator="between", formula=["0.5","0.699"],
fill=PatternFill("solid", fgColor="FDEBD0"),
font=Font(color="E67E22", bold=True, name="Arial")))
ws1.conditional_formatting.add(score_range,
CellIsRule(operator="lessThan", formula=["0.5"],
fill=PatternFill("solid", fgColor="FADBD8"),
font=Font(color="C0392B", bold=True, name="Arial")))
# ── Overall Average ──
ws1.merge_cells("B23:F23")
ws1["B23"].value = "OVERALL AVERAGE SCORE (all sessions)"
ws1["B23"].font = font(bold=True, color=WHITE, size=11)
ws1["B23"].fill = hfill(DARK_BLUE)
ws1["B23"].alignment = center()
ws1["B23"].border = border()
ws1["G23"].value = "=IFERROR(AVERAGEIF(E13:E21,\">0\",G13:G21),\"\")"
ws1["G23"].number_format = "0.0%"
ws1["G23"].font = font(bold=True, size=12, color="000000")
ws1["G23"].fill = hfill(YELLOW)
ws1["G23"].alignment = center()
ws1["G23"].border = border()
ws1["H23"].value = '=IFERROR(IF(G23>=0.7,"✅ On Track",IF(G23>=0.5,"⚠ Need More Practice","❌ Revise All")),"Fill Data")'
ws1["H23"].font = font(bold=True, size=11)
ws1["H23"].fill = hfill(YELLOW)
ws1["H23"].alignment = center()
ws1["H23"].border = border()
# ── Legend ──
ws1.merge_cells("B25:H25")
ws1["B25"].value = "LEGEND"
ws1["B25"].font = font(bold=True, color=WHITE, size=10)
ws1["B25"].fill = hfill(DARK_GREY)
ws1["B25"].alignment = center()
legend_items = [
("B26", "✅ Good", LIGHT_GREEN, GREEN),
("D26", "⚠ Average", LIGHT_ORANGE, ORANGE),
("F26", "❌ Revise", LIGHT_RED, RED),
]
for cell, txt, bg, fg in legend_items:
ws1[cell].value = txt
ws1[cell].font = Font(bold=True, color=fg, size=11, name="Arial")
ws1[cell].fill = hfill(bg)
ws1[cell].alignment = center()
ws1[cell].border = border()
ws1["C26"].value = "Score ≥ 70%"
ws1["C26"].font = font(size=10)
ws1["C26"].fill = hfill(LIGHT_GREEN)
ws1["C26"].alignment = center()
ws1["C26"].border = border()
ws1["E26"].value = "Score 50–69%"
ws1["E26"].font = font(size=10)
ws1["E26"].fill = hfill(LIGHT_ORANGE)
ws1["E26"].alignment = center()
ws1["E26"].border = border()
ws1["G26"].value = "Score < 50%"
ws1["G26"].value = "Score < 50%"
ws1["G26"].font = font(size=10)
ws1["G26"].fill = hfill(LIGHT_RED)
ws1["G26"].alignment = center()
ws1["G26"].border = border()
ws1.merge_cells("G26:H26")
# ══════════════════════════════════════════════════════════════════
# HELPER: Build a Day Sheet
# ══════════════════════════════════════════════════════════════════
def build_day_sheet(wb, sheet_name, day_num, date_str, sessions):
"""
sessions: list of (session_label, topic, target_qs)
"""
ws = wb.create_sheet(title=sheet_name)
col_widths = [3, 26, 20, 14, 14, 14, 22, 5]
for i, w in enumerate(col_widths, 1):
ws.column_dimensions[get_column_letter(i)].width = w
for r in range(1, 50):
ws.row_dimensions[r].height = 20
ws.row_dimensions[2].height = 34
# Title
ws.merge_cells("B2:G2")
c = ws["B2"]
c.value = f"DAY {day_num} — MCQ LOG | {date_str}"
c.font = Font(bold=True, color=WHITE, size=16, name="Arial")
c.fill = hfill(DARK_BLUE)
c.alignment = center()
ws.merge_cells("B3:G3")
c = ws["B3"]
c.value = "Enter your scores below after each MCQ session. Score % is calculated automatically."
c.font = font(italic=True, color=DARK_GREY, size=10)
c.fill = hfill(LIGHT_BLUE)
c.alignment = center()
# Table header
headers = ["Session", "Topics Covered", "Round", "Total Qs", "Correct", "Score %", "Notes / Weak Areas"]
cols = ["B", "C", "D", "E", "F", "G", "H"] # H used as notes
# Adjust: use cols B-H (7 cols)
# Redefine
hcols = ["B","C","D","E","F","G","H"]
for h, col in zip(headers, hcols):
c = ws[f"{col}4"]
c.value = h
c.font = font(bold=True, color=WHITE, size=10)
c.fill = hfill(MED_BLUE)
c.alignment = center()
c.border = border()
ws.column_dimensions["H"].width = 30
# Session rows
fill_cycle = [LIGHT_BLUE, LIGHT_GREEN, LIGHT_ORANGE]
for i, (sess, topic, target) in enumerate(sessions):
r = 5 + i
fc = fill_cycle[i % 3]
ws[f"B{r}"].value = sess
ws[f"C{r}"].value = topic
ws[f"D{r}"].value = f"Round {i+1}" if i < len(sessions)-1 else "Final"
ws[f"E{r}"].value = target # pre-filled target, user can change
ws[f"F{r}"].value = "" # user fills correct answers
ws[f"G{r}"].value = f'=IFERROR(IF(E{r}=0,"",F{r}/E{r}),"")'
ws[f"G{r}"].number_format = "0.0%"
ws[f"H{r}"].value = "" # notes
for col in ["B","C","D"]:
ws[f"{col}{r}"].font = font(size=10)
ws[f"{col}{r}"].fill = hfill(fc)
ws[f"{col}{r}"].alignment = center()
ws[f"{col}{r}"].border = border()
# E and F - user input cells (blue text = input)
for col in ["E","F"]:
ws[f"{col}{r}"].font = Font(bold=True, color="0000FF", size=11, name="Arial")
ws[f"{col}{r}"].fill = hfill(YELLOW)
ws[f"{col}{r}"].alignment = center()
ws[f"{col}{r}"].border = border()
ws[f"G{r}"].font = font(bold=True, size=11)
ws[f"G{r}"].fill = hfill(fc)
ws[f"G{r}"].alignment = center()
ws[f"G{r}"].border = border()
ws[f"H{r}"].font = font(size=10, italic=True)
ws[f"H{r}"].fill = hfill(LIGHT_GREY)
ws[f"H{r}"].alignment = left()
ws[f"H{r}"].border = border()
# Conditional formatting on Score %
score_r_start = 5
score_r_end = 5 + len(sessions) - 1
score_rng = f"G{score_r_start}:G{score_r_end}"
ws.conditional_formatting.add(score_rng,
CellIsRule(operator="greaterThanOrEqual", formula=["0.7"],
fill=PatternFill("solid", fgColor="D5F5E3"),
font=Font(color="1E8449", bold=True, name="Arial")))
ws.conditional_formatting.add(score_rng,
CellIsRule(operator="between", formula=["0.5","0.699"],
fill=PatternFill("solid", fgColor="FDEBD0"),
font=Font(color="E67E22", bold=True, name="Arial")))
ws.conditional_formatting.add(score_rng,
CellIsRule(operator="lessThan", formula=["0.5"],
fill=PatternFill("solid", fgColor="FADBD8"),
font=Font(color="C0392B", bold=True, name="Arial")))
# Day Summary
sum_r = score_r_end + 2
ws.merge_cells(f"B{sum_r}:E{sum_r}")
ws[f"B{sum_r}"].value = f"DAY {day_num} SUMMARY"
ws[f"B{sum_r}"].font = font(bold=True, color=WHITE, size=11)
ws[f"B{sum_r}"].fill = hfill(DARK_BLUE)
ws[f"B{sum_r}"].alignment = center()
ws[f"B{sum_r}"].border = border()
ws[f"F{sum_r}"].value = "Day Average:"
ws[f"F{sum_r}"].font = font(bold=True, size=11)
ws[f"F{sum_r}"].fill = hfill(DARK_BLUE)
ws[f"F{sum_r}"].alignment = center()
ws[f"F{sum_r}"].border = border()
ws[f"F{sum_r}"].font = Font(bold=True, color=WHITE, size=11, name="Arial")
ws[f"G{sum_r}"].value = f"=IFERROR(AVERAGEIF(E{score_r_start}:E{score_r_end},\">0\",G{score_r_start}:G{score_r_end}),\"\")"
ws[f"G{sum_r}"].number_format = "0.0%"
ws[f"G{sum_r}"].font = Font(bold=True, size=13, color="000000", name="Arial")
ws[f"G{sum_r}"].fill = hfill(YELLOW)
ws[f"G{sum_r}"].alignment = center()
ws[f"G{sum_r}"].border = border()
# Input note
note_r = sum_r + 2
ws.merge_cells(f"B{note_r}:H{note_r}")
ws[f"B{note_r}"].value = "💡 Yellow cells = Enter your data. Blue text = Input fields. Score % is auto-calculated."
ws[f"B{note_r}"].font = font(italic=True, color=DARK_GREY, size=10)
ws[f"B{note_r}"].fill = hfill(YELLOW)
ws[f"B{note_r}"].alignment = center()
return ws
# ── Day 1 ──
build_day_sheet(wb, "Day 1", 1, "Monday, 21 Jul 2026", [
("Morning Session", "Rapid Rev Part 1, 2, 3", 30),
("Afternoon Session", "Rapid Rev Part 1, 2, 3", 30),
("Night Final Round", "All Day 1 Topics", 30),
])
# ── Day 2 ──
build_day_sheet(wb, "Day 2", 2, "Tuesday, 22 Jul 2026", [
("Morning Session", "Rapid Rev Part 4, ETC & Protein, Vitamins", 30),
("Afternoon Session", "Rapid Rev Part 4, ETC & Protein, Vitamins", 30),
("Night Final Round", "All Day 2 Topics", 30),
])
# ── Day 3 ──
build_day_sheet(wb, "Day 3", 3, "Wednesday, 23 Jul 2026", [
("Morning Session", "Graph, Clinical Biochemistry, Genetics", 30),
("Grand Mix Session", "All 9 Topics Mixed", 50),
("Night Final Round", "Weak Areas + Full Revision", 30),
])
# ══════════════════════════════════════════════════════════════════
# SHEET 5 - PROGRESS CHART
# ══════════════════════════════════════════════════════════════════
ws_chart = wb.create_sheet(title="Progress Chart")
ws_chart.column_dimensions["A"].width = 3
ws_chart.column_dimensions["B"].width = 30
ws_chart.column_dimensions["C"].width = 16
ws_chart.column_dimensions["D"].width = 16
ws_chart.merge_cells("B2:D2")
ws_chart["B2"].value = "SCORE PROGRESS — ALL SESSIONS"
ws_chart["B2"].font = Font(bold=True, color=WHITE, size=14, name="Arial")
ws_chart["B2"].fill = hfill(DARK_BLUE)
ws_chart["B2"].alignment = center()
# Data for chart - pulling from day sheets
chart_headers = ["Session", "Score %", "Target (70%)"]
for i, h in enumerate(chart_headers):
col = get_column_letter(2 + i)
ws_chart[f"{col}4"].value = h
ws_chart[f"{col}4"].font = font(bold=True, color=WHITE, size=10)
ws_chart[f"{col}4"].fill = hfill(MED_BLUE)
ws_chart[f"{col}4"].alignment = center()
ws_chart[f"{col}4"].border = border()
sessions_for_chart = [
("Day 1 - Morning", "='Day 1'!G5"),
("Day 1 - Afternoon", "='Day 1'!G6"),
("Day 1 - Final", "='Day 1'!G7"),
("Day 2 - Morning", "='Day 2'!G5"),
("Day 2 - Afternoon", "='Day 2'!G6"),
("Day 2 - Final", "='Day 2'!G7"),
("Day 3 - Morning", "='Day 3'!G5"),
("Day 3 - Grand Mix", "='Day 3'!G6"),
("Day 3 - Final", "='Day 3'!G7"),
]
for i, (sess, score_formula) in enumerate(sessions_for_chart):
r = 5 + i
ws_chart[f"B{r}"].value = sess
ws_chart[f"B{r}"].font = font(size=10)
ws_chart[f"B{r}"].fill = hfill(LIGHT_GREY)
ws_chart[f"B{r}"].alignment = center()
ws_chart[f"B{r}"].border = border()
ws_chart[f"C{r}"].value = score_formula
ws_chart[f"C{r}"].number_format = "0.0%"
ws_chart[f"C{r}"].font = font(bold=True, size=11)
ws_chart[f"C{r}"].fill = hfill(YELLOW)
ws_chart[f"C{r}"].alignment = center()
ws_chart[f"C{r}"].border = border()
ws_chart[f"D{r}"].value = 0.70
ws_chart[f"D{r}"].number_format = "0.0%"
ws_chart[f"D{r}"].font = font(size=10, color=GREEN)
ws_chart[f"D{r}"].fill = hfill(LIGHT_GREEN)
ws_chart[f"D{r}"].alignment = center()
ws_chart[f"D{r}"].border = border()
# Build Line Chart
chart = LineChart()
chart.title = "MCQ Score Progress vs 70% Target"
chart.style = 10
chart.y_axis.title = "Score %"
chart.x_axis.title = "Session"
chart.y_axis.numFmt = "0%"
chart.y_axis.scaling.min = 0
chart.y_axis.scaling.max = 1
chart.width = 22
chart.height = 14
data_scores = Reference(ws_chart, min_col=3, min_row=4, max_row=13)
data_target = Reference(ws_chart, min_col=4, min_row=4, max_row=13)
cats = Reference(ws_chart, min_col=2, min_row=5, max_row=13)
chart.add_data(data_scores, titles_from_data=True)
chart.add_data(data_target, titles_from_data=True)
chart.set_categories(cats)
# Style the series
chart.series[0].graphicalProperties.line.solidFill = "2E75B6"
chart.series[0].graphicalProperties.line.width = 25000
chart.series[1].graphicalProperties.line.solidFill = "1E8449"
chart.series[1].graphicalProperties.line.dashDot = "dash"
chart.series[1].graphicalProperties.line.width = 18000
ws_chart.add_chart(chart, "B16")
# ── Freeze panes on all sheets ──
for sheet in [wb["Dashboard"], wb["Day 1"], wb["Day 2"], wb["Day 3"], wb["Progress Chart"]]:
sheet.freeze_panes = "B5"
# Save
path = "/tmp/workspace/biochem-tracker/Biochemistry_MCQ_Tracker.xlsx"
wb.save(path)
print(f"Saved: {path}")
python /tmp/workspace/biochem-tracker/create_tracker.py
Biochemistry MCQ Tracker
Spreadsheet · XLSX
Give me a pdf
~/biochem-tracker/create_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.platypus import (
SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, HRFlowable, PageBreak
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.platypus import KeepTogether
# ── Colors ──
DARK_BLUE = colors.HexColor("#1F3864")
MED_BLUE = colors.HexColor("#2E75B6")
LIGHT_BLUE = colors.HexColor("#D6E4F0")
GREEN = colors.HexColor("#1E8449")
LIGHT_GREEN = colors.HexColor("#D5F5E3")
ORANGE = colors.HexColor("#E67E22")
LIGHT_ORANGE= colors.HexColor("#FDEBD0")
RED = colors.HexColor("#C0392B")
LIGHT_RED = colors.HexColor("#FADBD8")
YELLOW = colors.HexColor("#FFF9C4")
WHITE = colors.white
LIGHT_GREY = colors.HexColor("#F2F2F2")
DARK_GREY = colors.HexColor("#595959")
path = "/tmp/workspace/biochem-tracker/Biochemistry_Study_Plan.pdf"
doc = SimpleDocTemplate(
path, pagesize=A4,
rightMargin=15*mm, leftMargin=15*mm,
topMargin=15*mm, bottomMargin=15*mm
)
styles = getSampleStyleSheet()
# Custom styles
title_style = ParagraphStyle("title", fontSize=20, textColor=WHITE,
alignment=TA_CENTER, fontName="Helvetica-Bold", spaceAfter=2)
sub_style = ParagraphStyle("sub", fontSize=10, textColor=DARK_GREY,
alignment=TA_CENTER, fontName="Helvetica-Oblique", spaceAfter=6)
section_style = ParagraphStyle("section", fontSize=13, textColor=WHITE,
alignment=TA_CENTER, fontName="Helvetica-Bold", spaceAfter=4)
body_style = ParagraphStyle("body", fontSize=9, textColor=colors.black,
alignment=TA_LEFT, fontName="Helvetica", spaceAfter=3, leading=13)
note_style = ParagraphStyle("note", fontSize=8, textColor=DARK_GREY,
alignment=TA_CENTER, fontName="Helvetica-Oblique")
def section_header(text, bg=DARK_BLUE):
data = [[Paragraph(text, ParagraphStyle("sh", fontSize=12, textColor=WHITE,
alignment=TA_CENTER, fontName="Helvetica-Bold"))]]
t = Table(data, colWidths=[180*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 8),
]))
return t
def day_header(day, date, bg=DARK_BLUE):
data = [[Paragraph(f"<b>{day}</b>", ParagraphStyle("dh", fontSize=14,
textColor=WHITE, alignment=TA_LEFT, fontName="Helvetica-Bold")),
Paragraph(date, ParagraphStyle("dd", fontSize=11,
textColor=LIGHT_BLUE, alignment=TA_RIGHT, fontName="Helvetica-Oblique"))]]
t = Table(data, colWidths=[100*mm, 80*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0),(-1,-1), 8),
("BOTTOMPADDING", (0,0),(-1,-1), 8),
("LEFTPADDING", (0,0),(-1,-1), 10),
("RIGHTPADDING", (0,0),(-1,-1), 10),
]))
return t
story = []
# ══════════════════════════════════════════
# PAGE 1: COVER + OVERVIEW
# ══════════════════════════════════════════
# Cover banner
cover_data = [[Paragraph("BIOCHEMISTRY RAPID REVISION", ParagraphStyle("c1",
fontSize=22, textColor=WHITE, alignment=TA_CENTER, fontName="Helvetica-Bold")),],
[Paragraph("3-Day Study Plan & MCQ Tracker", ParagraphStyle("c2",
fontSize=14, textColor=LIGHT_BLUE, alignment=TA_CENTER, fontName="Helvetica-Oblique")),],
[Paragraph("Rapid Revision V XI | July 20–23, 2026", ParagraphStyle("c3",
fontSize=11, textColor=YELLOW, alignment=TA_CENTER, fontName="Helvetica")),]]
cover_table = Table(cover_data, colWidths=[180*mm])
cover_table.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), DARK_BLUE),
("TOPPADDING", (0,0),(-1,-1), 10),
("BOTTOMPADDING", (0,0),(-1,-1), 10),
("LEFTPADDING", (0,0),(-1,-1), 8),
("ROUNDEDCORNERS",(0,0),(-1,-1),5),
]))
story.append(cover_table)
story.append(Spacer(1, 6*mm))
# Topic List
story.append(section_header("TOPICS & CONTENT HOURS", MED_BLUE))
story.append(Spacer(1, 2*mm))
topic_headers = [["#", "Topic", "Duration"]]
topics = [
["19", "Rapid Revision Part 1", "1 hr 29 min"],
["20", "Rapid Revision Part 2", "1 hr 07 min"],
["21", "Rapid Revision Part 3", "2 hr 10 min"],
["22", "Rapid Revision Part 4", "1 hr 51 min"],
["23", "ETC and Protein", "1 hr 56 min"],
["24", "Vitamins", "1 hr 50 min"],
["25", "Clinical Biochemistry", "2 hr 00 min"],
["26", "Genetics", "2 hr 43 min"],
["+", "Graph", "1 hr 00 min"],
["", "TOTAL", "16 hr 06 min"],
]
topic_data = topic_headers + topics
t = Table(topic_data, colWidths=[15*mm, 120*mm, 45*mm])
ts = TableStyle([
("BACKGROUND", (0,0),(-1,0), MED_BLUE),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 9),
("ALIGN", (0,0),(-1,-1), "CENTER"),
("ALIGN", (1,0),(1,-1), "LEFT"),
("GRID", (0,0),(-1,-1), 0.4, colors.grey),
("ROWBACKGROUNDS",(0,1),(-1,-2), [LIGHT_GREY, WHITE]),
("BACKGROUND", (0,-1),(-1,-1), DARK_BLUE),
("TEXTCOLOR", (0,-1),(-1,-1), WHITE),
("FONTNAME", (0,-1),(-1,-1), "Helvetica-Bold"),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (1,0),(1,-1), 6),
])
t.setStyle(ts)
story.append(t)
story.append(Spacer(1, 4*mm))
# Summary box
story.append(section_header("3-DAY OVERVIEW", MED_BLUE))
story.append(Spacer(1, 2*mm))
overview_data = [
["Day", "Date", "Content", "Total Study", "Focus"],
["Day 1", "Monday, 21 Jul", "4 hr 46 min", "~7 hrs", "Rapid Rev Parts 1, 2, 3"],
["Day 2", "Tuesday, 22 Jul", "5 hr 37 min", "~8 hrs", "Part 4, ETC & Protein, Vitamins"],
["Day 3", "Wednesday, 23 Jul","5 hr 43 min", "~10 hrs", "Graph, Clinical Biochem, Genetics + Full Revision"],
["TOTAL", "", "16 hr 06 min","~25 hrs", "All 9 topics + MCQs + Revision"],
]
ov = Table(overview_data, colWidths=[18*mm, 32*mm, 28*mm, 26*mm, 76*mm])
ov.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), MED_BLUE),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ALIGN", (0,0),(-1,-1), "CENTER"),
("ALIGN", (4,0),(4,-1), "LEFT"),
("GRID", (0,0),(-1,-1), 0.4, colors.grey),
("ROWBACKGROUNDS",(0,1),(-1,-2), [LIGHT_BLUE, WHITE]),
("BACKGROUND", (0,-1),(-1,-1), DARK_BLUE),
("TEXTCOLOR", (0,-1),(-1,-1), WHITE),
("FONTNAME", (0,-1),(-1,-1), "Helvetica-Bold"),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (4,0),(4,-1), 5),
]))
story.append(ov)
story.append(PageBreak())
# ══════════════════════════════════════════
# PAGE 2: TIMETABLE - DAY 1
# ══════════════════════════════════════════
story.append(day_header("DAY 1 - TIMETABLE", "Monday, 21 July 2026"))
story.append(Spacer(1, 3*mm))
day1_rows = [
["Time", "Activity", "Duration", "Type"],
["6:00 AM", "Wake up + freshen up + breakfast", "30 min", "Break"],
["6:30 AM", "Rapid Revision Part 1", "1 hr 29 min", "Content"],
["8:00 AM", "Short break + snack", "15 min", "Break"],
["8:15 AM", "Rapid Revision Part 2", "1 hr 07 min", "Content"],
["9:22 AM", "Short break", "15 min", "Break"],
["9:37 AM", "Rapid Revision Part 3 - First Half", "1 hr", "Content"],
["10:37 AM","Short break", "10 min", "Break"],
["10:47 AM","Rapid Revision Part 3 - Second Half", "1 hr 10 min", "Content"],
["11:57 AM","Lunch break", "45 min", "Break"],
["12:42 PM","Day 1 Notes Revision", "1 hr", "Revision"],
["1:42 PM", "MCQ Practice - Day 1 topics", "1 hr", "MCQ"],
["2:42 PM", "Short break + tea", "20 min", "Break"],
["3:02 PM", "Weak point re-study", "1 hr", "Revision"],
["4:02 PM", "Second round MCQs - Day 1", "45 min", "MCQ"],
["4:47 PM", "Evening break + walk", "45 min", "Break"],
["5:32 PM", "Flash revision - Day 1 key points", "1 hr", "Revision"],
["6:32 PM", "Dinner break", "45 min", "Break"],
["7:17 PM", "Difficult concepts deep dive", "1 hr 30 min", "Revision"],
["8:47 PM", "Short break", "15 min", "Break"],
["9:02 PM", "Day 1 Final MCQ round (30 Qs timed)", "45 min", "MCQ"],
["9:47 PM", "Write key formulas / mnemonics", "30 min", "Revision"],
["10:17 PM","Light review / relax reading", "30 min", "Revision"],
["11:00 PM","SLEEP", "-", "Rest"],
]
def type_color(t):
if t == "Content": return LIGHT_BLUE
if t == "MCQ": return LIGHT_GREEN
if t == "Revision":return LIGHT_ORANGE
if t == "Break": return LIGHT_GREY
if t == "Rest": return LIGHT_RED
return WHITE
def build_day_table(rows):
table_data = []
for r in rows:
table_data.append([Paragraph(str(c), ParagraphStyle("tc", fontSize=8,
fontName="Helvetica" if r[0]!="Time" else "Helvetica-Bold",
textColor=WHITE if r[0]=="Time" else colors.black,
alignment=TA_CENTER)) for c in r])
t = Table(table_data, colWidths=[22*mm, 90*mm, 25*mm, 23*mm])
style_cmds = [
("BACKGROUND", (0,0),(-1,0), MED_BLUE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("GRID", (0,0),(-1,-1), 0.3, colors.grey),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]
for i, row in enumerate(rows[1:], 1):
bg = type_color(row[3])
style_cmds.append(("BACKGROUND", (0,i),(-1,i), bg))
if row[3] in ("MCQ", "Content"):
style_cmds.append(("FONTNAME", (1,i),(1,i), "Helvetica-Bold"))
t.setStyle(TableStyle(style_cmds))
return t
story.append(build_day_table(day1_rows))
story.append(Spacer(1, 3*mm))
# Legend
leg_data = [["Content (Blue)", "MCQ Practice (Green)", "Revision (Orange)", "Break/Rest (Grey/Red)"]]
leg = Table(leg_data, colWidths=[45*mm]*4)
leg.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), LIGHT_BLUE),
("BACKGROUND", (1,0),(1,0), LIGHT_GREEN),
("BACKGROUND", (2,0),(2,0), LIGHT_ORANGE),
("BACKGROUND", (3,0),(3,0), LIGHT_GREY),
("FONTSIZE", (0,0),(-1,-1), 8),
("ALIGN", (0,0),(-1,-1), "CENTER"),
("GRID", (0,0),(-1,-1), 0.3, colors.grey),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
]))
story.append(leg)
story.append(PageBreak())
# ══════════════════════════════════════════
# PAGE 3: TIMETABLE - DAY 2
# ══════════════════════════════════════════
story.append(day_header("DAY 2 - TIMETABLE", "Tuesday, 22 July 2026"))
story.append(Spacer(1, 3*mm))
day2_rows = [
["Time", "Activity", "Duration", "Type"],
["6:00 AM", "Wake up + freshen up + breakfast", "30 min", "Break"],
["6:30 AM", "Day 1 Quick Recap (notes only)", "20 min", "Revision"],
["6:50 AM", "Rapid Revision Part 4", "1 hr 51 min", "Content"],
["8:41 AM", "Short break + snack", "20 min", "Break"],
["9:01 AM", "ETC and Protein", "1 hr 56 min", "Content"],
["10:57 AM","Short break", "15 min", "Break"],
["11:12 AM","Vitamins", "1 hr 50 min", "Content"],
["1:02 PM", "Lunch break", "45 min", "Break"],
["1:47 PM", "Day 2 Notes Revision", "1 hr", "Revision"],
["2:47 PM", "MCQ Practice - Day 2 topics", "1 hr", "MCQ"],
["3:47 PM", "Short break + tea", "20 min", "Break"],
["4:07 PM", "Weak point re-study (ETC, Protein, Vitamins)", "1 hr", "Revision"],
["5:07 PM", "Evening break + walk", "45 min", "Break"],
["5:52 PM", "Second round MCQs - Day 2", "45 min", "MCQ"],
["6:37 PM", "Combined revision - Day 1 + Day 2", "1 hr", "Revision"],
["7:37 PM", "Dinner break", "45 min", "Break"],
["8:22 PM", "Vitamins special focus (exam high-yield)", "1 hr", "Revision"],
["9:22 PM", "Short break", "15 min", "Break"],
["9:37 PM", "Day 2 Final MCQ round (30 Qs timed)", "45 min", "MCQ"],
["10:22 PM","Write key mnemonics - Day 2", "30 min", "Revision"],
["10:52 PM","Wind down", "8 min", "Break"],
["11:00 PM","SLEEP", "-", "Rest"],
]
story.append(build_day_table(day2_rows))
story.append(Spacer(1, 3*mm))
story.append(leg)
story.append(PageBreak())
# ══════════════════════════════════════════
# PAGE 4: TIMETABLE - DAY 3
# ══════════════════════════════════════════
story.append(day_header("DAY 3 - TIMETABLE", "Wednesday, 23 July 2026"))
story.append(Spacer(1, 3*mm))
day3_rows = [
["Time", "Activity", "Duration", "Type"],
["6:00 AM", "Wake up + freshen up + breakfast", "30 min", "Break"],
["6:30 AM", "Day 1 + Day 2 Combined Recap (notes only)", "30 min", "Revision"],
["7:00 AM", "Graph", "1 hr", "Content"],
["8:00 AM", "Short break + snack", "20 min", "Break"],
["8:20 AM", "Clinical Biochemistry", "2 hr 00 min", "Content"],
["10:20 AM","Short break", "20 min", "Break"],
["10:40 AM","Genetics", "2 hr 43 min", "Content"],
["1:23 PM", "Lunch break", "45 min", "Break"],
["2:08 PM", "MCQ Practice - Day 3 topics", "1 hr", "MCQ"],
["3:08 PM", "Short break + tea", "20 min", "Break"],
["3:28 PM", "FULL REVISION - All 9 topics (notes only)", "2 hrs", "Revision"],
["5:28 PM", "Evening break + walk", "45 min", "Break"],
["6:13 PM", "Grand Mixed MCQ Session (50 Qs timed)", "1 hr 15 min", "MCQ"],
["7:28 PM", "Dinner break", "45 min", "Break"],
["8:13 PM", "Weak areas targeted re-study (from errors)", "1 hr 15 min", "Revision"],
["9:28 PM", "Short break", "15 min", "Break"],
["9:43 PM", "Final Flash Revision - all key points", "1 hr", "Revision"],
["10:43 PM","Wrap up - write carry-forward points", "15 min", "Revision"],
["11:00 PM","ALL DONE - SLEEP", "-", "Rest"],
]
story.append(build_day_table(day3_rows))
story.append(Spacer(1, 3*mm))
story.append(leg)
story.append(PageBreak())
# ══════════════════════════════════════════
# PAGE 5: CHECKLIST
# ══════════════════════════════════════════
story.append(section_header("DAILY COMPLETION CHECKLIST", DARK_BLUE))
story.append(Spacer(1, 4*mm))
def checklist_section(day_label, date, items_content, items_practice, items_score, bg_light):
block = []
block.append(day_header(day_label, date, MED_BLUE))
block.append(Spacer(1, 2*mm))
def check_table(title, items, bg):
rows = [[Paragraph(f"<b>{title}</b>", ParagraphStyle("ct", fontSize=9,
textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_LEFT))]]
for item in items:
rows.append([Paragraph(f"☐ {item}", ParagraphStyle("ci", fontSize=8,
textColor=colors.black, fontName="Helvetica", alignment=TA_LEFT,
leftIndent=6))])
t = Table(rows, colWidths=[180*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), bg),
("BACKGROUND", (0,1),(-1,-1), WHITE),
("GRID", (0,0),(-1,-1), 0.3, colors.grey),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 8),
]))
return t
block.append(check_table("CONTENT WATCHED", items_content, MED_BLUE))
block.append(Spacer(1, 2*mm))
block.append(check_table("PRACTICE & REVISION", items_practice, GREEN))
block.append(Spacer(1, 2*mm))
block.append(check_table("SCORE CHECK", items_score, ORANGE))
block.append(Spacer(1, 4*mm))
return block
# Day 1 Checklist
d1_content = [
"Rapid Revision Part 1 (1 hr 29 min)",
"Rapid Revision Part 2 (1 hr 07 min)",
"Rapid Revision Part 3 - First Half (1 hr)",
"Rapid Revision Part 3 - Second Half (1 hr 10 min)",
]
d1_practice = [
"Day 1 Notes Revision done",
"MCQ Round 1 - Parts 1, 2, 3 completed",
"Weak points re-studied",
"MCQ Round 2 completed",
"Flash revision of key points done",
"Final MCQ round (30 Qs timed) done",
"Key formulas / mnemonics written down",
]
d1_score = [
"MCQ accuracy above 60%? (if not, flag topics for Day 3 revision)",
]
story.extend(checklist_section("DAY 1 CHECKLIST", "Monday, 21 July 2026",
d1_content, d1_practice, d1_score, LIGHT_BLUE))
story.append(PageBreak())
# Day 2 Checklist
d2_content = [
"Day 1 recap done (20 min)",
"Rapid Revision Part 4 (1 hr 51 min)",
"ETC and Protein (1 hr 56 min)",
"Vitamins (1 hr 50 min)",
]
d2_practice = [
"Day 2 Notes Revision done",
"MCQ Round 1 - Parts 4, ETC, Vitamins completed",
"Weak points re-studied",
"MCQ Round 2 completed",
"Combined Day 1 + Day 2 revision done",
"Vitamins deep focus done",
"Final MCQ round (30 Qs timed) done",
"Key mnemonics written down",
]
d2_score = [
"MCQ accuracy above 65%?",
"Vitamins deficiency list memorized?",
"ETC complexes sequence memorized?",
]
story.extend(checklist_section("DAY 2 CHECKLIST", "Tuesday, 22 July 2026",
d2_content, d2_practice, d2_score, LIGHT_GREEN))
story.append(Spacer(1, 2*mm))
# Day 3 Checklist
d3_content = [
"Day 1 + Day 2 combined recap done (30 min)",
"Graph (1 hr)",
"Clinical Biochemistry (2 hr 00 min)",
"Genetics (2 hr 43 min)",
]
d3_practice = [
"MCQ Practice - Day 3 topics done",
"Full revision of ALL 9 topics done (no video, notes only)",
"Grand Mixed MCQ Session (50 Qs timed) done",
"Weak areas from MCQ errors re-studied",
"Final flash revision of all key points done",
"Carry-forward points written for future revision",
]
d3_score = [
"Grand MCQ accuracy above 70%?",
"Genetics key concepts clear? (mutations, inheritance, PCR)",
"Clinical Biochemistry lab values noted?",
]
story.extend(checklist_section("DAY 3 CHECKLIST", "Wednesday, 23 July 2026",
d3_content, d3_practice, d3_score, LIGHT_ORANGE))
story.append(PageBreak())
# ══════════════════════════════════════════
# PAGE 6: MCQ TRACKER TABLES
# ══════════════════════════════════════════
story.append(section_header("MCQ SCORE TRACKER — FILL IN DAILY", DARK_BLUE))
story.append(Spacer(1, 4*mm))
def mcq_tracker_table(day_label, date, sessions):
block = []
block.append(day_header(day_label, date, MED_BLUE))
block.append(Spacer(1, 2*mm))
rows = [["Session", "Topics", "Total Qs", "Correct", "Score %", "Notes / Weak Areas"]]
for sess, topic, target in sessions:
rows.append([sess, topic, str(target), "______", "______", "________________________"])
rows.append(["", "DAY AVERAGE", "", "", "______", ""])
t = Table(rows, colWidths=[28*mm, 55*mm, 18*mm, 18*mm, 18*mm, 43*mm])
style_cmds = [
("BACKGROUND", (0,0),(-1,0), MED_BLUE),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ALIGN", (0,0),(-1,-1), "CENTER"),
("ALIGN", (1,0),(1,-1), "LEFT"),
("ALIGN", (5,0),(5,-1), "LEFT"),
("GRID", (0,0),(-1,-1), 0.4, colors.grey),
("ROWBACKGROUNDS",(0,1),(-1,-2), [LIGHT_BLUE, WHITE]),
("BACKGROUND", (0,-1),(-1,-1), LIGHT_YELLOW if hasattr(colors,'lightyellow') else YELLOW),
("FONTNAME", (0,-1),(-1,-1), "Helvetica-Bold"),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (1,0),(1,-1), 5),
("LEFTPADDING", (5,0),(5,-1), 5),
]
t.setStyle(TableStyle(style_cmds))
block.append(t)
block.append(Spacer(1, 4*mm))
return block
story.extend(mcq_tracker_table("DAY 1 MCQ LOG", "Monday, 21 July 2026", [
("Morning Session", "Rapid Rev Part 1, 2, 3", 30),
("Afternoon Session", "Rapid Rev Part 1, 2, 3", 30),
("Night Final Round", "All Day 1 Topics", 30),
]))
story.extend(mcq_tracker_table("DAY 2 MCQ LOG", "Tuesday, 22 July 2026", [
("Morning Session", "Rapid Rev Part 4, ETC & Protein, Vitamins", 30),
("Afternoon Session", "Rapid Rev Part 4, ETC & Protein, Vitamins", 30),
("Night Final Round", "All Day 2 Topics", 30),
]))
story.extend(mcq_tracker_table("DAY 3 MCQ LOG", "Wednesday, 23 July 2026", [
("Morning Session", "Graph, Clinical Biochemistry, Genetics", 30),
("Grand Mix Session", "All 9 Topics Mixed", 50),
("Night Final Round", "Weak Areas + Full Revision", 30),
]))
# Final summary box
story.append(section_header("FINAL 3-DAY SUMMARY", DARK_BLUE))
story.append(Spacer(1, 2*mm))
final_rows = [
["", "Day 1", "Day 2", "Day 3", "OVERALL"],
["Total Content", "4 hr 46 min", "5 hr 37 min", "5 hr 43 min", "16 hr 06 min"],
["Total Study", "~7 hrs", "~8 hrs", "~10 hrs", "~25 hrs"],
["MCQ Sessions", "3 rounds", "3 rounds", "3 rounds", "9 sessions"],
["Day Avg Score", "______", "______", "______", "______"],
["Status", "☐ Done", "☐ Done", "☐ Done", "☐ Complete"],
]
ft = Table(final_rows, colWidths=[36*mm, 36*mm, 36*mm, 36*mm, 36*mm])
ft.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), MED_BLUE),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("BACKGROUND", (0,0),(0,-1), DARK_BLUE),
("TEXTCOLOR", (0,0),(0,-1), WHITE),
("FONTNAME", (0,0),(0,-1), "Helvetica-Bold"),
("BACKGROUND", (4,0),(4,-1), YELLOW),
("FONTNAME", (4,1),(4,-1), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 9),
("ALIGN", (0,0),(-1,-1), "CENTER"),
("GRID", (0,0),(-1,-1), 0.4, colors.grey),
("ROWBACKGROUNDS",(0,1),(-1,-1), [LIGHT_GREY, WHITE]),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
]))
story.append(ft)
story.append(Spacer(1, 4*mm))
# Footer tip
tip = Paragraph(
"<b>Key Rule:</b> Any missed item automatically moves to the next day's weak area slot. "
"Never carry forward incomplete videos. Finish the day's content no matter what!",
ParagraphStyle("tip", fontSize=8, textColor=DARK_GREY, alignment=TA_CENTER,
fontName="Helvetica-Oblique", borderColor=MED_BLUE,
borderWidth=0.5, borderPadding=6, backColor=LIGHT_BLUE)
)
story.append(tip)
# Build PDF
doc.build(story)
print(f"PDF saved: {path}")
python /tmp/workspace/biochem-tracker/create_pdf.py
~/biochem-tracker/create_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/biochem-tracker/create_pdf.py'
python /tmp/workspace/biochem-tracker/create_pdf.py
Biochemistry Study Plan
PDF Document · PDF
| Page | Content |
|---|---|
| Page 1 | Cover banner + Full topic list with hours + 3-Day overview summary |
| Page 2 | Day 1 complete timetable (6 AM - 11 PM) with color coding |
| Page 3 | Day 2 complete timetable (6 AM - 11 PM) with color coding |
| Page 4 | Day 3 complete timetable (6 AM - 11 PM) with color coding |
| Page 5 | Daily checklist for all 3 days (printable, tick boxes) |
| Page 6 | MCQ score log tables to fill in manually + final 3-day summary table |