more complex
This commit is contained in:
@@ -14,10 +14,10 @@ DAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
|
||||
|
||||
HEADER_FILL = PatternFill(start_color="1F4E78", end_color="1F4E78", fill_type="solid")
|
||||
HEADER_FONT = Font(color="FFFFFF", bold=True)
|
||||
LUNCH_FILL = PatternFill(start_color="D9D9D9", end_color="D9D9D9", fill_type="solid")
|
||||
GENERAL_FILL = PatternFill(start_color="FFF2CC", end_color="FFF2CC", fill_type="solid")
|
||||
LAB_FILL = PatternFill(start_color="D9EAD3", end_color="D9EAD3", fill_type="solid")
|
||||
THEORY_FILL = PatternFill(start_color="DDEBF7", end_color="DDEBF7", fill_type="solid")
|
||||
LONG_LECTURE_FILL = PatternFill(start_color="F4CCCC", end_color="F4CCCC", fill_type="solid")
|
||||
THIN_BORDER = Border(
|
||||
left=Side(style="thin"), right=Side(style="thin"),
|
||||
top=Side(style="thin"), bottom=Side(style="thin"),
|
||||
@@ -28,6 +28,8 @@ CENTER = Alignment(horizontal="center", vertical="center", wrap_text=True)
|
||||
def cell_fill_for(session):
|
||||
if session is None:
|
||||
return None
|
||||
if session.get("duration_minutes") == 120:
|
||||
return LONG_LECTURE_FILL
|
||||
if session.get("is_general"):
|
||||
return GENERAL_FILL
|
||||
if session.get("course_type") == "lab":
|
||||
@@ -35,16 +37,21 @@ def cell_fill_for(session):
|
||||
return THEORY_FILL
|
||||
|
||||
|
||||
def build_grid_sheet(ws, title, subtitle, time_slots, sessions_by_day_slot, cell_text_fn):
|
||||
def build_grid_sheet(ws, title, subtitle, display_rows, sessions_by_cell, cell_text_fn):
|
||||
"""
|
||||
Renders one timetable grid onto worksheet `ws`.
|
||||
|
||||
time_slots: ordered list of dicts: {"label": str, "start": str, "end": str,
|
||||
"is_lunch": bool}
|
||||
sessions_by_day_slot: dict[(day, slot_index)] -> session dict (or list of
|
||||
session dicts for slots spanning a double/lab period), used
|
||||
only to decide fill color via cell_fill_for().
|
||||
cell_text_fn: function(day, slot_index) -> str to render into the cell.
|
||||
display_rows: ordered list of dicts, one per rendered row:
|
||||
{"label": str, "start": str, "end": str,
|
||||
"slot_index": int, "duration_minutes": int}
|
||||
The special 08:30-10:30 long-lecture row and the normal
|
||||
09:00-10:30 row both use slot_index 0 (they clash-track
|
||||
against the same slot) but are distinguished by
|
||||
duration_minutes (120 vs 90) so they render as separate rows.
|
||||
sessions_by_cell: dict[(day, slot_index, duration_minutes)] -> session
|
||||
dict, used only to decide fill color via cell_fill_for().
|
||||
cell_text_fn: function(day, slot_index, duration_minutes) -> str to
|
||||
render into the cell.
|
||||
"""
|
||||
invalid_chars = ':\\/?*[]'
|
||||
sheet_name = "".join(c for c in title if c not in invalid_chars)
|
||||
@@ -74,14 +81,12 @@ def build_grid_sheet(ws, title, subtitle, time_slots, sessions_by_day_slot, cell
|
||||
c.alignment = CENTER
|
||||
c.border = THIN_BORDER
|
||||
|
||||
for row_offset, slot in enumerate(time_slots):
|
||||
for row_offset, slot in enumerate(display_rows):
|
||||
row = header_row + 1 + row_offset
|
||||
time_cell = ws.cell(row=row, column=1, value=f'{slot["start"]} - {slot["end"]}')
|
||||
time_cell.font = Font(bold=True, size=9)
|
||||
time_cell.alignment = CENTER
|
||||
time_cell.border = THIN_BORDER
|
||||
if slot.get("is_lunch"):
|
||||
time_cell.fill = LUNCH_FILL
|
||||
|
||||
for col, day in enumerate(DAYS, start=2):
|
||||
cell = ws.cell(row=row, column=col)
|
||||
@@ -89,15 +94,10 @@ def build_grid_sheet(ws, title, subtitle, time_slots, sessions_by_day_slot, cell
|
||||
cell.alignment = CENTER
|
||||
cell.font = Font(size=9)
|
||||
|
||||
if slot.get("is_lunch"):
|
||||
cell.fill = LUNCH_FILL
|
||||
cell.value = "LUNCH BREAK"
|
||||
continue
|
||||
|
||||
text = cell_text_fn(day, row_offset)
|
||||
text = cell_text_fn(day, slot["slot_index"], slot["duration_minutes"])
|
||||
cell.value = text if text else ""
|
||||
|
||||
session = sessions_by_day_slot.get((day, row_offset))
|
||||
session = sessions_by_cell.get((day, slot["slot_index"], slot["duration_minutes"]))
|
||||
fill = cell_fill_for(session)
|
||||
if fill:
|
||||
cell.fill = fill
|
||||
@@ -106,7 +106,7 @@ def build_grid_sheet(ws, title, subtitle, time_slots, sessions_by_day_slot, cell
|
||||
for col in range(2, 2 + len(DAYS)):
|
||||
ws.column_dimensions[get_column_letter(col)].width = 26
|
||||
|
||||
for row_offset in range(len(time_slots)):
|
||||
for row_offset in range(len(display_rows)):
|
||||
ws.row_dimensions[header_row + 1 + row_offset].height = 42
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user