Spaces:
Sleeping
Sleeping
| 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.") | |