saptak21's picture
Update app.py
2d12975 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
with gr.Blocks() as iface:
gr.Image(
value="https://drive.google.com/uc?id=1nmhNC3JjyU9YsVh-bzgzAmQZgloqNtEQ",
height=158,
width=158,
show_label=False,
container=False
)
#gr.Markdown("## πŸ§‘β€πŸ« RKMRC Exam Invigilator Duty Allocation System")
gr.Markdown("<h1 style='text-align: center;'>πŸ§‘β€πŸ« RKMRC Exam Invigilator Duty Allocation System</h1>")
gr.Markdown("πŸ“ Upload your Excel files and click 'Submit' to generate duty assignments.")
teachers_file = gr.File(label="πŸ“˜ Teachers Excel File")
exams_file = gr.File(label="πŸ“ Exam Summary Excel File")
buffer_slider = gr.Slider(minimum=0, maximum=2, step=0.1, label="Duty Buffer", value=0.5)
submit_btn = gr.Button("Submit")
duty_assignments = gr.Dataframe(label="βœ… Duty Assignments")
unassigned_duties = gr.Dataframe(label="⚠️ Unassigned Duties")
teacher_summary = gr.Dataframe(label="πŸ‘¨β€πŸ« Teacher Summary")
total_hours_text = gr.Textbox(label="Total Invigilator Hours")
avg_duty_text = gr.Textbox(label="Average Duty per Teacher")
download_file = gr.File(label="πŸ“Š Download Duty Allocation Summary")
submit_btn.click(
fn=run_allocation,
inputs=[teachers_file, exams_file, buffer_slider],
outputs=[
duty_assignments,
unassigned_duties,
teacher_summary,
total_hours_text,
avg_duty_text,
download_file
]
)
iface.launch()