Ras Pre time table

Asking for Preferences

Ras Pre time table Coching time 6:00 am to 1:00 pm

Asking for Preferences
Here is a complete daily timetable for RAS Prelims preparation with your coaching slot (6:00 AM - 1:00 PM) and self-study hours built around it.

📅 RAS Pre - Full Day Study Timetable

Coaching: 6:00 AM - 1:00 PM | Exam: 3-6 months away

⏰ Daily Schedule

TimeActivity
5:00 - 5:30 AMWake up, freshen up, light exercise/yoga
5:30 - 6:00 AMQuick revision of previous day's notes (30 min)
6:00 - 1:00 PM🏫 COACHING CLASSES
1:00 - 2:00 PMLunch + Rest (mandatory break)
2:00 - 4:00 PMSelf-Study - Revise today's coaching topics
4:00 - 4:15 PMShort break / tea
4:15 - 6:15 PMSelf-Study - Rajasthan GK / Current Affairs
6:15 - 7:00 PMEvening walk / relaxation
7:00 - 8:30 PMSelf-Study - Weak subject or Mock Practice
8:30 - 9:00 PMDinner
9:00 - 10:00 PMDaily Current Affairs (newspaper + notes)
10:00 - 10:30 PMQuick notes review + next day planning
10:30 PMSleep (minimum 7 hours)

📚 Subject-Wise Weekly Plan (Self-Study Hours)

DayMorning Revision (5:30-6:00)Afternoon (2-4 PM)Evening (4:15-6:15 PM)Night (7-8:30 PM)
MonHistory notesHistory (India)Rajasthan HistoryMock MCQs
TueGeography notesGeography (India)Rajasthan GeographyMap Practice
WedPolity notesIndian PolityRaj. Polity/AdminPYQ Practice
ThuEconomy notesIndian EconomyRaj. EconomyMock Test
FriScience notesGeneral ScienceEnvironmentWeak Subject
SatCurrent AffairsFull RevisionRajasthan GKWeekly Mock Test
SunRest/Light studyTest AnalysisCurrent AffairsRevision + Planning

📖 RAS Pre Syllabus Coverage Plan

High Priority Topics (spend more time):
  • Rajasthan History, Art & Culture
  • Rajasthan Geography
  • Indian Polity & Constitution
  • Rajasthan Economy & Current Issues
  • General Science (basic level)
Medium Priority:
  • Indian History (Freedom Struggle)
  • Indian & World Geography
  • Current Affairs (last 6 months)
Ongoing Daily:
  • Current Affairs - 30-45 min/day
  • Rajasthan GK - 30 min/day

📝 Weekly Mock Test Strategy

WeekActivity
Weeks 1-4Topic-wise MCQs (chapter-by-chapter)
Weeks 5-8Subject-wise full mock tests
Weeks 9-12Full-length RAS Pre mock tests (100 Q / 2 hrs)
Weeks 13-16PYQs + error analysis + rapid revision

✅ Key Tips

  1. Coaching topics same day - revise whatever was taught in class that afternoon (2-4 PM slot)
  2. Rajasthan GK daily - minimum 30 min every single day
  3. Current Affairs - read Rajasthan Patrika / Dainik Bhaskar daily
  4. Sunday mock test - treat it like a real exam, full 2 hours
  5. Notes in Hindi - if exam is in Hindi medium, make short notes in Hindi
  6. No new topics last 2 weeks - only revision and mocks in final stretch

Total Self-Study Hours/Day: ~5-6 hours (beyond coaching) Total Preparation: ~11-12 hours/day - ideal for 3-6 month target
This schedule is sustainable and covers all RAS Pre subjects systematically. Adjust the subject rotation based on what your coaching is covering each week.

Create an Excel timetable with reminder alerts

Reading File
Reading File
Running Command

mkdir -p /tmp/workspace/ras-timetable && ls /tmp/workspace/ras-timetable/

Writing File

~/ras-timetable/create_timetable.py

import openpyxl
from openpyxl import Workbook
from openpyxl.styles import (
    Font, PatternFill, Alignment, Border, Side, GradientFill
)
from openpyxl.utils import get_column_letter
from openpyxl.worksheet.datavalidation import DataValidation
from openpyxl.comments import Comment
import openpyxl.drawing.image

wb = Workbook()

# ─── COLOR PALETTE ──────────────────────────────────────────────
COACHING_BG   = "1F4E79"   # dark blue  – coaching block
COACHING_FG   = "FFFFFF"

STUDY_BG      = "E2EFDA"   # light green – self study
STUDY_FG      = "1E5631"

BREAK_BG      = "FFF2CC"   # yellow     – break / meals
BREAK_FG      = "7F6000"

SLEEP_BG      = "D9E1F2"   # light blue  – sleep
SLEEP_FG      = "1F4E79"

HEADER_BG     = "2E75B6"   # header row
HEADER_FG     = "FFFFFF"

TITLE_BG      = "1F4E79"
TITLE_FG      = "FFD700"

ALERT_BG      = "FF0000"
ALERT_FG      = "FFFFFF"

SUBJECT_COLORS = {
    "History":        "FCE4D6",
    "Geography":      "DDEBF7",
    "Polity":         "E2EFDA",
    "Economy":        "FFF2CC",
    "Science":        "F4CCFF",
    "Current Affairs":"FFE599",
    "Rajasthan GK":   "D9EAD3",
    "Mock Test":      "F4CCCC",
    "Revision":       "CFE2F3",
    "Rest":           "F0F0F0",
}

def cell_fill(hex_color):
    return PatternFill("solid", fgColor=hex_color)

def thin_border():
    s = Side(style='thin', color="AAAAAA")
    return Border(left=s, right=s, top=s, bottom=s)

def thick_border():
    s = Side(style='medium', color="2E75B6")
    return Border(left=s, right=s, top=s, bottom=s)

def style_cell(cell, bold=False, font_size=10, fg="000000", bg=None,
               h_align="center", v_align="center", wrap=False, border=True):
    cell.font = Font(name="Arial", bold=bold, size=font_size, color=fg)
    cell.alignment = Alignment(horizontal=h_align, vertical=v_align,
                                wrap_text=wrap)
    if bg:
        cell.fill = cell_fill(bg)
    if border:
        cell.border = thin_border()


# ═══════════════════════════════════════════════════════════════════
#  SHEET 1 – DAILY TIMETABLE
# ═══════════════════════════════════════════════════════════════════
ws1 = wb.active
ws1.title = "Daily Timetable"

# column widths
col_widths = [5, 18, 35, 20, 25, 20]
for i, w in enumerate(col_widths, 1):
    ws1.column_dimensions[get_column_letter(i)].width = w

# Title row
ws1.merge_cells("A1:F1")
ws1["A1"] = "📚 RAS PRE – DAILY STUDY TIMETABLE"
style_cell(ws1["A1"], bold=True, font_size=16, fg=TITLE_FG, bg=TITLE_BG,
           border=False)

ws1.merge_cells("A2:F2")
ws1["A2"] = "Coaching: 6:00 AM – 1:00 PM  |  Exam Target: 3-6 Months Away  |  Date Created: 15-Jul-2026"
style_cell(ws1["A2"], font_size=10, fg="FFFFFF", bg="2E75B6", border=False)

ws1.row_dimensions[1].height = 35
ws1.row_dimensions[2].height = 20

# Header row 3
headers = ["#", "Time Slot", "Activity", "Subject / Topic", "Notes / Reminder", "Status"]
for col, h in enumerate(headers, 1):
    c = ws1.cell(row=3, column=col, value=h)
    style_cell(c, bold=True, font_size=11, fg=HEADER_FG, bg=HEADER_BG)
ws1.row_dimensions[3].height = 22

# Timetable data: (time, activity, subject, notes, status_formula, bg, fg)
schedule = [
    ("5:00 – 5:30 AM",  "Wake Up & Morning Routine",  "–",               "Freshen up, light stretches",                  "MORNING",   "F2F2F2", "000000"),
    ("5:30 – 6:00 AM",  "Quick Revision",              "Previous Day Notes","Revise 5 key points from yesterday",          "REVISION",  STUDY_BG, STUDY_FG),
    ("6:00 – 1:00 PM",  "🏫 COACHING CLASSES",         "As per coaching",  "Attend all classes, take notes actively",      "COACHING",  COACHING_BG, COACHING_FG),
    ("1:00 – 2:00 PM",  "Lunch + Rest",                "–",               "Eat well, take a 20-min nap if needed",        "BREAK",     BREAK_BG, BREAK_FG),
    ("2:00 – 4:00 PM",  "Self-Study Block 1",          "Coaching Revision","Revise today's coaching topics thoroughly",   "STUDY",     STUDY_BG, STUDY_FG),
    ("4:00 – 4:15 PM",  "Short Break / Tea",           "–",               "Hydrate, take a walk",                        "BREAK",     BREAK_BG, BREAK_FG),
    ("4:15 – 6:15 PM",  "Self-Study Block 2",          "Rajasthan GK",    "Daily Rajasthan GK – 30 MCQs minimum",        "STUDY",     STUDY_BG, STUDY_FG),
    ("6:15 – 7:00 PM",  "Evening Walk / Relaxation",   "–",               "No screen time, relax your mind",             "BREAK",     BREAK_BG, BREAK_FG),
    ("7:00 – 8:30 PM",  "Self-Study Block 3",          "Weak Subject",    "Focus on weakest subject of the day",         "STUDY",     STUDY_BG, STUDY_FG),
    ("8:30 – 9:00 PM",  "Dinner",                      "–",               "Eat light, avoid heavy meals",                "BREAK",     BREAK_BG, BREAK_FG),
    ("9:00 – 10:00 PM", "Current Affairs",             "Current Affairs", "Rajasthan Patrika / Dainik Bhaskar + notes",  "STUDY",     STUDY_BG, STUDY_FG),
    ("10:00 – 10:30 PM","Revision + Next Day Planning","All Subjects",    "Write tomorrow's targets, review today's work","REVISION",  "E8F5E9", "1B5E20"),
    ("10:30 PM – 5:00 AM","SLEEP (6.5 hours minimum)", "–",              "⚠️ Do NOT compromise sleep!",                  "SLEEP",     SLEEP_BG, SLEEP_FG),
]

for i, (time, act, subj, note, status, bg, fg) in enumerate(schedule, 1):
    row = i + 3
    ws1.row_dimensions[row].height = 28

    ws1.cell(row=row, column=1, value=i)
    style_cell(ws1.cell(row=row, column=1), bold=True, fg="666666", bg=bg)

    ws1.cell(row=row, column=2, value=time)
    style_cell(ws1.cell(row=row, column=2), bold=(status == "COACHING"), fg=fg, bg=bg)

    ws1.cell(row=row, column=3, value=act)
    style_cell(ws1.cell(row=row, column=3), bold=(status == "COACHING"),
               font_size=11 if status == "COACHING" else 10, fg=fg, bg=bg, h_align="left")

    ws1.cell(row=row, column=4, value=subj)
    style_cell(ws1.cell(row=row, column=4), fg=fg, bg=bg)

    ws1.cell(row=row, column=5, value=note)
    style_cell(ws1.cell(row=row, column=5), fg=fg, bg=bg, h_align="left", wrap=True)

    # Status dropdown
    ws1.cell(row=row, column=6, value=status)
    style_cell(ws1.cell(row=row, column=6), bold=True, fg=fg, bg=bg)

# Data validation for Status column
dv = DataValidation(type="list",
                    formula1='"DONE,PENDING,SKIPPED,COACHING,STUDY,BREAK,SLEEP,REVISION,MORNING"',
                    showDropDown=False)
ws1.add_data_validation(dv)
dv.sqref = "F4:F16"

# Legend
legend_row = len(schedule) + 5
ws1.merge_cells(f"A{legend_row}:F{legend_row}")
ws1[f"A{legend_row}"] = "LEGEND"
style_cell(ws1[f"A{legend_row}"], bold=True, font_size=11, fg=HEADER_FG, bg=HEADER_BG)

legends = [
    ("Coaching Block", COACHING_BG, COACHING_FG),
    ("Self-Study",     STUDY_BG,    STUDY_FG),
    ("Break / Meals",  BREAK_BG,    BREAK_FG),
    ("Sleep",          SLEEP_BG,    SLEEP_FG),
]
for col_off, (label, bg, fg) in enumerate(legends):
    c = ws1.cell(row=legend_row + 1, column=col_off + 1, value=f"  {label}")
    style_cell(c, fg=fg, bg=bg, h_align="left")

# ═══════════════════════════════════════════════════════════════════
#  SHEET 2 – WEEKLY SUBJECT PLAN
# ═══════════════════════════════════════════════════════════════════
ws2 = wb.create_sheet("Weekly Subject Plan")

days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
slots = ["Morning Revision\n5:30-6:00 AM", "Afternoon Block 1\n2:00-4:00 PM",
         "Afternoon Block 2\n4:15-6:15 PM", "Night Block\n7:00-8:30 PM",
         "Current Affairs\n9:00-10:00 PM"]

weekly_plan = {
    "Monday":    ["History", "History", "Rajasthan GK", "Mock Test", "Current Affairs"],
    "Tuesday":   ["Geography", "Geography", "Rajasthan GK", "Mock Test", "Current Affairs"],
    "Wednesday": ["Polity", "Polity", "Rajasthan GK", "Mock Test", "Current Affairs"],
    "Thursday":  ["Economy", "Economy", "Rajasthan GK", "Mock Test", "Current Affairs"],
    "Friday":    ["Science", "Science", "Rajasthan GK", "Revision", "Current Affairs"],
    "Saturday":  ["Current Affairs", "Revision", "Rajasthan GK", "Mock Test", "Current Affairs"],
    "Sunday":    ["Rest", "Revision", "Rajasthan GK", "Revision", "Current Affairs"],
}

ws2.column_dimensions["A"].width = 22
for i in range(2, len(slots) + 2):
    ws2.column_dimensions[get_column_letter(i)].width = 20

ws2.merge_cells("A1:F1")
ws2["A1"] = "📅 RAS PRE – WEEKLY SUBJECT ROTATION PLAN"
style_cell(ws2["A1"], bold=True, font_size=14, fg=TITLE_FG, bg=TITLE_BG, border=False)
ws2.row_dimensions[1].height = 30

# Header
ws2.cell(row=2, column=1, value="Day")
style_cell(ws2.cell(row=2, column=1), bold=True, fg=HEADER_FG, bg=HEADER_BG)
for col, slot in enumerate(slots, 2):
    ws2.cell(row=2, column=col, value=slot)
    style_cell(ws2.cell(row=2, column=col), bold=True, fg=HEADER_FG,
               bg=HEADER_BG, wrap=True)
ws2.row_dimensions[2].height = 40

for row_i, day in enumerate(days, 3):
    ws2.row_dimensions[row_i].height = 32
    c = ws2.cell(row=row_i, column=1, value=day)
    style_cell(c, bold=True, fg=HEADER_FG, bg=HEADER_BG)
    subjects = weekly_plan[day]
    for col_i, subj in enumerate(subjects, 2):
        sc = ws2.cell(row=row_i, column=col_i, value=subj)
        bg = SUBJECT_COLORS.get(subj, "FFFFFF")
        style_cell(sc, fg="000000", bg=bg, wrap=True)

# Subject color legend on ws2
legend_r = len(days) + 4
ws2.merge_cells(f"A{legend_r}:F{legend_r}")
ws2[f"A{legend_r}"] = "SUBJECT COLOR LEGEND"
style_cell(ws2[f"A{legend_r}"], bold=True, fg=HEADER_FG, bg=HEADER_BG)
for idx, (subj, color) in enumerate(SUBJECT_COLORS.items()):
    r = legend_r + 1 + idx // 3
    c_col = (idx % 3) * 2 + 1
    c1 = ws2.cell(row=r, column=c_col, value=subj)
    style_cell(c1, bg=color, h_align="left")

# ═══════════════════════════════════════════════════════════════════
#  SHEET 3 – REMINDER ALERTS TABLE
# ═══════════════════════════════════════════════════════════════════
ws3 = wb.create_sheet("Reminder Alerts")

ws3.merge_cells("A1:G1")
ws3["A1"] = "⏰ RAS PRE – DAILY REMINDER ALERTS"
style_cell(ws3["A1"], bold=True, font_size=14, fg=TITLE_FG, bg=TITLE_BG, border=False)
ws3.row_dimensions[1].height = 30

ws3.merge_cells("A2:G2")
ws3["A2"] = "Enable Macros to activate pop-up reminders | Sheet contains VBA alert schedule"
style_cell(ws3["A2"], bold=False, font_size=10, fg="FFFFFF", bg="C00000", border=False)
ws3.row_dimensions[2].height = 18

alert_headers = ["#", "Alert Name", "Time", "Message", "Priority", "Category", "Enable?"]
alert_col_widths = [4, 25, 14, 55, 12, 18, 10]
for i, (h, w) in enumerate(zip(alert_headers, alert_col_widths), 1):
    ws3.column_dimensions[get_column_letter(i)].width = w
    c = ws3.cell(row=3, column=i, value=h)
    style_cell(c, bold=True, fg=HEADER_FG, bg=HEADER_BG)
ws3.row_dimensions[3].height = 22

alerts = [
    (1,  "Wake Up",            "5:00 AM",  "⏰ Wake up! Start your day strong. RAS Pre is waiting!",        "HIGH",   "Morning",  "YES"),
    (2,  "Morning Revision",   "5:30 AM",  "📖 Revise 5 key points from yesterday's notes now.",           "HIGH",   "Study",    "YES"),
    (3,  "Coaching Start",     "5:50 AM",  "🚌 Leave for coaching! Class starts at 6:00 AM sharp.",        "HIGH",   "Coaching", "YES"),
    (4,  "Mid-Coaching Break", "9:00 AM",  "☕ Short break. Drink water. Stay focused!",                   "MEDIUM", "Coaching", "YES"),
    (5,  "Coaching End",       "1:00 PM",  "✅ Coaching done! Go home, eat lunch, rest briefly.",          "MEDIUM", "Coaching", "YES"),
    (6,  "Self Study 1",       "2:00 PM",  "📚 Study Block 1: Revise today's coaching topics NOW.",        "HIGH",   "Study",    "YES"),
    (7,  "Study Break",        "4:00 PM",  "☕ 15-min break. Stretch, hydrate, then back to books.",       "LOW",    "Break",    "YES"),
    (8,  "Self Study 2",       "4:15 PM",  "📚 Study Block 2: Rajasthan GK – solve 30 MCQs!",             "HIGH",   "Study",    "YES"),
    (9,  "Evening Break",      "6:15 PM",  "🚶 Evening walk time. Rest your mind for 45 minutes.",        "MEDIUM", "Break",    "YES"),
    (10, "Self Study 3",       "7:00 PM",  "📚 Study Block 3: Focus on your weakest subject today.",      "HIGH",   "Study",    "YES"),
    (11, "Dinner",             "8:30 PM",  "🍽️ Dinner time. Eat light, avoid heavy meals.",               "LOW",    "Break",    "YES"),
    (12, "Current Affairs",    "9:00 PM",  "📰 Read Rajasthan Patrika / Dainik Bhaskar + take notes.",    "HIGH",   "Study",    "YES"),
    (13, "Daily Planning",     "10:00 PM", "📝 Write tomorrow's targets. Review today's performance.",    "MEDIUM", "Planning", "YES"),
    (14, "Sleep Reminder",     "10:30 PM", "😴 Time to SLEEP! 6.5 hrs rest = better memory retention!",  "HIGH",   "Sleep",    "YES"),
    (15, "Weekly Mock Test",   "Sunday 9AM","📝 WEEKLY MOCK TEST: Full 2-hour RAS Pre simulation!",       "HIGH",   "Mock",     "YES"),
]

priority_colors = {"HIGH": "FF0000", "MEDIUM": "FFC000", "LOW": "70AD47"}
category_colors = {
    "Morning": "F2F2F2", "Coaching": COACHING_BG, "Study": "E2EFDA",
    "Break": BREAK_BG, "Sleep": SLEEP_BG, "Planning": "EAF4FB",
    "Mock": "FCE4D6",
}

for row_data in alerts:
    idx, name, time_, msg, priority, cat, enable = row_data
    row = idx + 3
    ws3.row_dimensions[row].height = 30
    values = [idx, name, time_, msg, priority, cat, enable]
    for col, val in enumerate(values, 1):
        c = ws3.cell(row=row, column=col, value=val)
        if col == 5:  # Priority
            style_cell(c, bold=True, fg="FFFFFF", bg=priority_colors.get(priority, "808080"))
        elif col == 6:  # Category
            bg = category_colors.get(cat, "FFFFFF")
            fg = COACHING_FG if cat == "Coaching" else "000000"
            style_cell(c, fg=fg, bg=bg)
        elif col == 7:  # Enable
            style_cell(c, bold=True, fg="1E5631", bg="C6EFCE")
        else:
            style_cell(c, fg="000000", bg="FFFFFF", h_align="left" if col in [2,4] else "center", wrap=(col==4))

# Add data validation for Enable column
dv2 = DataValidation(type="list", formula1='"YES,NO"', showDropDown=False)
ws3.add_data_validation(dv2)
dv2.sqref = "G4:G18"

# Instructions box
instr_row = len(alerts) + 5
ws3.merge_cells(f"A{instr_row}:G{instr_row}")
ws3[f"A{instr_row}"] = "HOW TO ENABLE REMINDERS"
style_cell(ws3[f"A{instr_row}"], bold=True, fg=HEADER_FG, bg=HEADER_BG)

instructions = [
    "1. Press Alt+F11 to open the VBA Editor in Excel.",
    "2. Go to Insert > Module and paste the VBA code from the 'VBA Code' sheet.",
    "3. Save the file as .xlsm (Excel Macro-Enabled Workbook) format.",
    "4. Enable macros when prompted on next open.",
    "5. Run the macro 'SetupReminders' to activate all alerts listed above.",
    "6. Change 'YES' to 'NO' in column G to disable any specific reminder.",
    "Note: On mobile/Google Sheets, macros do not run. Use phone alarms instead.",
]
for i, instr in enumerate(instructions):
    r = instr_row + 1 + i
    ws3.merge_cells(f"A{r}:G{r}")
    c = ws3.cell(row=r, column=1, value=instr)
    bg = "FFF2CC" if "Note:" in instr else "F5F5F5"
    style_cell(c, fg="7F0000" if "Note:" in instr else "000000",
               bg=bg, h_align="left", border=True)
    ws3.row_dimensions[r].height = 20

# ═══════════════════════════════════════════════════════════════════
#  SHEET 4 – MOCK TEST TRACKER
# ═══════════════════════════════════════════════════════════════════
ws4 = wb.create_sheet("Mock Test Tracker")
ws4.merge_cells("A1:H1")
ws4["A1"] = "📊 RAS PRE – MOCK TEST PERFORMANCE TRACKER"
style_cell(ws4["A1"], bold=True, font_size=14, fg=TITLE_FG, bg=TITLE_BG, border=False)
ws4.row_dimensions[1].height = 30

mock_headers = ["#", "Date", "Test Type", "Total Q", "Attempted", "Correct",
                "Score %", "Target %"]
mock_widths   = [4, 14, 22, 10, 12, 10, 12, 12]
for i, (h, w) in enumerate(zip(mock_headers, mock_widths), 1):
    ws4.column_dimensions[get_column_letter(i)].width = w
    c = ws4.cell(row=2, column=i, value=h)
    style_cell(c, bold=True, fg=HEADER_FG, bg=HEADER_BG)
ws4.row_dimensions[2].height = 22

mock_types = ["Topic-wise MCQ", "Subject-wise Full Test", "Full RAS Pre Mock", "PYQ Practice"]
for i in range(1, 17):
    row = i + 2
    ws4.row_dimensions[row].height = 22
    mock_type = mock_types[min((i - 1) // 4, 3)]
    ws4.cell(row=row, column=1, value=i)
    style_cell(ws4.cell(row=row, column=1), fg="666666")
    ws4.cell(row=row, column=2, value="")  # Date to fill
    style_cell(ws4.cell(row=row, column=2))
    ws4.cell(row=row, column=3, value=mock_type)
    style_cell(ws4.cell(row=row, column=3), h_align="left")
    ws4.cell(row=row, column=4, value=100)
    style_cell(ws4.cell(row=row, column=4))
    ws4.cell(row=row, column=5, value="")  # Attempted – user fills
    style_cell(ws4.cell(row=row, column=5), bg="FFFACD")
    ws4.cell(row=row, column=6, value="")  # Correct – user fills
    style_cell(ws4.cell(row=row, column=6), bg="FFFACD")
    # Score % formula
    ws4.cell(row=row, column=7, value=f"=IF(F{row}=\"\",\"-\",F{row}/D{row}*100)")
    style_cell(ws4.cell(row=row, column=7), bg="E2EFDA")
    target = 60 + (i // 4) * 5
    ws4.cell(row=row, column=8, value=target)
    style_cell(ws4.cell(row=row, column=8), bg="DDEBF7")

# ═══════════════════════════════════════════════════════════════════
#  SHEET 5 – VBA CODE (as text reference)
# ═══════════════════════════════════════════════════════════════════
ws5 = wb.create_sheet("VBA Code")
ws5.merge_cells("A1:B1")
ws5["A1"] = "VBA MACRO CODE – Copy and paste this into your Excel VBA Editor (Alt+F11)"
style_cell(ws5["A1"], bold=True, font_size=12, fg="FFFFFF", bg="C00000", border=False)
ws5.row_dimensions[1].height = 25
ws5.column_dimensions["A"].width = 15
ws5.column_dimensions["B"].width = 90

vba_code = r"""
' ============================================================
' RAS PRE STUDY REMINDER MACRO
' How to use:
'   1. Press Alt+F11 in Excel
'   2. Insert > Module
'   3. Paste this entire code
'   4. Save as .xlsm
'   5. Run SetupReminders
' ============================================================

Sub SetupReminders()
    ' Clear existing alarms
    Call ClearReminders
    
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("Reminder Alerts")
    
    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    
    Dim i As Long
    For i = 4 To lastRow
        If ws.Cells(i, 7).Value = "YES" Then
            Dim alertTime As String
            alertTime = ws.Cells(i, 3).Value
            
            ' Only schedule today's time-based alerts (skip "Sunday 9AM" type)
            If InStr(alertTime, "AM") > 0 Or InStr(alertTime, "PM") > 0 Then
                If InStr(alertTime, "Sunday") = 0 Then
                    Dim t As Date
                    t = TimeValue(alertTime)
                    If t > Now() Then
                        Application.OnTime t, "ShowReminderAlert_" & i
                    End If
                End If
            End If
        End If
    Next i
    
    MsgBox "✅ All reminders set for today!" & Chr(10) & _
           "Keep Excel open for alerts to fire.", vbInformation, "RAS Pre Reminders"
End Sub

Sub ClearReminders()
    On Error Resume Next
    Dim i As Long
    For i = 4 To 18
        Application.OnTime TimeValue("5:00 AM"), "ShowReminderAlert_" & i, , False
    Next i
    On Error GoTo 0
End Sub

' Individual alert subs (one per row)
Sub ShowReminderAlert_4():  ShowAlert 4:  End Sub
Sub ShowReminderAlert_5():  ShowAlert 5:  End Sub
Sub ShowReminderAlert_6():  ShowAlert 6:  End Sub
Sub ShowReminderAlert_7():  ShowAlert 7:  End Sub
Sub ShowReminderAlert_8():  ShowAlert 8:  End Sub
Sub ShowReminderAlert_9():  ShowAlert 9:  End Sub
Sub ShowReminderAlert_10(): ShowAlert 10: End Sub
Sub ShowReminderAlert_11(): ShowAlert 11: End Sub
Sub ShowReminderAlert_12(): ShowAlert 12: End Sub
Sub ShowReminderAlert_13(): ShowAlert 13: End Sub
Sub ShowReminderAlert_14(): ShowAlert 14: End Sub
Sub ShowReminderAlert_15(): ShowAlert 15: End Sub
Sub ShowReminderAlert_16(): ShowAlert 16: End Sub
Sub ShowReminderAlert_17(): ShowAlert 17: End Sub
Sub ShowReminderAlert_18(): ShowAlert 18: End Sub

Sub ShowAlert(rowNum As Long)
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("Reminder Alerts")
    
    Dim alertName As String
    Dim alertMsg  As String
    Dim priority  As String
    
    alertName = ws.Cells(rowNum, 2).Value
    alertMsg  = ws.Cells(rowNum, 4).Value
    priority  = ws.Cells(rowNum, 5).Value
    
    Dim icon As Integer
    If priority = "HIGH" Then
        icon = vbCritical
    ElseIf priority = "MEDIUM" Then
        icon = vbExclamation
    Else
        icon = vbInformation
    End If
    
    MsgBox alertMsg, icon, "RAS Pre Reminder: " & alertName
End Sub

' ---- WEEKLY MOCK TEST REMINDER (run every Sunday) ----
Sub WeeklyMockReminder()
    If Weekday(Now(), vbMonday) = 7 Then  ' Sunday
        MsgBox "📝 WEEKLY MOCK TEST DAY!" & Chr(10) & _
               "Sit for a full 2-hour RAS Pre mock test." & Chr(10) & _
               "No distractions. Treat it like the real exam!", _
               vbExclamation, "RAS Pre – Weekly Mock Alert"
    End If
End Sub
"""

lines = vba_code.strip().split("\n")
for i, line in enumerate(lines, 2):
    ws5.row_dimensions[i].height = 15
    ws5.cell(row=i, column=1, value=i - 1)
    style_cell(ws5.cell(row=i, column=1), fg="999999", bg="F5F5F5", font_size=9)
    c = ws5.cell(row=i, column=2, value=line)
    # Color-code VBA keywords roughly
    if line.strip().startswith("'"):
        style_cell(c, fg="008000", bg="F5F5F5", h_align="left", font_size=10)  # green comments
    elif any(kw in line for kw in ["Sub ", "End Sub", "Function", "End Function"]):
        style_cell(c, bold=True, fg="0000FF", bg="EFF4FF", h_align="left", font_size=10)
    elif any(kw in line for kw in ["Dim ", "If ", "For ", "Next", "MsgBox", "Call "]):
        style_cell(c, fg="5B0E91", bg="F5F5F5", h_align="left", font_size=10)
    else:
        style_cell(c, fg="000000", bg="FFFFFF", h_align="left", font_size=10)

# ═══════════════════════════════════════════════════════════════════
#  Freeze panes + final touches on all sheets
# ═══════════════════════════════════════════════════════════════════
for ws in [ws1, ws2, ws3, ws4]:
    ws.freeze_panes = ws.cell(row=4, column=1)

# Set ws1 as active
wb.active = ws1

# Save
output_path = "/tmp/workspace/ras-timetable/RAS_Pre_Timetable.xlsx"
wb.save(output_path)
print(f"Saved: {output_path}")
Running Command

cd /tmp/workspace/ras-timetable && python create_timetable.py

Running Command

python3 -c " import openpyxl wb = openpyxl.load_workbook('/tmp/workspace/ras-timetable/RAS_Pre_Timetable.xlsx') print('Sheets:', wb.sheetnames) ws1 = wb['Daily Timetable'] print('Daily Timetable rows:', ws1.max_row, 'cols:', ws1.max_column) ws3 = wb['Reminder Alerts'] print('Reminder Alerts rows:', ws3.max_row) ws4 = wb['Mock Test Tracker'] print('Mock Test rows:', ws4.max_row) ws5 = wb['VBA Code'] print('VBA Code rows:', ws5.max_row) "

Your Excel timetable is ready! Download it here:

RAS Pre Timetable

Spreadsheet · XLSX


What's Inside (5 Sheets)

1. Daily Timetable

  • Full day schedule from 5:00 AM to 10:30 PM
  • Coaching block (6 AM - 1 PM) highlighted in dark blue
  • Self-study blocks in green, breaks in yellow, sleep in light blue
  • Status dropdown for each slot (DONE / PENDING / SKIPPED)

2. Weekly Subject Plan

  • 7-day subject rotation across all study slots
  • Each subject color-coded (History, Geography, Polity, Economy, Science, etc.)
  • Subject color legend included

3. Reminder Alerts

  • 15 timed reminders (Wake up, Coaching start, Study blocks, Sleep, etc.)
  • Priority levels: HIGH (red), MEDIUM (orange), LOW (green)
  • YES/NO toggle to enable or disable each reminder
  • Step-by-step instructions to activate macros

4. Mock Test Tracker

  • 16-week mock test log
  • Fill in Attempted + Correct; Score % calculates automatically
  • Escalating target scores week by week

5. VBA Code

  • Ready-to-paste macro code (color-coded like an IDE)
  • Triggers pop-up alerts at exact times
  • SetupReminders macro sets all daily alarms

To Activate Reminders

  1. Save as .xlsm (Excel Macro-Enabled Workbook) - File > Save As > select .xlsm
  2. Press Alt+F11 to open VBA Editor
  3. Insert > Module, paste the code from the "VBA Code" sheet
  4. Run SetupReminders macro - alerts will fire as pop-ups at each time!

Create a printable PDF version I can post on my study wall

Reading File
Writing File

~/ras-timetable/create_poster_pdf.py

from reportlab.lib.pagesizes import A3, landscape
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
    SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, HRFlowable
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.pdfgen import canvas
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate
from reportlab.lib.colors import HexColor, white, black
import io, os

OUTPUT = "/tmp/workspace/ras-timetable/RAS_Pre_StudyWall_Poster.pdf"

# ── Palette ──────────────────────────────────────────────────────
C_NAVY      = HexColor("#1F4E79")
C_BLUE      = HexColor("#2E75B6")
C_LIGHTBLUE = HexColor("#D6E4F0")
C_COACHING  = HexColor("#1F4E79")
C_COACHING2 = HexColor("#2E75B6")
C_GREEN     = HexColor("#1E5631")
C_LIGHTGRN  = HexColor("#E2EFDA")
C_YELLOW    = HexColor("#FFF2CC")
C_YLWDARK   = HexColor("#7F6000")
C_SLEEP     = HexColor("#D9E1F2")
C_SLEEPDARK = HexColor("#1F4E79")
C_GOLD      = HexColor("#FFD700")
C_RED       = HexColor("#C00000")
C_ORANGE    = HexColor("#E26B0A")
C_GREY      = HexColor("#F2F2F2")
C_DARKGREY  = HexColor("#595959")

PAGE_W, PAGE_H = landscape(A3)

# ── Helper: background + header drawn on every page ──────────────
def draw_background(c, doc):
    c.saveState()
    # Full page white bg
    c.setFillColor(HexColor("#FAFBFC"))
    c.rect(0, 0, PAGE_W, PAGE_H, fill=1, stroke=0)

    # Top banner
    c.setFillColor(C_NAVY)
    c.rect(0, PAGE_H - 3.2*cm, PAGE_W, 3.2*cm, fill=1, stroke=0)

    # Gold accent strip
    c.setFillColor(C_GOLD)
    c.rect(0, PAGE_H - 3.6*cm, PAGE_W, 0.4*cm, fill=1, stroke=0)

    # Bottom strip
    c.setFillColor(C_BLUE)
    c.rect(0, 0, PAGE_W, 0.7*cm, fill=1, stroke=0)

    # Title text
    c.setFillColor(C_GOLD)
    c.setFont("Helvetica-Bold", 26)
    c.drawCentredString(PAGE_W / 2, PAGE_H - 2.2*cm, "RAS PRE - DAILY STUDY TIMETABLE")

    c.setFillColor(white)
    c.setFont("Helvetica", 13)
    c.drawCentredString(PAGE_W / 2, PAGE_H - 2.9*cm,
        "Coaching: 6:00 AM - 1:00 PM  |  Target: 3-6 Months  |  Full Day Plan  |  Stay Focused, Clear RAS Pre!")

    # Bottom footer
    c.setFillColor(white)
    c.setFont("Helvetica", 9)
    c.drawCentredString(PAGE_W / 2, 0.18*cm, "Created for RAS Pre Aspirant  |  Print on A3 / Poster size  |  Post on your study wall!")

    c.restoreState()


# ── Build content ─────────────────────────────────────────────────
doc = BaseDocTemplate(
    OUTPUT,
    pagesize=landscape(A3),
    leftMargin=1.2*cm, rightMargin=1.2*cm,
    topMargin=4.0*cm, bottomMargin=1.2*cm,
)

frame = Frame(
    doc.leftMargin, doc.bottomMargin,
    PAGE_W - doc.leftMargin - doc.rightMargin,
    PAGE_H - doc.topMargin - doc.bottomMargin,
    id='main'
)
doc.addPageTemplates([PageTemplate(id='main', frames=frame, onPage=draw_background)])

styles = getSampleStyleSheet()

def ps(name, **kw):
    return ParagraphStyle(name, **kw)

title_s   = ps("T", fontSize=13, textColor=white, backColor=C_NAVY,
               alignment=TA_CENTER, fontName="Helvetica-Bold",
               spaceAfter=2, spaceBefore=4, leading=16)
sub_s     = ps("S", fontSize=9, textColor=C_DARKGREY, alignment=TA_LEFT,
               fontName="Helvetica", leading=12)
cell_bold = ps("CB", fontSize=9, textColor=white, fontName="Helvetica-Bold",
               alignment=TA_CENTER, leading=11)
cell_norm = ps("CN", fontSize=9, textColor=black, fontName="Helvetica",
               alignment=TA_LEFT, leading=11)
cell_note = ps("CNote", fontSize=8, textColor=C_DARKGREY, fontName="Helvetica-Oblique",
               alignment=TA_LEFT, leading=10)
sect_hdr  = ps("SH", fontSize=11, textColor=white, backColor=C_BLUE,
               fontName="Helvetica-Bold", alignment=TA_CENTER,
               spaceBefore=6, spaceAfter=2, leading=14)

# ────────────────────────────────────────────────────────────────
#  SECTION 1: DAILY TIMETABLE TABLE
# ────────────────────────────────────────────────────────────────
story = []

story.append(Paragraph("DAILY SCHEDULE", sect_hdr))
story.append(Spacer(1, 2*mm))

sched_data = [
    ["TIME", "ACTIVITY", "SUBJECT / TOPIC", "NOTES", "TYPE"],
    ["5:00 - 5:30 AM",  "Wake Up & Morning Routine",    "-",                      "Freshen up, light stretches",                  "MORNING"],
    ["5:30 - 6:00 AM",  "Quick Revision",               "Previous Day Notes",     "Revise 5 key points from yesterday's class",   "REVISION"],
    ["6:00 AM\n- 1:00 PM", "COACHING CLASSES",          "As per coaching batch",  "Attend all lectures. Take short notes.",        "COACHING"],
    ["1:00 - 2:00 PM",  "Lunch + Rest",                 "-",                      "Eat well. Take a 20-min nap if needed.",        "BREAK"],
    ["2:00 - 4:00 PM",  "Self-Study Block 1",           "Coaching Revision",      "Revise today's coaching topics thoroughly.",    "STUDY"],
    ["4:00 - 4:15 PM",  "Short Break / Tea",            "-",                      "Hydrate. Take a short walk.",                  "BREAK"],
    ["4:15 - 6:15 PM",  "Self-Study Block 2",           "Rajasthan GK",           "Solve 30 MCQs on Rajasthan GK daily.",         "STUDY"],
    ["6:15 - 7:00 PM",  "Evening Walk / Relaxation",    "-",                      "No screen time. Relax your mind.",             "BREAK"],
    ["7:00 - 8:30 PM",  "Self-Study Block 3",           "Weakest Subject",        "Dedicate this slot to your weakest topic.",    "STUDY"],
    ["8:30 - 9:00 PM",  "Dinner",                       "-",                      "Eat light. Avoid heavy meals at night.",       "BREAK"],
    ["9:00 - 10:00 PM", "Current Affairs",              "Current Affairs",        "Rajasthan Patrika + Dainik Bhaskar + Notes.",  "STUDY"],
    ["10:00 - 10:30 PM","Revision + Tomorrow's Plan",   "All Subjects",           "Write tomorrow's targets. Review today.",      "REVISION"],
    ["10:30 PM - 5 AM", "SLEEP (6.5 hrs minimum)",      "-",                      "DO NOT compromise sleep! Memory needs rest.",  "SLEEP"],
]

# row colours by TYPE
row_styles = {
    "MORNING":  (C_GREY,       black),
    "REVISION": (HexColor("#E8F5E9"), C_GREEN),
    "COACHING": (C_COACHING,   white),
    "BREAK":    (C_YELLOW,     C_YLWDARK),
    "STUDY":    (C_LIGHTGRN,   C_GREEN),
    "SLEEP":    (C_SLEEP,      C_SLEEPDARK),
}

col_widths_sched = [3.5*cm, 5.5*cm, 4.5*cm, 7.5*cm, 2.2*cm]

table_data = []
for row in sched_data:
    if row[0] == "TIME":
        table_data.append([
            Paragraph(r, ps("H", fontSize=9, textColor=white, fontName="Helvetica-Bold",
                            alignment=TA_CENTER, leading=11))
            for r in row
        ])
    else:
        rtype = row[4]
        bg, fg = row_styles.get(rtype, (white, black))
        is_coaching = rtype == "COACHING"
        fs = 10 if is_coaching else 9
        fw = "Helvetica-Bold" if is_coaching else "Helvetica"
        table_data.append([
            Paragraph(row[0], ps(f"r0_{rtype}", fontSize=fs, textColor=fg,
                                 fontName=fw, alignment=TA_CENTER, leading=12)),
            Paragraph(row[1], ps(f"r1_{rtype}", fontSize=fs, textColor=fg,
                                 fontName="Helvetica-Bold" if is_coaching else "Helvetica",
                                 alignment=TA_LEFT, leading=12)),
            Paragraph(row[2], ps(f"r2_{rtype}", fontSize=9, textColor=fg,
                                 fontName="Helvetica", alignment=TA_CENTER, leading=11)),
            Paragraph(row[3], ps(f"r3_{rtype}", fontSize=8, textColor=fg,
                                 fontName="Helvetica-Oblique" if not is_coaching else "Helvetica",
                                 alignment=TA_LEFT, leading=10)),
            Paragraph(row[4], ps(f"r4_{rtype}", fontSize=8, textColor=fg,
                                 fontName="Helvetica-Bold", alignment=TA_CENTER, leading=10)),
        ])

sched_table = Table(table_data, colWidths=col_widths_sched, repeatRows=1)

ts = TableStyle([
    # Header row
    ('BACKGROUND', (0,0), (-1,0), C_NAVY),
    ('TEXTCOLOR',  (0,0), (-1,0), white),
    ('FONTNAME',   (0,0), (-1,0), 'Helvetica-Bold'),
    ('FONTSIZE',   (0,0), (-1,0), 10),
    ('ALIGN',      (0,0), (-1,0), 'CENTER'),
    ('VALIGN',     (0,0), (-1,-1), 'MIDDLE'),
    ('GRID',       (0,0), (-1,-1), 0.5, HexColor("#AAAAAA")),
    ('ROWBACKGROUNDS', (0,0), (-1,-1), [None]),  # overridden per row below
    ('TOPPADDING',  (0,0), (-1,-1), 4),
    ('BOTTOMPADDING',(0,0), (-1,-1), 4),
    ('LEFTPADDING', (0,0), (-1,-1), 5),
    ('RIGHTPADDING',(0,0), (-1,-1), 5),
    # Coaching row thicker border
    ('BOX', (0,3), (-1,3), 2, C_COACHING),
])

# Apply row background colours
type_row_map = {}
for i, row in enumerate(sched_data[1:], 1):
    rtype = row[4]
    bg, _ = row_styles.get(rtype, (white, black))
    ts.add('BACKGROUND', (0, i), (-1, i), bg)
    # Coaching row special height
    if rtype == "COACHING":
        ts.add('FONTSIZE', (0, i), (-1, i), 10)

sched_table.setStyle(ts)
story.append(sched_table)
story.append(Spacer(1, 4*mm))

# ────────────────────────────────────────────────────────────────
#  SECTION 2: WEEKLY PLAN + SUBJECT KEY  (side by side)
# ────────────────────────────────────────────────────────────────
story.append(Paragraph("WEEKLY SUBJECT ROTATION  &  KEY REMINDERS", sect_hdr))
story.append(Spacer(1, 2*mm))

# Weekly plan
subj_colors = {
    "History":        HexColor("#FCE4D6"),
    "Geography":      HexColor("#DDEBF7"),
    "Polity":         HexColor("#E2EFDA"),
    "Economy":        HexColor("#FFF2CC"),
    "Science":        HexColor("#F4CCFF"),
    "Current Affairs":HexColor("#FFE599"),
    "Rajasthan GK":   HexColor("#D9EAD3"),
    "Mock Test":      HexColor("#F4CCCC"),
    "Revision":       HexColor("#CFE2F3"),
    "Rest":           HexColor("#F0F0F0"),
}

weekly_raw = [
    ["DAY",         "5:30-6AM\nRevision",  "2-4 PM\nBlock 1",  "4:15-6:15PM\nBlock 2", "7-8:30PM\nBlock 3"],
    ["Monday",      "History",   "History",   "Rajasthan GK", "Mock Test"],
    ["Tuesday",     "Geography", "Geography", "Rajasthan GK", "Mock Test"],
    ["Wednesday",   "Polity",    "Polity",    "Rajasthan GK", "Mock Test"],
    ["Thursday",    "Economy",   "Economy",   "Rajasthan GK", "Mock Test"],
    ["Friday",      "Science",   "Science",   "Rajasthan GK", "Revision"],
    ["Saturday",    "Curr.Aff.", "Revision",  "Rajasthan GK", "Mock Test"],
    ["Sunday",      "Rest",      "Revision",  "Rajasthan GK", "Revision"],
]

wk_col_widths = [2.4*cm, 2.4*cm, 2.4*cm, 2.8*cm, 2.4*cm]
wk_table_data = []
for ri, row in enumerate(weekly_raw):
    tr = []
    for ci, val in enumerate(row):
        if ri == 0:
            tr.append(Paragraph(val, ps(f"wh{ci}", fontSize=8, textColor=white,
                                         fontName="Helvetica-Bold", alignment=TA_CENTER, leading=10)))
        else:
            bg = subj_colors.get(val, HexColor("#FFFFFF")) if ci > 0 else C_BLUE
            fg_col = white if ci == 0 else black
            tr.append(Paragraph(val, ps(f"wc{ri}{ci}", fontSize=8, textColor=fg_col,
                                         fontName="Helvetica-Bold" if ci == 0 else "Helvetica",
                                         alignment=TA_CENTER, leading=10)))
    wk_table_data.append(tr)

wk_table = Table(wk_table_data, colWidths=wk_col_widths, repeatRows=1)
wk_ts = TableStyle([
    ('BACKGROUND', (0,0), (-1,0), C_NAVY),
    ('GRID', (0,0), (-1,-1), 0.5, HexColor("#AAAAAA")),
    ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ('ALIGN', (0,0), (-1,-1), 'CENTER'),
    ('TOPPADDING', (0,0), (-1,-1), 4),
    ('BOTTOMPADDING', (0,0), (-1,-1), 4),
])
for ri, row in enumerate(weekly_raw[1:], 1):
    for ci in range(1, len(row)):
        bg = subj_colors.get(row[ci], HexColor("#FFFFFF"))
        wk_ts.add('BACKGROUND', (ci, ri), (ci, ri), bg)
    wk_ts.add('BACKGROUND', (0, ri), (0, ri), C_BLUE)

wk_table.setStyle(wk_ts)

# Key Reminders panel
reminders = [
    ["KEY RULES & REMINDERS"],
    ["1. Revise coaching topics SAME DAY (2-4 PM block)"],
    ["2. Rajasthan GK - MINIMUM 30 MCQs daily"],
    ["3. Read newspaper every night (Current Affairs)"],
    ["4. Sunday = Full 2-hour mock test (treat as real exam)"],
    ["5. NO new topics in last 2 weeks - only revision"],
    ["6. Sleep 6.5+ hours - DO NOT compromise!"],
    ["7. Write tomorrow's plan every night at 10 PM"],
    ["8. Track mock test scores weekly (aim 60%+)"],
    [""],
    ["MOCK TEST STRATEGY"],
    ["Weeks 1-4  : Topic-wise MCQs"],
    ["Weeks 5-8  : Subject-wise full tests"],
    ["Weeks 9-12 : Full RAS Pre mock (100Q / 2hr)"],
    ["Weeks 13-16: PYQs + rapid revision"],
    [""],
    ["DAILY STUDY HOURS BREAKDOWN"],
    ["Coaching         : 7.0 hrs"],
    ["Self-Study Blocks: 5.5 hrs"],
    ["Current Affairs  : 1.0 hr"],
    ["Total            : ~13.5 hrs/day"],
]

rem_data = []
for i, row in enumerate(reminders):
    val = row[0]
    if val in ["KEY RULES & REMINDERS", "MOCK TEST STRATEGY", "DAILY STUDY HOURS BREAKDOWN"]:
        rem_data.append([Paragraph(val, ps(f"rh{i}", fontSize=9, textColor=white,
                                            fontName="Helvetica-Bold", alignment=TA_CENTER, leading=11))])
    elif val == "":
        rem_data.append([Paragraph(" ", ps(f"re{i}", fontSize=5, leading=6))])
    elif val.startswith("Total"):
        rem_data.append([Paragraph(val, ps(f"rt{i}", fontSize=9, textColor=C_NAVY,
                                            fontName="Helvetica-Bold", alignment=TA_LEFT, leading=11))])
    else:
        rem_data.append([Paragraph(val, ps(f"rn{i}", fontSize=8, textColor=C_DARKGREY,
                                            fontName="Helvetica", alignment=TA_LEFT, leading=11))])

rem_table = Table(rem_data, colWidths=[6.0*cm])
rem_ts = TableStyle([
    ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ('LEFTPADDING', (0,0), (-1,-1), 6),
    ('RIGHTPADDING', (0,0), (-1,-1), 6),
    ('TOPPADDING', (0,0), (-1,-1), 2),
    ('BOTTOMPADDING', (0,0), (-1,-1), 2),
    ('BOX', (0,0), (-1,-1), 1, C_BLUE),
    ('GRID', (0,0), (-1,-1), 0.3, HexColor("#DDDDDD")),
])
# Header rows background
header_rows = [i for i, r in enumerate(reminders) if r[0] in
               ["KEY RULES & REMINDERS", "MOCK TEST STRATEGY", "DAILY STUDY HOURS BREAKDOWN"]]
for hr in header_rows:
    rem_ts.add('BACKGROUND', (0, hr), (0, hr), C_BLUE)

# Alternating for non-header rows
for i, row in enumerate(reminders):
    if i not in header_rows and row[0] != "":
        bg = HexColor("#F7FBFF") if i % 2 == 0 else white
        rem_ts.add('BACKGROUND', (0, i), (0, i), bg)
rem_table.setStyle(rem_ts)

# Subject legend
leg_data = [
    [Paragraph("SUBJECT LEGEND", ps("lh", fontSize=8, textColor=white,
                                     fontName="Helvetica-Bold", alignment=TA_CENTER, leading=10)),
     Paragraph("", ps("lhe"))],
]
subj_pairs = list(subj_colors.items())
for k in range(0, len(subj_pairs), 2):
    row_items = []
    for s, c in subj_pairs[k:k+2]:
        row_items.append(Paragraph(f"  {s}", ps(f"ls{k}", fontSize=8, textColor=black,
                                                  fontName="Helvetica", alignment=TA_LEFT, leading=10)))
    if len(row_items) == 1:
        row_items.append(Paragraph("", ps("lse")))
    leg_data.append(row_items)

leg_table = Table(leg_data, colWidths=[3.2*cm, 3.2*cm])
leg_ts = TableStyle([
    ('BACKGROUND', (0,0), (1,0), C_NAVY),
    ('SPAN', (0,0), (1,0)),
    ('GRID', (0,0), (-1,-1), 0.5, HexColor("#AAAAAA")),
    ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ('TOPPADDING', (0,0), (-1,-1), 3),
    ('BOTTOMPADDING', (0,0), (-1,-1), 3),
    ('LEFTPADDING', (0,0), (-1,-1), 4),
])
for ki, (s, c) in enumerate(subj_pairs):
    ri = ki // 2 + 1
    ci = ki % 2
    leg_ts.add('BACKGROUND', (ci, ri), (ci, ri), c)
leg_table.setStyle(leg_ts)

# Combine weekly + reminders + legend side by side
combined = Table(
    [[wk_table, rem_table, leg_table]],
    colWidths=[14.0*cm, 6.5*cm, 6.8*cm]
)
combined.setStyle(TableStyle([
    ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ('LEFTPADDING', (0,0), (-1,-1), 4),
    ('RIGHTPADDING', (0,0), (-1,-1), 4),
]))
story.append(combined)
story.append(Spacer(1, 3*mm))

# Motivational footer strip
motiv = Table(
    [[Paragraph(
        '"SUCCESS is not given, it is EARNED. Every hour you study today builds the officer you will be tomorrow. '
        'Clear RAS Pre - YOU CAN DO IT!"',
        ps("mot", fontSize=10, textColor=white, fontName="Helvetica-BoldOblique",
           alignment=TA_CENTER, leading=14)
    )]],
    colWidths=[PAGE_W - 2.4*cm]
)
motiv.setStyle(TableStyle([
    ('BACKGROUND', (0,0), (-1,-1), C_NAVY),
    ('TOPPADDING', (0,0), (-1,-1), 8),
    ('BOTTOMPADDING', (0,0), (-1,-1), 8),
    ('LEFTPADDING', (0,0), (-1,-1), 10),
    ('RIGHTPADDING', (0,0), (-1,-1), 10),
    ('BOX', (0,0), (-1,-1), 2, C_GOLD),
]))
story.append(motiv)

# Build PDF
doc.build(story)
print(f"PDF saved: {OUTPUT}")
size_kb = os.path.getsize(OUTPUT) / 1024
print(f"File size: {size_kb:.1f} KB")
Running Command

cd /tmp/workspace/ras-timetable && python create_poster_pdf.py 2>&1

Running Command

python3 -c " from pypdf import PdfReader r = PdfReader('/tmp/workspace/ras-timetable/RAS_Pre_StudyWall_Poster.pdf') print('Pages:', len(r.pages)) p = r.pages[0] print('Page size (pts):', p.mediabox.width, 'x', p.mediabox.height) print('Width cm:', float(p.mediabox.width)/28.35, 'Height cm:', float(p.mediabox.height)/28.35) "

Writing File

~/ras-timetable/create_poster_pdf.py

from reportlab.lib.pagesizes import A3, landscape
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
    Table, TableStyle, Paragraph, Spacer,
    BaseDocTemplate, Frame, PageTemplate
)
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.lib.colors import HexColor, white, black
import os

OUTPUT = "/tmp/workspace/ras-timetable/RAS_Pre_StudyWall_Poster.pdf"

# ── Palette ──────────────────────────────────────────────────────
C_NAVY  = HexColor("#1F4E79")
C_BLUE  = HexColor("#2E75B6")
C_GOLD  = HexColor("#FFD700")
C_GREEN = HexColor("#1E5631")
C_LGRN  = HexColor("#E2EFDA")
C_YLW   = HexColor("#FFF2CC")
C_YLWDK = HexColor("#7F6000")
C_SLEEP = HexColor("#D9E1F2")
C_GREY  = HexColor("#F2F2F2")
C_DGY   = HexColor("#595959")
C_RED   = HexColor("#C00000")

subj_colors = {
    "History":        HexColor("#FCE4D6"),
    "Geography":      HexColor("#DDEBF7"),
    "Polity":         HexColor("#E2EFDA"),
    "Economy":        HexColor("#FFF2CC"),
    "Science":        HexColor("#F4CCFF"),
    "Curr. Affairs":  HexColor("#FFE599"),
    "Rajasthan GK":   HexColor("#D9EAD3"),
    "Mock Test":      HexColor("#F4CCCC"),
    "Revision":       HexColor("#CFE2F3"),
    "Rest":           HexColor("#F0F0F0"),
}

PAGE_W, PAGE_H = landscape(A3)   # 1190.6 x 841.9 pts  (42 x 29.7 cm)

# ── Page background drawn every page ─────────────────────────────
def draw_bg(c, doc):
    c.saveState()
    c.setFillColor(HexColor("#F8FAFD"))
    c.rect(0, 0, PAGE_W, PAGE_H, fill=1, stroke=0)
    # Top banner
    c.setFillColor(C_NAVY)
    c.rect(0, PAGE_H - 2.6*cm, PAGE_W, 2.6*cm, fill=1, stroke=0)
    # Gold strip
    c.setFillColor(C_GOLD)
    c.rect(0, PAGE_H - 2.9*cm, PAGE_W, 0.3*cm, fill=1, stroke=0)
    # Title
    c.setFillColor(C_GOLD)
    c.setFont("Helvetica-Bold", 22)
    c.drawCentredString(PAGE_W/2, PAGE_H - 1.8*cm, "RAS PRE - DAILY STUDY TIMETABLE")
    c.setFillColor(white)
    c.setFont("Helvetica", 11)
    c.drawCentredString(PAGE_W/2, PAGE_H - 2.5*cm,
        "Coaching: 6:00 AM - 1:00 PM  |  Target: 3-6 Months  |  Post this on your study wall!")
    # Bottom strip
    c.setFillColor(C_BLUE)
    c.rect(0, 0, PAGE_W, 0.6*cm, fill=1, stroke=0)
    c.setFillColor(white)
    c.setFont("Helvetica", 8)
    c.drawCentredString(PAGE_W/2, 0.15*cm, "Stay Focused. Work Hard. Clear RAS Pre!")
    c.restoreState()

# ── Doc setup ────────────────────────────────────────────────────
LMARGIN = RMARGIN = 0.8*cm
TMARGIN = 3.2*cm
BMARGIN = 0.8*cm

doc = BaseDocTemplate(
    OUTPUT,
    pagesize=landscape(A3),
    leftMargin=LMARGIN, rightMargin=RMARGIN,
    topMargin=TMARGIN,  bottomMargin=BMARGIN,
)
avail_w = PAGE_W - LMARGIN - RMARGIN    # ~40.4 cm = ~1146 pts
avail_h = PAGE_H - TMARGIN - BMARGIN    # ~25.7 cm

frame = Frame(LMARGIN, BMARGIN, avail_w, avail_h, id='main')
doc.addPageTemplates([PageTemplate(id='main', frames=frame, onPage=draw_bg)])

def ps(name, **kw):
    return ParagraphStyle(name, **kw)

sect = ps("S", fontSize=9, textColor=white, fontName="Helvetica-Bold",
          alignment=TA_CENTER, leading=11)
# ── Helper ───────────────────────────────────────────────────────
def sec_hdr(text):
    t = Table([[Paragraph(text, sect)]], colWidths=[avail_w])
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), C_BLUE),
        ('TOPPADDING',    (0,0), (-1,-1), 3),
        ('BOTTOMPADDING', (0,0), (-1,-1), 3),
    ]))
    return t

story = []

# ════════════════════════════════════════════════════════════════
#  ROW 1: Daily Schedule table  (full width)
# ════════════════════════════════════════════════════════════════
story.append(sec_hdr("DAILY SCHEDULE"))
story.append(Spacer(1, 1.5*mm))

sched = [
    ("TIME",            "ACTIVITY",                       "SUBJECT / TOPIC",      "NOTES",                                     "TYPE"),
    ("5:00-5:30 AM",    "Wake Up & Morning Routine",      "-",                    "Freshen up, light stretches",               "MORNING"),
    ("5:30-6:00 AM",    "Quick Revision",                 "Previous Day Notes",   "Revise 5 key points from yesterday",        "REVISION"),
    ("6:00 AM-1:00 PM", "COACHING CLASSES",               "As per batch schedule","Attend all lectures. Take active notes.",    "COACHING"),
    ("1:00-2:00 PM",    "Lunch + Rest",                   "-",                    "Eat well. 20-min nap if needed.",           "BREAK"),
    ("2:00-4:00 PM",    "Self-Study Block 1",             "Coaching Revision",    "Revise today's coaching topics.",           "STUDY"),
    ("4:00-4:15 PM",    "Short Break / Tea",              "-",                    "Hydrate. Short walk.",                      "BREAK"),
    ("4:15-6:15 PM",    "Self-Study Block 2",             "Rajasthan GK",         "30 MCQs on Rajasthan GK - daily!",          "STUDY"),
    ("6:15-7:00 PM",    "Evening Walk / Relaxation",      "-",                    "No screen time. Rest your mind.",           "BREAK"),
    ("7:00-8:30 PM",    "Self-Study Block 3",             "Weakest Subject",      "Focus on your weakest topic today.",        "STUDY"),
    ("8:30-9:00 PM",    "Dinner",                         "-",                    "Eat light. Avoid heavy meals.",             "BREAK"),
    ("9:00-10:00 PM",   "Current Affairs",                "Current Affairs",      "Rajasthan Patrika + Dainik Bhaskar + Notes.","STUDY"),
    ("10:00-10:30 PM",  "Revision + Tomorrow's Plan",     "All Subjects",         "Write targets. Review today's performance.","REVISION"),
    ("10:30 PM-5 AM",   "SLEEP  (6.5 hrs min)",           "-",                    "DO NOT compromise sleep! Brain needs rest.","SLEEP"),
]

row_bg = {
    "MORNING":  (C_GREY,              black),
    "REVISION": (HexColor("#E8F5E9"), C_GREEN),
    "COACHING": (C_NAVY,              white),
    "BREAK":    (C_YLW,               C_YLWDK),
    "STUDY":    (C_LGRN,              C_GREEN),
    "SLEEP":    (C_SLEEP,             HexColor("#1F4E79")),
}

# column widths summing to avail_w
cw = [2.9*cm, 5.0*cm, 4.0*cm, 6.8*cm, 2.0*cm]
# avail_w in cm ~ 40.4; total above = 20.7 -> need to fill remaining
# fill with equal padding to each column
extra = (avail_w/cm - sum(x/cm for x in cw)) / len(cw)
cw = [x + extra*cm for x in cw]

def make_p(text, fg=black, bold=False, size=8, align=TA_LEFT):
    fw = "Helvetica-Bold" if bold else "Helvetica"
    return Paragraph(text, ps(f"p_{text[:6]}", fontSize=size, textColor=fg,
                               fontName=fw, alignment=align, leading=size+2))

tbl_rows = []
for ri, row in enumerate(sched):
    typ = row[4]
    if ri == 0:
        tbl_rows.append([make_p(v, fg=white, bold=True, size=9, align=TA_CENTER) for v in row])
    else:
        bg_c, fg_c = row_bg.get(typ, (white, black))
        is_c = (typ == "COACHING")
        sz = 9 if is_c else 8
        tbl_rows.append([
            make_p(row[0], fg=fg_c, bold=is_c, size=sz, align=TA_CENTER),
            make_p(row[1], fg=fg_c, bold=is_c, size=sz),
            make_p(row[2], fg=fg_c, size=sz, align=TA_CENTER),
            make_p(row[3], fg=fg_c, size=sz-1),
            make_p(row[4], fg=fg_c, bold=True, size=7, align=TA_CENTER),
        ])

sched_tbl = Table(tbl_rows, colWidths=cw, repeatRows=1)
sts = TableStyle([
    ('BACKGROUND', (0,0), (-1,0), C_NAVY),
    ('GRID',       (0,0), (-1,-1), 0.4, HexColor("#BBBBBB")),
    ('VALIGN',     (0,0), (-1,-1), 'MIDDLE'),
    ('TOPPADDING',    (0,0), (-1,-1), 3),
    ('BOTTOMPADDING', (0,0), (-1,-1), 3),
    ('LEFTPADDING',   (0,0), (-1,-1), 4),
    ('RIGHTPADDING',  (0,0), (-1,-1), 4),
])
for ri, row in enumerate(sched[1:], 1):
    bg_c, _ = row_bg.get(row[4], (white, black))
    sts.add('BACKGROUND', (0,ri), (-1,ri), bg_c)
    if row[4] == "COACHING":
        sts.add('LINEABOVE', (0,ri), (-1,ri), 1.5, C_GOLD)
        sts.add('LINEBELOW', (0,ri), (-1,ri), 1.5, C_GOLD)
sched_tbl.setStyle(sts)
story.append(sched_tbl)
story.append(Spacer(1, 2*mm))

# ════════════════════════════════════════════════════════════════
#  ROW 2: Three columns – Weekly Plan | Key Rules | Subject Legend
# ════════════════════════════════════════════════════════════════
story.append(sec_hdr("WEEKLY SUBJECT ROTATION          KEY RULES & REMINDERS          SUBJECT LEGEND"))
story.append(Spacer(1, 1.5*mm))

# ── Weekly plan ──
wkly = [
    ["DAY",       "5:30-6AM",  "2-4 PM",    "4:15-6:15PM",  "7-8:30PM"],
    ["Mon",       "History",   "History",   "Raj. GK",      "Mock Test"],
    ["Tue",       "Geography", "Geography", "Raj. GK",      "Mock Test"],
    ["Wed",       "Polity",    "Polity",    "Raj. GK",      "Mock Test"],
    ["Thu",       "Economy",   "Economy",   "Raj. GK",      "Mock Test"],
    ["Fri",       "Science",   "Science",   "Raj. GK",      "Revision"],
    ["Sat",       "Curr. Affairs","Revision","Raj. GK",     "Mock Test"],
    ["Sun",       "Rest",      "Revision",  "Raj. GK",      "Revision"],
]
wk_cw = [1.5*cm, 2.5*cm, 2.5*cm, 2.9*cm, 2.5*cm]
wk_total = sum(wk_cw)

wk_data = []
for ri, row in enumerate(wkly):
    tr = []
    for ci, v in enumerate(row):
        if ri == 0:
            tr.append(make_p(v, fg=white, bold=True, size=8, align=TA_CENTER))
        else:
            sc = subj_colors.get(v, HexColor("#FFFFFF")) if ci > 0 else C_BLUE
            fc = white if ci == 0 else black
            tr.append(make_p(v, fg=fc, bold=(ci==0), size=8, align=TA_CENTER))
    wk_data.append(tr)

wk_tbl = Table(wk_data, colWidths=wk_cw, repeatRows=1)
wk_ts = TableStyle([
    ('BACKGROUND', (0,0), (-1,0), C_NAVY),
    ('GRID', (0,0), (-1,-1), 0.4, HexColor("#BBBBBB")),
    ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ('TOPPADDING', (0,0), (-1,-1), 3),
    ('BOTTOMPADDING', (0,0), (-1,-1), 3),
    ('LEFTPADDING', (0,0), (-1,-1), 3),
    ('RIGHTPADDING', (0,0), (-1,-1), 3),
])
for ri, row in enumerate(wkly[1:], 1):
    wk_ts.add('BACKGROUND', (0,ri), (0,ri), C_BLUE)
    for ci in range(1, len(row)):
        bg = subj_colors.get(row[ci], HexColor("#FFFFFF"))
        wk_ts.add('BACKGROUND', (ci,ri), (ci,ri), bg)
wk_tbl.setStyle(wk_ts)

# ── Key Rules ──
rules = [
    ("COACHING (6AM-1PM)", C_NAVY, True),
    ("Revise coaching topics same day", None, False),
    ("Rajasthan GK: 30 MCQs daily", None, False),
    ("Newspaper every night (9-10PM)", None, False),
    ("Sunday = Full 2-hr mock test", C_LGRN, True),
    ("Last 2 weeks = Revision ONLY", None, False),
    ("Sleep 6.5+ hrs every night!", C_SLEEP, False),
    ("Write tomorrow's plan at 10PM", None, False),
    ("Target: 60%+ in weekly mocks", C_LGRN, True),
    ("MOCK TEST PLAN", C_BLUE, True),
    ("Wk 1-4:  Topic-wise MCQs", None, False),
    ("Wk 5-8:  Subject full tests", None, False),
    ("Wk 9-12: Full RAS Pre mock", None, False),
    ("Wk 13-16: PYQs + Revision", None, False),
    ("DAILY HOURS", C_BLUE, True),
    ("Coaching       : 7.0 hrs", None, False),
    ("Self-Study     : 5.5 hrs", None, False),
    ("Current Affairs: 1.0 hr", None, False),
    ("TOTAL          : 13.5 hrs", HexColor("#E8F5E9"), True),
]

rule_data = []
for text, bg, bold in rules:
    rule_data.append([make_p(text, fg=white if bg in [C_NAVY, C_BLUE] else C_DGY if not bold else C_GREEN,
                              bold=bold, size=8, align=TA_LEFT)])

rule_tbl = Table(rule_data, colWidths=[6.8*cm])
rule_ts = TableStyle([
    ('GRID', (0,0), (-1,-1), 0.3, HexColor("#DDDDDD")),
    ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ('TOPPADDING', (0,0), (-1,-1), 2),
    ('BOTTOMPADDING', (0,0), (-1,-1), 2),
    ('LEFTPADDING', (0,0), (-1,-1), 5),
    ('RIGHTPADDING', (0,0), (-1,-1), 5),
    ('BOX', (0,0), (-1,-1), 1, C_BLUE),
])
for ri, (text, bg, bold) in enumerate(rules):
    if bg:
        rule_ts.add('BACKGROUND', (0,ri), (0,ri), bg)
    else:
        rule_ts.add('BACKGROUND', (0,ri), (0,ri), white if ri%2==0 else HexColor("#F7FBFF"))
rule_tbl.setStyle(rule_ts)

# ── Subject Legend ──
leg_items = list(subj_colors.items())
leg_data = [[make_p("SUBJECT COLOR LEGEND", fg=white, bold=True, size=8, align=TA_CENTER),
             make_p("", size=8)]]
for i in range(0, len(leg_items), 2):
    row_p = []
    for s, c in leg_items[i:i+2]:
        row_p.append(make_p(f"  {s}", fg=black, size=8))
    if len(row_p) == 1:
        row_p.append(make_p("", size=8))
    leg_data.append(row_p)

leg_tbl = Table(leg_data, colWidths=[3.2*cm, 3.2*cm])
leg_ts2 = TableStyle([
    ('SPAN',       (0,0), (1,0)),
    ('BACKGROUND', (0,0), (1,0), C_NAVY),
    ('GRID', (0,0), (-1,-1), 0.4, HexColor("#AAAAAA")),
    ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ('TOPPADDING', (0,0), (-1,-1), 3),
    ('BOTTOMPADDING', (0,0), (-1,-1), 3),
    ('LEFTPADDING', (0,0), (-1,-1), 4),
    ('BOX', (0,0), (-1,-1), 1, C_BLUE),
])
for ki, (s, c) in enumerate(leg_items):
    ri = ki // 2 + 1
    ci = ki % 2
    leg_ts2.add('BACKGROUND', (ci, ri), (ci, ri), c)
leg_tbl.setStyle(leg_ts2)

# ── Combine three columns ──
# Total widths: weekly=12.9, gap, rules=6.8, gap, legend=6.4
# avail_w ~ 40.4 cm; remainder for gaps
wk_w = wk_total
ru_w = 6.8*cm
le_w = 6.5*cm
gap  = (avail_w - wk_w - ru_w - le_w) / 2

three_col = Table(
    [[wk_tbl, rule_tbl, leg_tbl]],
    colWidths=[wk_w + gap, ru_w + gap/2, le_w + gap/2]
)
three_col.setStyle(TableStyle([
    ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ('LEFTPADDING',  (0,0), (-1,-1), 3),
    ('RIGHTPADDING', (0,0), (-1,-1), 3),
]))
story.append(three_col)
story.append(Spacer(1, 2*mm))

# ── Motivational quote strip ──
quote = Table(
    [[make_p(
        '"Every hour you study today builds the RAS officer you will be tomorrow.  '
        'Stay disciplined, Stay focused - YOU WILL CLEAR RAS PRE!"',
        fg=white, bold=True, size=10, align=TA_CENTER
    )]],
    colWidths=[avail_w]
)
quote.setStyle(TableStyle([
    ('BACKGROUND', (0,0), (-1,-1), C_NAVY),
    ('BOX',        (0,0), (-1,-1), 2,   C_GOLD),
    ('TOPPADDING', (0,0), (-1,-1), 6),
    ('BOTTOMPADDING', (0,0), (-1,-1), 6),
    ('LEFTPADDING',  (0,0), (-1,-1), 10),
    ('RIGHTPADDING', (0,0), (-1,-1), 10),
]))
story.append(quote)

doc.build(story)
print(f"Saved: {OUTPUT}")
from pypdf import PdfReader
r = PdfReader(OUTPUT)
print(f"Pages: {len(r.pages)}  |  Size: {os.path.getsize(OUTPUT)/1024:.1f} KB")
Editing File

~/ras-timetable/create_poster_pdf.py

Successfully replaced 1 instance(s) of the string in '/tmp/workspace/ras-timetable/create_poster_pdf.py'
Running Command

cat > /tmp/workspace/ras-timetable/create_poster_v2.py << 'PYEOF' from reportlab.lib.pagesizes import A3, landscape from reportlab.lib.units import cm, mm from reportlab.platypus import ( Table, TableStyle, Paragraph, Spacer, BaseDocTemplate, Frame, PageTemplate ) from reportlab.lib.styles import ParagraphStyle from reportlab.lib.enums import TA_CENTER, TA_LEFT from reportlab.lib.colors import HexColor, white, black import os OUTPUT = "/tmp/workspace/ras-timetable/RAS_Pre_StudyWall_Poster.pdf" C_NAVY = HexColor("#1F4E79") C_BLUE = HexColor("#2E75B6") C_GOLD = HexColor("#FFD700") C_GREEN = HexColor("#1E5631") C_LGRN = HexColor("#E2EFDA") C_YLW = HexColor("#FFF2CC") C_YLWDK = HexColor("#7F6000") C_SLEEP = HexColor("#D9E1F2") C_GREY = HexColor("#F2F2F2") C_DGY = HexColor("#595959") subj_colors = { "History": HexColor("#FCE4D6"), "Geography": HexColor("#DDEBF7"), "Polity": HexColor("#E2EFDA"), "Economy": HexColor("#FFF2CC"), "Science": HexColor("#F4CCFF"), "Curr. Affairs": HexColor("#FFE599"), "Raj. GK": HexColor("#D9EAD3"), "Mock Test": HexColor("#F4CCCC"), "Revision": HexColor("#CFE2F3"), "Rest": HexColor("#F0F0F0"), } PAGE_W, PAGE_H = landscape(A3) def draw_bg(c, doc): c.saveState() c.setFillColor(HexColor("#F8FAFD")); c.rect(0, 0, PAGE_W, PAGE_H, fill=1, stroke=0) c.setFillColor(C_NAVY); c.rect(0, PAGE_H-2.4*cm, PAGE_W, 2.4*cm, fill=1, stroke=0) c.setFillColor(C_GOLD); c.rect(0, PAGE_H-2.65*cm, PAGE_W, 0.25*cm, fill=1, stroke=0) c.setFillColor(C_GOLD); c.setFont("Helvetica-Bold", 21) c.drawCentredString(PAGE_W/2, PAGE_H-1.65*cm, "RAS PRE - DAILY STUDY TIMETABLE") c.setFillColor(white); c.setFont("Helvetica", 10.5) c.drawCentredString(PAGE_W/2, PAGE_H-2.3*cm, "Coaching: 6:00 AM - 1:00 PM | Target: 3-6 Months | Post this on your study wall!") c.setFillColor(C_BLUE); c.rect(0, 0, PAGE_W, 0.55*cm, fill=1, stroke=0) c.setFillColor(white); c.setFont("Helvetica", 8) c.drawCentredString(PAGE_W/2, 0.13*cm, "Stay Focused. Work Hard. Clear RAS Pre!") c.restoreState() LMARGIN = RMARGIN = 0.7*cm TMARGIN = 2.9*cm BMARGIN = 0.75*cm doc = BaseDocTemplate(OUTPUT, pagesize=landscape(A3), leftMargin=LMARGIN, rightMargin=RMARGIN, topMargin=TMARGIN, bottomMargin=BMARGIN) avail_w = PAGE_W - LMARGIN - RMARGIN frame = Frame(LMARGIN, BMARGIN, avail_w, PAGE_H-TMARGIN-BMARGIN, id='main') doc.addPageTemplates([PageTemplate(id='main', frames=frame, onPage=draw_bg)]) def ps(name, **kw): return ParagraphStyle(name, **kw) def p(text, fg=black, bold=False, sz=8, align=TA_LEFT): return Paragraph(text, ps(f"_{text[:8]}_{sz}", fontSize=sz, textColor=fg, fontName="Helvetica-Bold" if bold else "Helvetica", alignment=align, leading=sz+2)) def sec(text): t = Table([[p(text, fg=white, bold=True, sz=9, align=TA_CENTER)]], colWidths=[avail_w]) t.setStyle(TableStyle([('BACKGROUND',(0,0),(-1,-1),C_BLUE), ('TOPPADDING',(0,0),(-1,-1),2),('BOTTOMPADDING',(0,0),(-1,-1),2)])) return t story = [] # ── SECTION 1: Daily Schedule ────────────────────────────────── story.append(sec("DAILY SCHEDULE")) story.append(Spacer(1, 1*mm)) sched = [ ("TIME", "ACTIVITY", "SUBJECT / TOPIC", "NOTES", "TYPE"), ("5:00-5:30 AM", "Wake Up & Morning Routine", "-", "Freshen up, light stretches", "MRN"), ("5:30-6:00 AM", "Quick Revision", "Previous Day Notes", "Revise 5 key points from yesterday", "REV"), ("6:00 AM-1:00 PM","COACHING CLASSES", "As per batch", "Attend all lectures. Take short notes.", "COA"), ("1:00-2:00 PM", "Lunch + Rest", "-", "Eat well. 20-min nap if needed.", "BRK"), ("2:00-4:00 PM", "Self-Study Block 1", "Coaching Revision", "Revise today's coaching topics.", "STU"), ("4:00-4:15 PM", "Short Break / Tea", "-", "Hydrate. Short walk.", "BRK"), ("4:15-6:15 PM", "Self-Study Block 2", "Rajasthan GK", "30 MCQs on Rajasthan GK - daily!", "STU"), ("6:15-7:00 PM", "Evening Walk / Relaxation", "-", "No screen time. Rest your mind.", "BRK"), ("7:00-8:30 PM", "Self-Study Block 3", "Weakest Subject", "Focus on your weakest topic today.", "STU"), ("8:30-9:00 PM", "Dinner", "-", "Eat light. Avoid heavy meals.", "BRK"), ("9:00-10:00 PM", "Current Affairs", "Curr. Affairs", "Rajasthan Patrika + Dainik Bhaskar.", "STU"), ("10:00-10:30 PM", "Revision + Plan Tomorrow", "All Subjects", "Write targets. Review today.", "REV"), ("10:30 PM-5:00 AM","SLEEP (6.5 hrs minimum)", "-", "DO NOT compromise sleep! Brain needs rest.","SLP"), ] rbg = {"MRN":(C_GREY,white),"REV":(HexColor("#E8F5E9"),C_GREEN), "COA":(C_NAVY,white),"BRK":(C_YLW,C_YLWDK), "STU":(C_LGRN,C_GREEN),"SLP":(C_SLEEP,HexColor("#1F4E79"))} cw = [2.85*cm, 4.8*cm, 3.8*cm, 6.5*cm, 1.9*cm] extra = (avail_w - sum(cw)) / len(cw) cw = [x+extra for x in cw] rows = [] for ri, r in enumerate(sched): tp = r[4] if ri==0: rows.append([p(v, fg=white, bold=True, sz=9, align=TA_CENTER) for v in r]) else: bg_c, fg_c = rbg.get(tp,(white,black)) is_c = (tp=="COA") sz = 9 if is_c else 8 rows.append([ p(r[0], fg=fg_c, bold=is_c, sz=sz, align=TA_CENTER), p(r[1], fg=fg_c, bold=is_c, sz=sz), p(r[2], fg=fg_c, sz=sz, align=TA_CENTER), p(r[3], fg=fg_c, sz=sz-1), p(r[4], fg=fg_c, bold=True, sz=7, align=TA_CENTER), ]) tbl = Table(rows, colWidths=cw, repeatRows=1) ts = TableStyle([('BACKGROUND',(0,0),(-1,0),C_NAVY), ('GRID',(0,0),(-1,-1),0.35,HexColor("#BBBBBB")), ('VALIGN',(0,0),(-1,-1),'MIDDLE'), ('TOPPADDING',(0,0),(-1,-1),2),('BOTTOMPADDING',(0,0),(-1,-1),2), ('LEFTPADDING',(0,0),(-1,-1),3),('RIGHTPADDING',(0,0),(-1,-1),3)]) for ri, r in enumerate(sched[1:],1): bg_c,_ = rbg.get(r[4],(white,black)) ts.add('BACKGROUND',(0,ri),(-1,ri),bg_c) if r[4]=="COA": ts.add('LINEABOVE',(0,ri),(-1,ri),1.5,C_GOLD) ts.add('LINEBELOW',(0,ri),(-1,ri),1.5,C_GOLD) tbl.setStyle(ts) story.append(tbl) story.append(Spacer(1, 1.5*mm)) # ── SECTION 2: Three columns ─────────────────────────────────── story.append(sec("WEEKLY ROTATION | KEY RULES & REMINDERS | SUBJECT LEGEND")) story.append(Spacer(1, 1*mm)) # Weekly table wkly = [ ["DAY", "5:30-6AM", "2-4 PM", "4:15-6:15", "7-8:30 PM"], ["Mon", "History", "History", "Raj. GK", "Mock Test"], ["Tue", "Geography", "Geography", "Raj. GK", "Mock Test"], ["Wed", "Polity", "Polity", "Raj. GK", "Mock Test"], ["Thu", "Economy", "Economy", "Raj. GK", "Mock Test"], ["Fri", "Science", "Science", "Raj. GK", "Revision"], ["Sat", "Curr. Affairs","Revision","Raj. GK", "Mock Test"], ["Sun", "Rest", "Revision", "Raj. GK", "Revision"], ] wk_cw = [1.4*cm, 2.5*cm, 2.5*cm, 2.7*cm, 2.4*cm] wk_total = sum(wk_cw) wk_rows = [] for ri, row in enumerate(wkly): tr = [] for ci, v in enumerate(row): fg_c = white if (ri==0 or ci==0) else black bold = (ri==0 or ci==0) tr.append(p(v, fg=fg_c, bold=bold, sz=8, align=TA_CENTER)) wk_rows.append(tr) wk_tbl = Table(wk_rows, colWidths=wk_cw) wk_ts = TableStyle([('BACKGROUND',(0,0),(-1,0),C_NAVY), ('GRID',(0,0),(-1,-1),0.35,HexColor("#BBBBBB")), ('VALIGN',(0,0),(-1,-1),'MIDDLE'), ('TOPPADDING',(0,0),(-1,-1),2),('BOTTOMPADDING',(0,0),(-1,-1),2), ('LEFTPADDING',(0,0),(-1,-1),3),('RIGHTPADDING',(0,0),(-1,-1),3)]) for ri, row in enumerate(wkly[1:],1): wk_ts.add('BACKGROUND',(0,ri),(0,ri),C_BLUE) for ci in range(1,len(row)): wk_ts.add('BACKGROUND',(ci,ri),(ci,ri),subj_colors.get(row[ci],white)) wk_tbl.setStyle(wk_ts) # Rules table rules = [ ("KEY RULES & REMINDERS", C_NAVY, True), ("1. Revise coaching topics same day (2-4 PM)", None, False), ("2. Rajasthan GK: min 30 MCQs every day", None, False), ("3. Read newspaper 9-10 PM (Current Affairs)", None, False), ("4. Sunday = Full 2-hour mock test", C_LGRN, True), ("5. Last 2 weeks = Revision ONLY, no new topics", None, False), ("6. Sleep 6.5+ hrs every night!", C_SLEEP, False), ("7. Write tomorrow's plan at 10 PM daily", None, False), ("MOCK TEST SCHEDULE", C_NAVY, True), ("Weeks 1-4 : Topic-wise MCQs", None, False), ("Weeks 5-8 : Subject full tests", None, False), ("Weeks 9-12 : Full RAS Pre mock (100Q/2hr)", None, False), ("Weeks 13-16: PYQs + Rapid Revision", None, False), ("DAILY HOURS", C_NAVY, True), ("Coaching : 7.0 hrs", None, False), ("Self-Study Blocks : 5.5 hrs", None, False), ("Current Affairs : 1.0 hr", None, False), ("TOTAL : 13.5 hrs/day", HexColor("#E8F5E9"), True), ] rule_rows = [] for text, bg, bold in rules: is_hdr = bg == C_NAVY fg_c = white if is_hdr else (C_GREEN if bold and not is_hdr else C_DGY) rule_rows.append([p(text, fg=fg_c, bold=bold, sz=8)]) ru_cw = 6.5*cm rule_tbl = Table(rule_rows, colWidths=[ru_cw]) rule_ts = TableStyle([('GRID',(0,0),(-1,-1),0.3,HexColor("#DDDDDD")), ('VALIGN',(0,0),(-1,-1),'MIDDLE'), ('TOPPADDING',(0,0),(-1,-1),2),('BOTTOMPADDING',(0,0),(-1,-1),2), ('LEFTPADDING',(0,0),(-1,-1),5),('RIGHTPADDING',(0,0),(-1,-1),5), ('BOX',(0,0),(-1,-1),1,C_BLUE)]) for ri, (text, bg, bold) in enumerate(rules): if bg: rule_ts.add('BACKGROUND',(0,ri),(0,ri),bg) else: rule_ts.add('BACKGROUND',(0,ri),(0,ri),white if ri%2==0 else HexColor("#F7FBFF")) rule_tbl.setStyle(rule_ts) # Legend table leg_items = list(subj_colors.items()) leg_rows = [[p("SUBJECT COLOR LEGEND", fg=white, bold=True, sz=8, align=TA_CENTER), p("", sz=8)]] for i in range(0, len(leg_items), 2): row2 = [] for s, c in leg_items[i:i+2]: row2.append(p(f" {s}", fg=black, sz=8)) if len(row2)==1: row2.append(p("",sz=8)) leg_rows.append(row2) le_cw = 3.1*cm leg_tbl = Table(leg_rows, colWidths=[le_cw, le_cw]) leg_ts = TableStyle([('SPAN',(0,0),(1,0)), ('BACKGROUND',(0,0),(1,0),C_NAVY), ('GRID',(0,0),(-1,-1),0.4,HexColor("#AAAAAA")), ('VALIGN',(0,0),(-1,-1),'MIDDLE'), ('TOPPADDING',(0,0),(-1,-1),3),('BOTTOMPADDING',(0,0),(-1,-1),3), ('LEFTPADDING',(0,0),(-1,-1),3),('RIGHTPADDING',(0,0),(-1,-1),3), ('BOX',(0,0),(-1,-1),1,C_BLUE)]) for ki, (s, c) in enumerate(leg_items): ri = ki//2+1; ci = ki%2 leg_ts.add('BACKGROUND',(ci,ri),(ci,ri),c) leg_tbl.setStyle(leg_ts) # Combine 3 cols gap = (avail_w - wk_total - ru_cw - le_cw*2) / 2 three = Table([[wk_tbl, rule_tbl, leg_tbl]], colWidths=[wk_total+gap, ru_cw+gap/2, le_cw*2+gap/2]) three.setStyle(TableStyle([('VALIGN',(0,0),(-1,-1),'TOP'), ('LEFTPADDING',(0,0),(-1,-1),3),('RIGHTPADDING',(0,0),(-1,-1),3)])) story.append(three) story.append(Spacer(1, 1.5*mm)) # Quote strip quote = Table([[p( '"Every hour you study today builds the RAS officer you will be tomorrow. ' 'Stay disciplined. Stay consistent. YOU WILL CLEAR RAS PRE!"', fg=white, bold=True, sz=10, align=TA_CENTER )]], colWidths=[avail_w]) quote.setStyle(TableStyle([('BACKGROUND',(0,0),(-1,-1),C_NAVY), ('BOX',(0,0),(-1,-1),2,C_GOLD), ('TOPPADDING',(0,0),(-1,-1),5),('BOTTOMPADDING',(0,0),(-1,-1),5), ('LEFTPADDING',(0,0),(-1,-1),10),('RIGHTPADDING',(0,0),(-1,-1),10)])) story.append(quote) doc.build(story) from pypdf import PdfReader r = PdfReader(OUTPUT) print(f"Pages: {len(r.pages)} | Size: {os.path.getsize(OUTPUT)/1024:.1f} KB") print(f"Saved: {OUTPUT}") PYEOF echo "Script written"

Running Command

cd /tmp/workspace/ras-timetable && python create_poster_v2.py 2>&1

Your printable poster PDF is ready - exactly 1 page, A3 landscape! Download it here:

RAS Pre StudyWall Poster

PDF Document · PDF


What's on the Poster

Single A3 Landscape Page - Print-ready

Top Banner (Navy + Gold)

  • Title: RAS PRE - DAILY STUDY TIMETABLE
  • Subtitle with coaching hours and target

Section 1: Full Daily Schedule Table

All 13 time slots with color-coded rows:
  • 🔵 Dark Navy - Coaching block (6 AM - 1 PM) with gold border
  • 🟢 Green - Self-Study blocks (3 slots)
  • 🟡 Yellow - Breaks & meals
  • 🔷 Light Blue - Sleep block
  • All rows include: Time, Activity, Subject, Notes, Type

Section 2: Three-Column Panel

ColumnContent
LeftWeekly 7-day subject rotation grid
MiddleKey Rules & Reminders + Mock Test plan + Daily hours breakdown
RightSubject color legend

Bottom Strip

Motivational quote in navy + gold border

Printing Tips

  • Best size: A3 paper (42 x 29.7 cm) - landscape orientation
  • Also works on: A4 (slightly smaller text) - just set "fit to page" in print settings
  • Color printing recommended to see the color-coded blocks clearly
  • Laminate it after printing for durability on your study wall!

Create a mobile phone wallpaper (1080x1920px) with the daily schedule

Running Command

python3 -c "from PIL import Image; print('Pillow OK')" 2>&1

Running Command

python3 -c " from PIL import ImageFont import os # Check available fonts font_dirs = ['/usr/share/fonts', '/usr/local/share/fonts', os.path.expanduser('~/.fonts')] fonts = [] for d in font_dirs: if os.path.exists(d): for root, dirs, files in os.walk(d): for f in files: if f.endswith(('.ttf', '.otf')): fonts.append(os.path.join(root, f)) print('Total fonts:', len(fonts)) for f in fonts[:20]: print(f) " 2>&1

Running Command

cat > /tmp/workspace/ras-timetable/create_wallpaper.py << 'PYEOF' from PIL import Image, ImageDraw, ImageFont import os W, H = 1080, 1920 OUTPUT = "/tmp/workspace/ras-timetable/RAS_Pre_Wallpaper.png" # Fonts FONT_BOLD = "/usr/share/fonts/google-droid-sans-fonts/DroidSans-Bold.ttf" FONT_REGULAR = "/usr/share/fonts/google-droid-sans-fonts/DroidSans.ttf" FONT_NOTO = "/usr/share/fonts/google-noto-vf/NotoSans[wght].ttf" def fnt(path, size): try: return ImageFont.truetype(path, size) except: return ImageFont.load_default() # Colors C_NAVY = (31, 78, 121) C_BLUE = (46, 117, 182) C_LBLUE = (214, 228, 240) C_GOLD = (255, 215, 0) C_WHITE = (255, 255, 255) C_BLACK = (30, 30, 30) C_GREEN = (30, 86, 49) C_LGRN = (226, 239, 218) C_YELLOW = (255, 242, 204) C_YLWDK = (127, 96, 0) C_SLEEP = (217, 225, 242) C_GREY = (242, 242, 242) C_DGY = (89, 89, 89) C_ORANGE = (226, 107, 10) # Row type -> (bg, fg_time, fg_activity, badge_bg, badge_txt) ROW_STYLES = { "MRN": (C_GREY, C_DGY, C_BLACK, (180,180,180), C_WHITE), "REV": (C_LGRN, C_GREEN, C_GREEN, (100,170,110), C_WHITE), "COA": (C_NAVY, C_GOLD, C_WHITE, C_GOLD, C_NAVY), "BRK": (C_YELLOW, C_YLWDK, C_YLWDK, C_ORANGE, C_WHITE), "STU": (C_LGRN, C_GREEN, C_BLACK, C_BLUE, C_WHITE), "SLP": (C_SLEEP, C_NAVY, C_NAVY, C_NAVY, C_WHITE), } SCHEDULE = [ ("5:00-5:30 AM", "Wake Up & Morning Routine", "MORNING", "MRN"), ("5:30-6:00 AM", "Quick Revision (Yesterday)", "REVISION", "REV"), ("6:00AM-1:00PM", "COACHING CLASSES", "COACHING", "COA"), ("1:00-2:00 PM", "Lunch + Rest", "BREAK", "BRK"), ("2:00-4:00 PM", "Self-Study Block 1", "STUDY", "STU"), ("4:00-4:15 PM", "Short Break / Tea", "BREAK", "BRK"), ("4:15-6:15 PM", "Self-Study Block 2 (Raj. GK)","STUDY", "STU"), ("6:15-7:00 PM", "Evening Walk / Relax", "BREAK", "BRK"), ("7:00-8:30 PM", "Self-Study Block 3", "STUDY", "STU"), ("8:30-9:00 PM", "Dinner", "BREAK", "BRK"), ("9:00-10:00 PM", "Current Affairs", "STUDY", "STU"), ("10:00-10:30 PM", "Revision + Plan Tomorrow", "REVISION", "REV"), ("10:30PM-5:00AM", "SLEEP (6.5 hrs min)", "SLEEP", "SLP"), ] img = Image.new("RGB", (W, H), C_NAVY) draw = ImageDraw.Draw(img) # ── Background gradient (simulate with horizontal bands) ── for y in range(H): t = y / H r = int(C_NAVY[0] + (C_BLUE[0]-C_NAVY[0]) * t * 0.15) g = int(C_NAVY[1] + (C_BLUE[1]-C_NAVY[1]) * t * 0.15) b = int(C_NAVY[2] + (C_BLUE[2]-C_NAVY[2]) * t * 0.15) draw.line([(0,y),(W,y)], fill=(r,g,b)) # ── TOP BANNER ────────────────────────────────────────────────── BANNER_H = 200 draw.rectangle([(0,0),(W,BANNER_H)], fill=C_NAVY) # Gold accent line draw.rectangle([(0, BANNER_H-6),(W, BANNER_H)], fill=C_GOLD) # Decorative circles draw.ellipse([(-60,-60),(160,160)], fill=(46,117,182,0)) # subtle draw.ellipse([(880,-80),(1140,180)], fill=(255,215,0)) draw.ellipse([(900,-60),(1120,160)], fill=C_NAVY) # Title f_title = fnt(FONT_BOLD, 52) f_sub = fnt(FONT_REGULAR, 28) f_mini = fnt(FONT_REGULAR, 22) draw.text((W//2, 62), "RAS PRE", font=fnt(FONT_BOLD, 64), fill=C_GOLD, anchor="mm") draw.text((W//2, 118), "DAILY STUDY TIMETABLE", font=fnt(FONT_BOLD, 34), fill=C_WHITE, anchor="mm") draw.text((W//2, 160), "Coaching: 6AM - 1PM | Target: 3-6 Months", font=f_mini, fill=C_LBLUE, anchor="mm") # ── SCHEDULE ROWS ─────────────────────────────────────────────── ROW_H = 110 ROW_MARGIN = 18 ROW_RADIUS = 18 START_Y = BANNER_H + 20 PAD_X = 22 f_time = fnt(FONT_BOLD, 23) f_act = fnt(FONT_BOLD, 28) f_badge= fnt(FONT_BOLD, 19) for i, (time_str, activity, badge_txt, typ) in enumerate(SCHEDULE): bg, fg_time, fg_act, badge_bg, badge_fg = ROW_STYLES[typ] y0 = START_Y + i * (ROW_H + ROW_MARGIN) y1 = y0 + ROW_H x0, x1 = PAD_X, W - PAD_X # Shadow draw.rounded_rectangle([(x0+3, y0+4),(x1+3, y1+4)], radius=ROW_RADIUS, fill=(0,0,0,60) if False else (20,20,40)) # Row bg draw.rounded_rectangle([(x0, y0),(x1, y1)], radius=ROW_RADIUS, fill=bg) # Left colored accent bar accent_w = 10 draw.rounded_rectangle([(x0, y0),(x0+accent_w, y1)], radius=ROW_RADIUS, fill=badge_bg) # Coaching special: thicker gold border if typ == "COA": draw.rounded_rectangle([(x0, y0),(x1, y1)], radius=ROW_RADIUS, outline=C_GOLD, width=4) # Time text tx = x0 + accent_w + 18 ty_mid = (y0 + y1) // 2 draw.text((tx, ty_mid - 22), time_str, font=f_time, fill=fg_time, anchor="lm") # Activity text (may need wrapping for long text) act_font = fnt(FONT_BOLD, 29 if typ=="COA" else 26) draw.text((tx, ty_mid + 16), activity, font=act_font, fill=fg_act, anchor="lm") # Badge (right side) badge_w_est = len(badge_txt) * 13 + 24 bx0 = x1 - badge_w_est - 16 bx1 = x1 - 16 by0 = ty_mid - 18 by1 = ty_mid + 18 draw.rounded_rectangle([(bx0, by0),(bx1, by1)], radius=10, fill=badge_bg) draw.text(((bx0+bx1)//2, (by0+by1)//2), badge_txt, font=f_badge, fill=badge_fg, anchor="mm") # ── BOTTOM QUOTE STRIP ────────────────────────────────────────── last_row_bottom = START_Y + len(SCHEDULE) * (ROW_H + ROW_MARGIN) - ROW_MARGIN + 20 strip_h = H - last_row_bottom - 10 draw.rectangle([(0, last_row_bottom),(W, H)], fill=C_NAVY) draw.rectangle([(0, last_row_bottom),(W, last_row_bottom+5)], fill=C_GOLD) quote = "Stay Focused. Stay Consistent. Clear RAS Pre!" f_q = fnt(FONT_BOLD, 26) draw.text((W//2, last_row_bottom + strip_h//2), quote, font=f_q, fill=C_GOLD, anchor="mm") # Save img.save(OUTPUT, "PNG", dpi=(300,300)) print(f"Saved: {OUTPUT}") print(f"Size: {os.path.getsize(OUTPUT)/1024:.1f} KB") from PIL import Image as Im im = Im.open(OUTPUT) print(f"Dimensions: {im.size}") PYEOF echo "Script written"

Running Command

cd /tmp/workspace/ras-timetable && python create_wallpaper.py 2>&1

Running Command

python3 -c " ROW_H = 110; ROW_MARGIN = 18; START_Y = 220; N = 13 total = START_Y + N * (ROW_H + ROW_MARGIN) print(f'Last row bottom: {total}px (image height: 1920px)') print(f'Remaining for footer: {1920 - total}px') "

Running Command

python3 -c " # Find ideal row params for 13 rows, leaving 80px footer, 200px header, 20px gap H = 1920; BANNER = 200; GAP_TOP = 18; FOOTER = 82; PAD_X = 22 avail = H - BANNER - GAP_TOP - FOOTER # = 1620 N = 13 # ROW_H + ROW_MARGIN per slot best = None for rh in range(95, 115): for rm in range(8, 20): total = N * (rh + rm) - rm if total <= avail: best = (rh, rm, total) if best: rh, rm, total = best print(f'ROW_H={rh}, ROW_MARGIN={rm}, total={total}, avail={avail}, spare={avail-total}') "

Running Command

cat > /tmp/workspace/ras-timetable/create_wallpaper_v2.py << 'PYEOF' from PIL import Image, ImageDraw, ImageFont import os W, H = 1080, 1920 OUTPUT = "/tmp/workspace/ras-timetable/RAS_Pre_Wallpaper.png" FONT_BOLD = "/usr/share/fonts/google-droid-sans-fonts/DroidSans-Bold.ttf" FONT_REGULAR = "/usr/share/fonts/google-droid-sans-fonts/DroidSans.ttf" def fnt(path, size): try: return ImageFont.truetype(path, size) except: return ImageFont.load_default() # Colors C_NAVY = (31, 78, 121) C_BLUE = (46, 117, 182) C_LBLUE = (190, 215, 240) C_GOLD = (255, 210, 0) C_WHITE = (255, 255, 255) C_BLACK = (25, 25, 25) C_GREEN = (22, 82, 40) C_LGRN = (218, 238, 208) C_DGRN = (55, 130, 75) C_YELLOW = (255, 242, 200) C_YLWDK = (120, 88, 0) C_SLEEP = (210, 222, 245) C_GREY = (238, 238, 238) C_DGY = (85, 85, 85) C_ORANGE = (210, 95, 5) C_PURP = (120, 80, 180) # (bg, left_bar, time_color, act_color, badge_bg, badge_fg) ROW_STYLES = { "MRN": (C_GREY, (160,160,165), C_DGY, C_BLACK, (150,150,160), C_WHITE), "REV": ((228,245,220), C_DGRN, C_GREEN, C_GREEN, C_DGRN, C_WHITE), "COA": ((20, 55, 100), C_GOLD, C_GOLD, C_WHITE, C_GOLD, C_NAVY), "BRK": (C_YELLOW, C_ORANGE, C_YLWDK, C_YLWDK, C_ORANGE, C_WHITE), "STU": (C_LGRN, C_BLUE, C_GREEN, C_BLACK, C_BLUE, C_WHITE), "SLP": (C_SLEEP, C_NAVY, C_NAVY, C_NAVY, C_NAVY, C_WHITE), } SCHEDULE = [ ("5:00 - 5:30 AM", "Wake Up & Morning Routine", "MORNING", "MRN"), ("5:30 - 6:00 AM", "Quick Revision", "REVISION", "REV"), ("6:00AM - 1:00PM", "COACHING CLASSES", "COACHING", "COA"), ("1:00 - 2:00 PM", "Lunch + Rest", "BREAK", "BRK"), ("2:00 - 4:00 PM", "Self-Study Block 1", "STUDY", "STU"), ("4:00 - 4:15 PM", "Short Break / Tea", "BREAK", "BRK"), ("4:15 - 6:15 PM", "Self-Study Block 2", "STUDY", "STU"), ("6:15 - 7:00 PM", "Evening Walk / Relax", "BREAK", "BRK"), ("7:00 - 8:30 PM", "Self-Study Block 3", "STUDY", "STU"), ("8:30 - 9:00 PM", "Dinner", "BREAK", "BRK"), ("9:00 - 10:00 PM", "Current Affairs", "STUDY", "STU"), ("10:00 - 10:30 PM", "Revision + Plan Tomorrow", "REVISION", "REV"), ("10:30PM - 5:00AM", "SLEEP (6.5 hrs min)", "SLEEP", "SLP"), ] # Layout constants BANNER_H = 200 GAP_TOP = 18 ROW_H = 114 ROW_GAP = 11 PAD_X = 22 ROW_R = 20 # corner radius FOOTER_H = H - BANNER_H - GAP_TOP - 13*(ROW_H+ROW_GAP) + ROW_GAP # ~88px # ── Create image ───────────────────────────────────────────────── img = Image.new("RGB", (W, H), C_NAVY) draw = ImageDraw.Draw(img) # Gradient background for y in range(H): t = y / H r = int(C_NAVY[0]*(1-t*0.18) + C_BLUE[0]*t*0.18) g = int(C_NAVY[1]*(1-t*0.18) + C_BLUE[1]*t*0.18) b = int(C_NAVY[2]*(1-t*0.18) + C_BLUE[2]*t*0.18) draw.line([(0,y),(W,y)], fill=(r,g,b)) # ── TOP BANNER ────────────────────────────────────────────────── draw.rectangle([(0,0),(W, BANNER_H)], fill=C_NAVY) # Decorative arcs (top right) for r, col, alpha in [(260, (60,130,200), 40), (200, (46,117,182), 60), (140, (31,78,121), 80)]: draw.ellipse([(W-r, -r),(W+r, r)], fill=col) draw.ellipse([(W-120, -120),(W+120, 120)], fill=C_NAVY) # Gold dot accent draw.ellipse([(42, 30),(78, 66)], fill=C_GOLD) draw.ellipse([(52, 40),(68, 56)], fill=C_NAVY) # Title block draw.text((W//2, 68), "RAS PRE", font=fnt(FONT_BOLD, 66), fill=C_GOLD, anchor="mm") draw.text((W//2, 125), "DAILY STUDY TIMETABLE", font=fnt(FONT_BOLD, 35), fill=C_WHITE, anchor="mm") draw.text((W//2, 163), "Coaching 6 AM-1 PM | Target 3-6 Months", font=fnt(FONT_REGULAR, 24), fill=C_LBLUE, anchor="mm") # Gold line separator draw.rectangle([(PAD_X, BANNER_H-5),(W-PAD_X, BANNER_H-1)], fill=C_GOLD) # ── SCHEDULE ROWS ─────────────────────────────────────────────── f_time = fnt(FONT_BOLD, 24) f_act_n = fnt(FONT_BOLD, 27) f_act_c = fnt(FONT_BOLD, 30) # coaching special f_badge = fnt(FONT_BOLD, 18) f_icon = fnt(FONT_REGULAR, 28) ICONS = {"MRN":"☀","REV":"📖","COA":"🏫","BRK":"☕","STU":"📚","SLP":"😴"} # Fallback text icons if emoji not rendered well ICONS_TXT = {"MRN":"*","REV":"R","COA":"C","BRK":"-","STU":"S","SLP":"Z"} for i, (time_str, activity, badge_txt, typ) in enumerate(SCHEDULE): bg, left_col, fg_time, fg_act, badge_bg, badge_fg = ROW_STYLES[typ] y0 = BANNER_H + GAP_TOP + i*(ROW_H + ROW_GAP) y1 = y0 + ROW_H x0, x1 = PAD_X, W - PAD_X # Drop shadow draw.rounded_rectangle([(x0+4, y0+5),(x1+4, y1+5)], radius=ROW_R, fill=(10,20,35)) # Row card background draw.rounded_rectangle([(x0, y0),(x1, y1)], radius=ROW_R, fill=bg) # Left accent bar draw.rounded_rectangle([(x0, y0),(x0+12, y1)], radius=ROW_R, fill=left_col) # Coaching: golden border if typ == "COA": draw.rounded_rectangle([(x0, y0),(x1, y1)], radius=ROW_R, outline=C_GOLD, width=5) draw.rounded_rectangle([(x0, y0),(x0+12, y1)], radius=ROW_R, fill=C_GOLD) text_x = x0 + 12 + 18 cy = (y0 + y1) // 2 # vertical center # Time draw.text((text_x, cy - 20), time_str, font=f_time, fill=fg_time, anchor="lm") # Activity act_font = f_act_c if typ == "COA" else f_act_n draw.text((text_x, cy + 20), activity, font=act_font, fill=fg_act, anchor="lm") # Badge (pill on right) badge_margin = 18 tw = draw.textlength(badge_txt, font=f_badge) pill_w = int(tw) + 28 pill_h = 36 bx1_ = x1 - badge_margin bx0_ = bx1_ - pill_w by0_ = cy - pill_h//2 by1_ = cy + pill_h//2 draw.rounded_rectangle([(bx0_, by0_),(bx1_, by1_)], radius=pill_h//2, fill=badge_bg) if typ == "COA": draw.rounded_rectangle([(bx0_, by0_),(bx1_, by1_)], radius=pill_h//2, outline=C_NAVY, width=2) draw.text(((bx0_+bx1_)//2, (by0_+by1_)//2), badge_txt, font=f_badge, fill=badge_fg, anchor="mm") # ── FOOTER ────────────────────────────────────────────────────── footer_y = BANNER_H + GAP_TOP + 13*(ROW_H + ROW_GAP) - ROW_GAP + 14 draw.rectangle([(0, footer_y),(W, H)], fill=C_NAVY) draw.rectangle([(0, footer_y),(W, footer_y+4)], fill=C_GOLD) quote_y = footer_y + (H - footer_y)//2 draw.text((W//2, quote_y), "Stay Focused. Clear RAS Pre!", font=fnt(FONT_BOLD, 28), fill=C_GOLD, anchor="mm") # Save img.save(OUTPUT, "PNG") sz = os.path.getsize(OUTPUT)/1024 print(f"Saved: {OUTPUT} ({sz:.0f} KB) {W}x{H}px") PYEOF python /tmp/workspace/ras-timetable/create_wallpaper_v2.py 2>&1

Loading Image
Running Command

python3 -c " from PIL import Image img = Image.open('/tmp/workspace/ras-timetable/RAS_Pre_Wallpaper.png') print('Size:', img.size, '| Mode:', img.mode) # Check a few pixel colors to verify layout pixels = [(540, 100), (540, 300), (540, 500), (540, 900), (540, 1800)] for px in pixels: print(f' px{px} = {img.getpixel(px)}') "

Pixels confirm: Navy header (100), Grey morning row (300), Navy coaching (500), Yellow break (900), Sleep blue (1800). Layout is perfect! Your wallpaper is ready:

RAS Pre Wallpaper

Image · PNG


Wallpaper Details

Size: 1080 x 1920 px (Full HD portrait - fits all Android & iPhone screens)

Design Layout

Top Banner (Navy + Gold)
  • "RAS PRE" in large gold text
  • "DAILY STUDY TIMETABLE" subtitle
  • Coaching hours + target info
  • Decorative arc accent in top-right corner
13 Timetable Cards (each with rounded corners + drop shadow)
Card ColorBlock Type
Dark Navy + Gold borderCoaching (6AM-1PM) - stands out
Light GreenSelf-Study blocks
YellowBreak / Meal slots
Light BlueSleep block
GreyMorning routine
Green tintRevision slots
Each card shows:
  • Time slot (bold, color-coded)
  • Activity name
  • Pill badge on right (COACHING / STUDY / BREAK / SLEEP / REVISION)
Footer - Gold motivational quote on navy background

How to Set as Wallpaper

  1. Transfer the PNG to your phone
  2. Go to Settings > Wallpaper (iOS) or Settings > Display > Wallpaper (Android)
  3. Select the image and set as Lock Screen wallpaper - you'll see your schedule every time you pick up your phone!
This is a shared conversation. Sign in to Orris to start your own chat.