Ras Pre time table
Ras Pre time table Coching time 6:00 am to 1:00 pm
| Time | Activity |
|---|---|
| 5:00 - 5:30 AM | Wake up, freshen up, light exercise/yoga |
| 5:30 - 6:00 AM | Quick revision of previous day's notes (30 min) |
| 6:00 - 1:00 PM | 🏫 COACHING CLASSES |
| 1:00 - 2:00 PM | Lunch + Rest (mandatory break) |
| 2:00 - 4:00 PM | Self-Study - Revise today's coaching topics |
| 4:00 - 4:15 PM | Short break / tea |
| 4:15 - 6:15 PM | Self-Study - Rajasthan GK / Current Affairs |
| 6:15 - 7:00 PM | Evening walk / relaxation |
| 7:00 - 8:30 PM | Self-Study - Weak subject or Mock Practice |
| 8:30 - 9:00 PM | Dinner |
| 9:00 - 10:00 PM | Daily Current Affairs (newspaper + notes) |
| 10:00 - 10:30 PM | Quick notes review + next day planning |
| 10:30 PM | Sleep (minimum 7 hours) |
| Day | Morning Revision (5:30-6:00) | Afternoon (2-4 PM) | Evening (4:15-6:15 PM) | Night (7-8:30 PM) |
|---|---|---|---|---|
| Mon | History notes | History (India) | Rajasthan History | Mock MCQs |
| Tue | Geography notes | Geography (India) | Rajasthan Geography | Map Practice |
| Wed | Polity notes | Indian Polity | Raj. Polity/Admin | PYQ Practice |
| Thu | Economy notes | Indian Economy | Raj. Economy | Mock Test |
| Fri | Science notes | General Science | Environment | Weak Subject |
| Sat | Current Affairs | Full Revision | Rajasthan GK | Weekly Mock Test |
| Sun | Rest/Light study | Test Analysis | Current Affairs | Revision + Planning |
| Week | Activity |
|---|---|
| Weeks 1-4 | Topic-wise MCQs (chapter-by-chapter) |
| Weeks 5-8 | Subject-wise full mock tests |
| Weeks 9-12 | Full-length RAS Pre mock tests (100 Q / 2 hrs) |
| Weeks 13-16 | PYQs + error analysis + rapid revision |
Create an Excel timetable with reminder alerts
mkdir -p /tmp/workspace/ras-timetable && ls /tmp/workspace/ras-timetable/
~/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}")
cd /tmp/workspace/ras-timetable && python create_timetable.py
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) "
RAS Pre Timetable
Spreadsheet · XLSX
SetupReminders macro sets all daily alarms.xlsm (Excel Macro-Enabled Workbook) - File > Save As > select .xlsmSetupReminders macro - alerts will fire as pop-ups at each time!Create a printable PDF version I can post on my study wall
~/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")
cd /tmp/workspace/ras-timetable && python create_poster_pdf.py 2>&1
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) "
~/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")
~/ras-timetable/create_poster_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/ras-timetable/create_poster_pdf.py'
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"
cd /tmp/workspace/ras-timetable && python create_poster_v2.py 2>&1
RAS Pre StudyWall Poster
PDF Document · PDF
| Column | Content |
|---|---|
| Left | Weekly 7-day subject rotation grid |
| Middle | Key Rules & Reminders + Mock Test plan + Daily hours breakdown |
| Right | Subject color legend |
Create a mobile phone wallpaper (1080x1920px) with the daily schedule
python3 -c "from PIL import Image; print('Pillow OK')" 2>&1
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
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"
cd /tmp/workspace/ras-timetable && python create_wallpaper.py 2>&1
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') "
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}') "
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
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)}') "
RAS Pre Wallpaper
Image · PNG
| Card Color | Block Type |
|---|---|
| Dark Navy + Gold border | Coaching (6AM-1PM) - stands out |
| Light Green | Self-Study blocks |
| Yellow | Break / Meal slots |
| Light Blue | Sleep block |
| Grey | Morning routine |
| Green tint | Revision slots |