File size: 6,002 Bytes
63dc9b9 2d12975 63dc9b9 2d12975 63dc9b9 2d12975 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | 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()
|