"""Renders one timetable grid per instructor.""" import sys import os _ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") sys.path.insert(0, os.path.join(_ROOT, "app")) sys.path.insert(0, os.path.join(_ROOT, "controller")) from xlsx_grid_helper import build_grid_sheet, new_workbook, save_workbook # noqa: E402 from template_controller import TIME_SLOTS as GRID_TIME_SLOTS # noqa: E402 from template_logger import log_error # noqa: E402 def generate_teacher_wise_templates(sessions, data, output_dir): written = [] # instructors.csv has one row per (instructor, course, section) teaching # assignment, so the same instructor_code can repeat; render one sheet # per unique instructor, listing all of their assignments in the subtitle. seen_codes = [] assignments_by_code = {} name_by_code = {} for row in data["instructors"]: code = row["instructor_code"] if code not in assignments_by_code: seen_codes.append(code) assignments_by_code[code] = [] name_by_code[code] = row["instructor_name"] assignments_by_code[code].append(f'{row["course_id"]} (Sec {row["section_id"]})') for code in seen_codes: instructor_name = name_by_code[code] instr_sessions = [s for s in sessions if s["instructor_code"] == code] # A teacher can only be in one place at a time: each (day, slot) # must resolve to exactly one session. If the schedule places more # than one, that's a real scheduling error - log it instead of # silently picking/overwriting one. raw_by_day_slot = {} for s in instr_sessions: for slot_index in s["slot_indices"]: raw_by_day_slot.setdefault((s["day"], slot_index), []).append(s) by_day_slot = {} for (day, slot_index), entries in raw_by_day_slot.items(): if len(entries) > 1: course_list = ", ".join( f'{e["course_id"]} ({e["course_type"]}) for batch(es) {"+".join(e["batch_codes"])} in {e["room_id"]}' for e in entries ) log_error( f"Teacher conflict: {instructor_name} ({code}) is double-booked on " f"{day} slot {slot_index}: {course_list}" ) by_day_slot[(day, slot_index)] = entries[0] def cell_text(day, slot_index, raw_by_day_slot=raw_by_day_slot): entries = raw_by_day_slot.get((day, slot_index)) if not entries: return "" s = entries[0] tag = " (Lab)" if s["course_type"] == "lab" else (" (General)" if s["is_general"] else "") batches = "+".join(s["batch_codes"]) text = f'{s["course_name"]}{tag} [Sec {s["section_id"]}]\n{batches}\n{s["room_id"]}' if len(entries) > 1: text = "CONFLICT!\n" + text return text subtitle = "Teaches: " + ", ".join(assignments_by_code[code]) wb = new_workbook() ws = wb.active build_grid_sheet( ws, title=f'{instructor_name} ({code})', subtitle=subtitle, time_slots=GRID_TIME_SLOTS, sessions_by_day_slot=by_day_slot, cell_text_fn=cell_text, ) path = save_workbook(wb, output_dir, f"{code}.xlsx") written.append(path) return written