Timetable_app / app.py
Munwar92's picture
Update app.py
4dd2be4 verified
import streamlit as st
import pandas as pd
from ortools.sat.python import cp_model
# Initialize session state if not already done
if "timetable" not in st.session_state:
st.session_state.timetable = pd.DataFrame(columns=["Day", "Time", "Subject", "Teacher", "Room"])
if "subjects" not in st.session_state:
st.session_state.subjects = {}
if "teachers" not in st.session_state:
st.session_state.teachers = []
if "rooms" not in st.session_state:
st.session_state.rooms = []
# App title
st.title("Subject Timetable Generator")
# Sidebar inputs to add data
st.sidebar.header("Add Data")
# Add subjects with weekly slots
subject = st.sidebar.text_input("Enter Subject Name")
weekly_slots = st.sidebar.number_input("Number of Weekly Slots", min_value=1, max_value=10, step=1)
if st.sidebar.button("Add Subject"):
if subject and weekly_slots > 0:
st.session_state.subjects[subject] = weekly_slots
st.success(f"Added Subject: {subject} with {weekly_slots} slots per week")
else:
st.error("Please provide a valid subject and weekly slots.")
# Add teachers
teacher = st.sidebar.text_input("Enter Teacher Name")
if st.sidebar.button("Add Teacher"):
if teacher:
st.session_state.teachers.append(teacher)
st.success(f"Added Teacher: {teacher}")
else:
st.error("Teacher name cannot be empty!")
# Add rooms
room = st.sidebar.text_input("Enter Room Name")
if st.sidebar.button("Add Room"):
if room:
st.session_state.rooms.append(room)
st.success(f"Added Room: {room}")
else:
st.error("Room name cannot be empty!")
# Show current data
st.write("### Current Data")
st.write("**Subjects:**", st.session_state.subjects)
st.write("**Teachers:**", st.session_state.teachers)
st.write("**Rooms:**", st.session_state.rooms)
# Timetable generation logic with debugging
def generate_timetable(subjects, teachers, rooms, time_slots, days):
model = cp_model.CpModel()
schedule = {}
# Create variables for each subject-teacher-room-time-slot combination
for subject, slots in subjects.items():
for teacher in teachers:
for room in rooms:
for day in days:
for time_slot in time_slots:
schedule[(subject, teacher, room, day, time_slot)] = model.NewBoolVar(
f"{subject}_{teacher}_{room}_{day}_{time_slot}"
)
# Constraints: Each subject should have the required number of weekly slots
for subject, slots in subjects.items():
model.Add(
sum(
schedule[(subject, teacher, room, day, time_slot)]
for teacher in teachers
for room in rooms
for day in days
for time_slot in time_slots
) == slots
)
# Constraints: No teacher or room should be double-booked
for teacher in teachers:
for day in days:
for time_slot in time_slots:
model.Add(
sum(
schedule[(subject, teacher, room, day, time_slot)]
for subject in subjects
for room in rooms
) <= 1 # A teacher can only be in one class at a time
)
for room in rooms:
for day in days:
for time_slot in time_slots:
model.Add(
sum(
schedule[(subject, teacher, room, day, time_slot)]
for subject in subjects
for teacher in teachers
) <= 1 # A room can only be used for one subject at a time
)
# Solve the model
solver = cp_model.CpSolver()
status = solver.Solve(model)
# Debugging: Print the solver status and results
if status != cp_model.OPTIMAL:
st.error(f"Solver failed to find a solution. Solver status: {status}")
return []
result = []
for key, var in schedule.items():
if solver.Value(var) == 1:
result.append(key)
return result
# Time slots and days for timetable
time_slots = [f"{hour}:00 - {hour+1}:00" for hour in range(8, 18)] # 8 AM to 6 PM
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
# Generate timetable button
if st.button("Generate Timetable"):
timetable = generate_timetable(
st.session_state.subjects, st.session_state.teachers, st.session_state.rooms, time_slots, days
)
if timetable:
# Store the generated timetable
for entry in timetable:
subject, teacher, room, day, time_slot = entry
st.session_state.timetable = pd.concat(
[st.session_state.timetable, pd.DataFrame([[day, time_slot, subject, teacher, room]],
columns=["Day", "Time", "Subject", "Teacher", "Room"])],
ignore_index=True
)
st.success("Timetable generated successfully!")
else:
st.error("Failed to generate timetable. Check constraints!")
# Display the generated timetable
st.write("### Generated Timetable")
if not st.session_state.timetable.empty:
st.dataframe(st.session_state.timetable)
st.download_button(
"Download Timetable (CSV)",
data=st.session_state.timetable.to_csv(index=False),
file_name="timetable.csv",
mime="text/csv"
)
else:
st.write("No timetable generated yet.")