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.")