Powered by constraint programming • Built with love for educators
Smooth • Stable • Alive
Quick Start • Features • Documentation • Demo
Smart Timetable Builder is a next-generation scheduling solution that transforms the complex task of school timetable creation into an elegant, visual experience. Combining Google's OR-Tools constraint solver with a beautifully animated dark-themed interface, it generates mathematically guaranteed clash-free schedules while providing real-time analytics, scenario simulation, and stunning visualizations.
| Constraint programming ensures zero conflicts. No manual checking needed. | Fluid animations, glowing transitions, and a modern dark theme. | Visual heatmaps and energy fields reveal insights at a glance. |
- Zero Conflicts Guaranteed - Mathematical proof via constraint programming
- 5 What-If Scenarios - Test disruptions without touching base timetable
- 4 Visual Analytics - Heatmaps for load, fatigue, congestion, clashes
- 4 Energy Maps - Animated Plotly fields with glowing orbs and wave motion
- Auto-Save Everything - 8 JSON files persist all data across sessions
- Chrome-Style History - Full audit trail with timestamps
- Demo Data Included - 12 teachers, 6 classes, 164 periods ready to go
- Professional PDFs - Print-ready A4 exports for classes and teachers
| Clash-Free Generation | No teacher or class double-booking (hard constraint) |
| Priority Scheduling | Important subjects scheduled earlier in the day (optional) |
| Teacher Constraints | Respect max periods per day + max periods per week |
| Break Periods | Configurable breaks (e.g., "4, Lunch Break" or "7, Tea Break") |
| Weekly Rotation | 3-week automatic rotation for fairness |
| OR-Tools Solver | Google's constraint programming solver (CP-SAT) |
Simulate disruptions without modifying the base timetable:
| Scenario | Description | Use Case |
|---|---|---|
| Teacher Absent | Mark teacher unavailable, auto-substitute or free period | Sick leave, training |
| Substitute Teacher | Assign replacement teacher for specific classes | Planned absence |
| Lab Unavailable | Mark lab subjects (Physics, Chemistry, Biology) as free | Maintenance, exams |
| Shortened Day | Reduce max periods for the day | Half-day schedule |
| Emergency Free | Force specific class/period to be free | Assembly, event |
┌─────────────────────────────────────────────────────────────┐
│ Teacher Load │ Periods per teacher per day │
│ Day Congestion │ Total teaching periods per day │
│ Class Fatigue │ Heavy subject clustering │
│ Clash Risk │ Overload and conflict detection │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Teacher Load │ Glowing orbs sized by workload │
│ Fatigue Flow │ Ripple effects show heavy clusters│
│ Congestion │ Pulsing gradients per day │
│ Impact Diffusion │ Wave propagation from changes │
└─────────────────────────────────────────────────────────────┘
Controls: Animation Speed • Glow Intensity • Motion Toggle
All data automatically saves to data/ directory:
data/
├── teachers.json # Teacher definitions
├── classes.json # Class and subject assignments
├── priority_configs.json # Priority settings per class
├── config.json # School configuration
├── history.json # Activity log (last 500 entries)
├── demo_loaded.json # Demo data flag
├── base_timetable.json # Generated timetable
└── scenario_state.json # What-If Lab scenarios
|
Smooth Animations
|
Intuitive Interface
|
Modern, eye-friendly design:
- Background:
#0f0f0f - Containers:
#18181b - Borders:
#27272a - Text:
#fafafa/#e4e4e7/#a1a1aa
Python 3.8 or higher
pip package manager
4GB RAM recommended# Clone the repository
git clone https://github.com/yourusername/smart-timetable-builder.git
cd smart-timetable-builder
# Install dependencies
pip install -r requirements.txtstreamlit run app.pyApplication opens at: http://localhost:8501
|
1. Load Demo Click "Load Demo Data" in sidebar 12 teachers + 6 classes ready to use |
2. Generate Navigate to "Class Timetables" tab Click "Generate Timetable" Solver runs ~2-5 seconds |
3. Explore View results, try scenarios, check analytics All features now unlocked! |
| Stream | Teacher | Subjects | Max/Day |
|---|---|---|---|
| Science | Eric Simon | Physics | 5 |
| Aisha Khan | Chemistry | 5 | |
| Rahul Mehta | Mathematics | 5 | |
| Neha Verma | Biology | 5 | |
| Commerce | Priya Nair | Economics | 5 |
| Arjun Patel | Accountancy | 5 | |
| Kavita Rao | Business Studies | 4 | |
| Humanities | Sofia Mendes | History | 5 |
| Aman Gupta | Political Science | 5 | |
| Ritu Chawla | Geography | 4 | |
| Common | Daniel Brooks | English (all streams) | 4 |
| Marcus Lee | Physical Education (all) | 3 |
┌─────────┬────────────────────────────────────────────────┬────────┐
│ Class │ Subjects (periods/week) │ Total │
├─────────┼────────────────────────────────────────────────┼────────┤
│ 11SCI │ Physics(6) • Chemistry(6) • Math(6) │ 30 │
│ │ Biology(6) • English(4) • PE(2) │ │
├─────────┼────────────────────────────────────────────────┼────────┤
│ 12SCI │ Physics(6) • Chemistry(6) • Math(6) │ 30 │
│ │ Biology(6) • English(4) • PE(2) │ │
├─────────┼────────────────────────────────────────────────┼────────┤
│ 11COM │ Accountancy(6) • Business(6) • Economics(6) │ 28 │
│ │ Math(4) • English(4) • PE(2) │ │
├─────────┼────────────────────────────────────────────────┼────────┤
│ 12COM │ Accountancy(6) • Business(6) • Economics(6) │ 28 │
│ │ Math(4) • English(4) • PE(2) │ │
├─────────┼────────────────────────────────────────────────┼────────┤
│ 11HUM │ History(6) • PolSci(6) • Geography(6) │ 24 │
│ │ English(4) • PE(2) │ │
├─────────┼────────────────────────────────────────────────┼────────┤
│ 12HUM │ History(6) • PolSci(6) • Geography(6) │ 24 │
│ │ English(4) • PE(2) │ │
└─────────┴────────────────────────────────────────────────┴────────┘
Total: 164 periods/week across 6 classes
┌────────────────────────────────────────────────────────────────────┐
│ Teachers & Saved History Class Teacher │
│ Classes Data Timetables Timetables │
│ │
│ Rotation What-If Insights Energy PDF │
│ Lab Maps Export │
└────────────────────────────────────────────────────────────────────┘
Days: Mon,Tue,Wed,Thu,Fri
Periods per day: 8
Break Periods:
4, Lunch Break
7, Tea BreakClick "Apply Config" to save.
Navigate to "Teachers & Classes" tab:
┌─────────────────────────────────────┐
│ Teacher ID: Eric Simon │
│ Subjects: Physics │
│ Sections: 11SCI, 12SCI │
│ Max Periods/Day: 5 │
│ │
│ [Save] [Cancel] │
└─────────────────────────────────────┘
Result: Toast notification " Teacher Eric Simon added"
Scroll to "2. Add Classes" section:
┌─────────────────────────────────────┐
│ Class ID: 11SCI │
│ │
│ Add Subjects: │
│ • Physics: 6 periods → Eric Simon │
│ • Chemistry: 6 periods → Aisha Khan │
│ • Math: 6 periods → Rahul Mehta │
│ ... │
│ │
│ [Save] [Cancel] │
└─────────────────────────────────────┘
Expand each class to configure:
Priorities for 11SCI:
┌─────────────────────────────────────┐
│ Priority (early) subjects: │
│ Physics, Chemistry, Mathematics │
│ │
│ Weak subjects: │
│ Physics, Chemistry │
│ │
│ Heavy subjects: │
│ Physics, Chemistry, Math, Biology │
│ │
│ [Save] │
└─────────────────────────────────────┘
Navigate to " Class Timetables" tab:
- Click " Generate Timetable"
- Spinner appears: "Solving..."
- Toast: " Timetable generated!"
- View results in tables below
Navigate to " What-If Lab" tab:
Day: [Monday ▼]
Scenarios:
☑ Teacher absent today
└─ Absent teacher: [Eric Simon ▼]
☑ Shortened school day
└─ Max periods today: [6]
Live timetable updates below ↓
Heatmaps ( Insights tab):
Heatmap: [Teacher load ▼]
Displays: Styled dataframe with color gradients
- Green → Yellow → Orange → Red
- Darker = Higher load
Energy Maps ( Energy Maps tab):
Energy Map Type: [Teacher Load Energy Field ▼]
Animation Speed: ————●———— 0.5
Glow Intensity: ————●———— 1.0
Motion: ☑
Displays: Animated Plotly chart with:
- Glowing orbs (teacher workload)
- Smooth gradients
- Wave motion effects
Navigate to " PDF Export" tab:
┌──────────────────────────────────┐
│ Download Class PDFs │
│ Download Teacher PDFs │
└──────────────────────────────────┘
Format: A4, print-ready
@dataclass
class Teacher:
teacher_id: str # Unique ID (e.g., "Eric Simon")
subjects: List[str] # ["Physics"]
sections: List[str] # ["11SCI", "12SCI"]
max_periods_per_day: int = 6 # Daily limit
@dataclass
class ClassSubject:
subject: str # "Physics"
weekly_periods: int # 6
teacher_id: str # "Eric Simon"
@dataclass
class Class:
class_id: str # "11SCI"
subjects: List[ClassSubject] # List of subjects
@dataclass
class SchoolConfig:
days: List[str] = ["Mon", "Tue", "Wed", "Thu", "Fri"]
periods_per_day: int = 8
break_periods: Dict[int, str] = {} # {3: "Lunch", 6: "Tea"}
@dataclass
class ClassPriorityConfig:
class_id: str
priority_subjects: List[str] = [] # Early scheduling
weak_subjects: List[str] = [] # Morning only
heavy_subjects: List[str] = [] # Avoid consecutive┌─────────────────────────────────────────────────────────────┐
│ 1. Session State Init (_init_session) │
│ └─ Load from JSON (all 8 files) │
└──────────────────────┬──────────────────────────────────────┘
│
┌──────────────────────▼──────────────────────────────────────┐
│ 2. Render UI (10 tabs) │
│ └─ Streamlit components + custom CSS │
└──────────────────────┬──────────────────────────────────────┘
│
┌──────────────────────▼──────────────────────────────────────┐
│ 3. User Actions (add/edit/delete/generate) │
│ └─ Form submissions, button clicks │
└──────────────────────┬──────────────────────────────────────┘
│
┌──────────────────────▼──────────────────────────────────────┐
│ 4. Business Logic │
│ ├─ Solver (OR-Tools CP-SAT) │
│ ├─ Scenarios (overlay, no mutation) │
│ └─ Analytics (heatmaps, energy maps) │
└──────────────────────┬──────────────────────────────────────┘
│
┌──────────────────────▼──────────────────────────────────────┐
│ 5. Auto-Save (storage.py → JSON) │
│ └─ Persist to data/ directory │
└──────────────────────┬──────────────────────────────────────┘
│
┌──────────────────────▼──────────────────────────────────────┐
│ 6. Update UI + Show Toast Notification │
│ └─ Fragment reruns, smooth animations │
└─────────────────────────────────────────────────────────────┘
# Hard Constraints (MUST be satisfied)
✓ No teacher conflicts # Teacher can't be in 2 places
✓ No class conflicts # Class can't have 2 subjects
✓ All periods satisfied # Sum matches weekly_periods
✓ Teacher max per day # Respect daily limit
✓ Teacher max per week # Respect weekly limit
# Soft Constraints (Optimization - if priority configs exist)
⚡ Priority subjects early # Morning scheduling
⚡ Weak subjects morning # When students fresh
⚡ Heavy not consecutive # Avoid back-to-backSolver Performance:
- Small (6 classes): ~2 seconds
- Medium (20 classes): ~5-10 seconds
- Large (50+ classes): ~20-60 seconds
# Core Functions
load_teachers() → List[Teacher]
save_teachers(teachers: List[Teacher])
load_classes() → List[Class]
save_classes(classes: List[Class])
load_config() → SchoolConfig
save_config(config: SchoolConfig)
load_priority_configs() → List[ClassPriorityConfig]
save_priority_configs(configs)
# History & State
append_history(action, target, summary, details)
load_history() → List[dict] # Last 500 entries
load_scenario_state() → dict
save_scenario_state(state: dict)
load_base_timetable() → Optional[dict]
save_base_timetable(serialized: dict)
# Utility
is_demo_loaded() → bool
set_demo_loaded()
clear_demo_loaded()
clear_base_timetable()
clear_scenario_state()/* Color Palette */
--bg-primary: #0f0f0f
--bg-secondary: #18181b
--border: #27272a
--text-primary: #fafafa
--text-secondary: #e4e4e7
--text-muted: #a1a1aa
/* Gradients */
--sidebar: linear-gradient(180deg, #18181b 0%, #0f0f0f 100%)/* Fade In */
@keyframes cardFadeIn {
from { opacity: 0; transform: translateY(4px); }
to { opacity: 1; transform: translateY(0); }
}
/* Glow (Changed Cells) */
@keyframes glow {
0% { box-shadow: 0 0 8px 2px #ffd700; }
100% { box-shadow: 0 0 16px 6px #ffec99; }
}
/* Toast Slide */
@keyframes toastFadeIn {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}Stackable toast notifications with live countdown:
show_toast("Timetable generated!", duration_sec=3)Display:
┌─────────────────────────────────┐
│ Timetable generated! 3s │
│ Teacher added 2s │
│ PDF exported 1s │
└─────────────────────────────────┘
Fragment reruns every 1 second via @st.fragment(run_every=timedelta(seconds=1))
Class 11SCI
┌───────────┬──────────┬──────────┬──────────┬────────────┬──────────┬──────────┬──────────┬──────────┐
│ Day │ P1 │ P2 │ P3 │ P4 (Lunch) │ P5 │ P6 │ P7 (Tea) │ P8 │
│ │ 08:00 │ 08:45 │ 09:30 │ 10:15 │ 11:00 │ 11:45 │ 12:30 │ 13:15 │
├───────────┼──────────┼──────────┼──────────┼────────────┼──────────┼──────────┼──────────┼──────────┤
│ Monday │ Physics │ Chemistry│ Math │ BREAK │ Biology │ English │ BREAK │ Free │
├───────────┼──────────┼──────────┼──────────┼────────────┼──────────┼──────────┼──────────┼──────────┤
│ Tuesday │ Chemistry│ Math │ Biology │ BREAK │ Physics │ English │ BREAK │ PE │
├───────────┼──────────┼──────────┼──────────┼────────────┼──────────┼──────────┼──────────┼──────────┤
│ Wednesday │ Math │ Physics │ Chemistry│ BREAK │ English │ Biology │ BREAK │ Free │
├───────────┼──────────┼──────────┼──────────┼────────────┼──────────┼──────────┼──────────┼──────────┤
│ Thursday │ Biology │ Chemistry│ Physics │ BREAK │ Math │ PE │ BREAK │ Free │
├───────────┼──────────┼──────────┼──────────┼────────────┼──────────┼──────────┼──────────┼──────────┤
│ Friday │ English │ Math │ Chemistry│ BREAK │ Physics │ Biology │ BREAK │ Free │
└───────────┴──────────┴──────────┴──────────┴────────────┴──────────┴──────────┴──────────┴──────────┘
Teacher: Eric Simon (Physics) - Max 5 periods/day
┌───────────┬─────────┬─────────┬─────────┬────────────┬─────────┬─────────┬──────────┬─────────┐
│ Day │ P1 │ P2 │ P3 │ P4 (Lunch) │ P5 │ P6 │ P7 (Tea) │ P8 │
├───────────┼─────────┼─────────┼─────────┼────────────┼─────────┼─────────┼──────────┼─────────┤
│ Monday │ 11SCI │ Free │ 12SCI │ BREAK │ Free │ Free │ BREAK │ Free │
├───────────┼─────────┼─────────┼─────────┼────────────┼─────────┼─────────┼──────────┼─────────┤
│ Tuesday │ Free │ 12SCI │ Free │ BREAK │ 11SCI │ Free │ BREAK │ Free │
├───────────┼─────────┼─────────┼─────────┼────────────┼─────────┼─────────┼──────────┼─────────┤
│ Wednesday │ Free │ 11SCI │ Free │ BREAK │ Free │ 12SCI │ BREAK │ Free │
├───────────┼─────────┼─────────┼─────────┼────────────┼─────────┼─────────┼──────────┼─────────┤
│ Thursday │ Free │ Free │ 11SCI │ BREAK │ Free │ Free │ BREAK │ Free │
├───────────┼─────────┼─────────┼─────────┼────────────┼─────────┼─────────┼──────────┼─────────┤
│ Friday │ Free │ Free │ Free │ BREAK │ 12SCI │ Free │ BREAK │ Free │
└───────────┴─────────┴─────────┴─────────┴────────────┴─────────┴─────────┴──────────┴─────────┘
Summary:
• Total periods: 10/40 (25%)
• Periods per day: 2.0 average
• Max daily: 2 periods
• Free periods: 30
Chrome-style activity tracking (last 500 entries):
┌────────────────────────────────────────────────────────────┐
│ 2024-02-15 14:30 — Generated clash-free timetable │
│ Action: generate | Target: Timetable │
├────────────────────────────────────────────────────────────┤
│ 2024-02-15 14:25 — Exported class timetables PDF │
│ Action: export | Target: PDF │
├────────────────────────────────────────────────────────────┤
│ 2024-02-15 14:20 — Updated teacher Eric Simon │
│ Action: edit | Target: Teacher Eric Simon │
├────────────────────────────────────────────────────────────┤
│ 2024-02-15 14:15 — Added class 11SCI │
│ Action: add | Target: Class 11SCI │
└────────────────────────────────────────────────────────────┘
Automatic 3-week rotation system:
Week 1: Original schedule
Week 2: All subjects shifted +1 period (with wraparound)
Week 3: All subjects shifted +2 periods (with wraparound)
Result: Same subject doesn't always fall at same time of day
Benefits: Fairer for students, accounts for energy variations
What-If scenarios auto-save:
{
"selected_day": 0,
"scenarios": {
"teacher_absent": {
"active": true,
"teacher_id": "Eric Simon"
},
"shortened_day": {
"active": true,
"max_periods": 6
},
"substitute": {
"active": false
}
}
}Base timetable never modified - scenarios create live overlay view.
Q: "No solution found" error when generating
Possible Causes:
- Too many periods required vs. available slots
- Teacher max_periods_per_day too restrictive
- Conflicting teacher-subject assignments
Solutions:
# Check math:
total_required = sum(subject.weekly_periods for class in classes
for subject in class.subjects)
available_slots = periods_per_day × days_per_week
# Must satisfy: total_required ≤ available_slots × num_classes
# Check teacher capacity:
teacher_capacity = sum(teacher.max_periods_per_day × days_per_week
for teacher in teachers)
# Must satisfy: total_required ≤ teacher_capacityQuick Fix:
- Reduce subject weekly_periods
- Increase teacher max_periods_per_day
- Add more teachers
Q: Data disappeared after browser refresh
Answer: Check data/ folder exists and has write permissions.
Verify:
ls -la data/
# Should show 8 JSON filesIf missing: Click "Load Demo Data" to restore sample data.
Q: Timetable won't generate (button does nothing)
Verify Prerequisites:
- ✓ At least 1 teacher exists
- ✓ At least 1 class exists
- ✓ Days and periods configured (sidebar)
- ✓ Teachers can teach assigned subjects
Check Console: Press F12 → Console tab → Look for errors
Q: Energy maps not animating
Solutions:
- Toggle "Motion" switch ON in Energy Maps tab
- Use modern browser (Chrome 90+, Firefox 88+, Safari 14+)
- Disable browser extensions that block JavaScript
- Check browser console for errors
Q: PDF download shows blank pages
Solutions:
- Regenerate timetable first
- Try different PDF viewer (Adobe Reader, Chrome, Firefox)
- Check if timetable has data:
# In Class Timetables tab, verify table shows data - Update ReportLab:
pip install --upgrade reportlab
# Core Framework
streamlit>=1.28.0 # Web UI framework
ortools>=9.5.0 # Constraint programming solver
# Data Processing
pandas>=1.5.0 # DataFrames and tables
numpy>=1.23.0 # Numerical operations
# Visualization
plotly>=5.14.0 # Interactive charts (energy maps)
matplotlib>=3.7.0 # Static charts (heatmaps)
# PDF Generation
reportlab>=4.0.0 # Professional PDF documents
# Scientific Computing
scipy>=1.10.0 # Gaussian filters, image processing
# Utilities
python-dateutil>=2.8.2 # Date/time handlingInstallation:
pip install -r requirements.txt| Layer | Technology | Version | Purpose |
|---|---|---|---|
| Frontend | Streamlit | 1.28+ | Reactive web interface |
| Custom CSS | - | Dark theme, animations | |
| Solver | OR-Tools CP-SAT | 9.5+ | Constraint programming |
| Visualization | Plotly | 5.14+ | Interactive energy maps |
| Matplotlib | 3.7+ | Static heatmaps | |
| Data | Pandas | 1.5+ | DataFrames, tables |
| NumPy | 1.23+ | Array operations | |
| ReportLab | 4.0+ | Document generation | |
| Scientific | SciPy | 1.10+ | Filters, effects |
| Storage | JSON | stdlib | Lightweight persistence |
We welcome contributions! Here's how to get started:
# Fork and clone
git clone https://github.com/YOUR_USERNAME/smart-timetable-builder.git
cd smart-timetable-builder
# Create virtual environment
python -m venv venv
source venv/bin/activate # macOS/Linux
venv\Scripts\activate # Windows
# Install dependencies
pip install -r requirements.txt
# Run in development mode
streamlit run app.py|
Google OR-Tools Constraint programming solver |
Streamlit Web app framework |
Plotly Interactive visualizations |
ReportLab PDF generation |
Special Thanks:
- All contributors
- Educators who provided feedback
- Open source community
|
Found a bug? Let us know! |
Questions? Ideas? Let's talk! |
Direct contact for sensitive issues |
If this project helps your school, please consider:
Starring the repository on GitHub
Sharing on social media
Contributing improvements
Writing about your experience
© 2024 Smart Timetable Builder
Made using Python, Streamlit, and OR-Tools
