Spaces:
Build error
Build error
| from transformers import pipeline | |
| import pandas as pd | |
| import math | |
| import gradio as gr | |
| # Step 1: Load Excel Files (Not needed for Gradio, files are loaded in run_allocation) | |
| # Step 2: Calculate Total Hours and Average Duty (n) | |
| def calculate_average_duty(exams_df, teachers_df): | |
| grouped = exams_df.groupby(['Day', 'Slot', 'Room Number'])['Student Number'].sum().reset_index(name='TotalStudents') | |
| def compute_invigilators(x): | |
| n = math.ceil(x / 20) | |
| while (20 * n + 10) < x: | |
| n += 1 | |
| return n | |
| grouped['RequiredInvigilators'] = grouped['TotalStudents'].apply(compute_invigilators) | |
| exams_df = pd.merge( | |
| exams_df, | |
| grouped[['Day', 'Slot', 'Room Number', 'RequiredInvigilators']], | |
| on=['Day', 'Slot', 'Room Number'], | |
| how='left' | |
| ) | |
| exams_df['Duration'] = exams_df['Duration'].astype(int) | |
| total_invigilator_hours = sum(exams_df['RequiredInvigilators'] * exams_df['Duration']) | |
| n = total_invigilator_hours / len(teachers_df) | |
| return n, total_invigilator_hours, exams_df | |
| # Step 3: Assign Initial Duty Limits Based on Designation | |
| def assign_initial_duties(teachers_df, avg_duty): | |
| teachers_df['DESIG'] = teachers_df['DESIG'].str.strip().str.upper() | |
| def get_duty_limit(desig, avg): | |
| if desig == "SACT": | |
| return avg - 2 | |
| elif desig in ["LAB", "HOD", "BURSAR", "AQAC"]: | |
| return avg - 1 | |
| else: | |
| return avg # Default for A.P. and others | |
| teachers_df['DutyLimit'] = teachers_df['DESIG'].apply(lambda d: get_duty_limit(d, math.ceil(avg_duty))) | |
| teachers_df['AssignedHours'] = 0 | |
| teachers_df['AssignedDays'] = [[] for _ in range(len(teachers_df))] | |
| return teachers_df | |
| # Step 4: Assign Duties | |
| def assign_duties(teachers_df, exams_df, buffer=0.5): | |
| assignments = [] | |
| unassigned = [] | |
| unique_sessions = exams_df[['Day', 'Slot', 'Room Number', 'Duration', 'RequiredInvigilators']].drop_duplicates() | |
| for _, exam in unique_sessions.iterrows(): | |
| date = exam['Day'] | |
| time = exam['Slot'] | |
| duration = int(exam['Duration']) | |
| room = exam['Room Number'] | |
| required_invigilators = int(exam['RequiredInvigilators']) | |
| for _ in range(required_invigilators): | |
| available_teachers = teachers_df[ | |
| (teachers_df['AssignedHours'] + duration <= teachers_df['DutyLimit'] + buffer) & | |
| (~teachers_df['AssignedDays'].apply(lambda x: (date, time) in x)) | |
| ] | |
| if available_teachers.empty: | |
| unassigned.append({ | |
| 'Day': date, 'Slot': time, 'Room': room, | |
| 'Duration': duration, 'Reason': 'No available teacher' | |
| }) | |
| continue | |
| available_teachers = available_teachers.sort_values(by='AssignedHours') | |
| selected_teacher = available_teachers.head(1) | |
| idx = selected_teacher.index[0] | |
| teachers_df.at[idx, 'AssignedHours'] += duration | |
| teachers_df.at[idx, 'AssignedDays'].append((date, time)) | |
| assignments.append({ | |
| 'Day': date, | |
| 'Slot': time, | |
| 'Room': room, | |
| 'Duration': duration, | |
| 'Teacher': teachers_df.at[idx, 'NAME'], | |
| 'Designation': teachers_df.at[idx, 'DESIG'], | |
| 'AssignedHoursAfter': teachers_df.at[idx, 'AssignedHours'] | |
| }) | |
| return pd.DataFrame(assignments), pd.DataFrame(unassigned) | |
| # Function to run the allocation process | |
| def run_allocation(teachers_file, exams_file, buffer=0.5): | |
| try: | |
| teachers_df = pd.read_excel(teachers_file.name) | |
| exams_df = pd.read_excel(exams_file.name) | |
| n, total_hours, exams_df = calculate_average_duty(exams_df, teachers_df) | |
| teachers_df = assign_initial_duties(teachers_df, n) | |
| assignments_df, unassigned_df = assign_duties(teachers_df, exams_df, buffer=buffer) | |
| # Save assignments to Excel for download | |
| assignments_df.to_excel("duty_allocation_summary.xlsx", index=False) | |
| # Return DataFrames, summary, and file path for display and download | |
| return assignments_df, unassigned_df, teachers_df[['NAME', 'DESIG', 'AssignedHours', 'DutyLimit']], total_hours, n, "duty_allocation_summary.xlsx" | |
| except Exception as e: | |
| return None, None, None, None, str(e), None # Return None for file path on error | |
| # Gradio Interface | |
| iface = gr.Interface( | |
| fn=run_allocation, | |
| inputs=[ | |
| gr.File(label="Teachers Excel File"), | |
| gr.File(label="Exam Summary Excel File"), | |
| gr.Slider(minimum=0, maximum=2, step=0.1, label="Duty Buffer", value=0.5), | |
| ], | |
| outputs=[ | |
| gr.Dataframe(label="Duty Assignments"), | |
| gr.Dataframe(label="Unassigned Duties"), | |
| gr.Dataframe(label="Teacher Summary"), | |
| gr.Textbox(label="Total Invigilator Hours"), | |
| gr.Textbox(label="Average Duty per Teacher"), | |
| gr.File(label="Download Duty Allocation Summary") # Add File component for download | |
| ], | |
| title="🧑🏫 Duty Allocation System", | |
| description="Upload your Excel files and click 'Submit' to generate duty assignments." | |
| ) | |
| iface.launch(inline = False) | |