saptak21's picture
Update app.py
989e952 verified
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)