Skip to content
Arrit Gashi
← All work
Prototype2026Web app

Orari Shkollor

Generates a school's entire weekly timetable with no student gaps and no double-bookings, in seconds.

to optimal at 40 classes, 1,280 lesson-hours
17s
to optimal for a 12-class school
0.89s
student gaps, as a hard constraint
0

The problem

School timetabling is NP-hard, and an Albanian vocational school's version has no soft edges: students may have no free periods between lessons, every class starts at 08:00, teacher availability is absolute, and specialist labs cannot double-book. The project was built against a written 14-section Albanian requirements specification that explicitly demanded a real constraint-programming algorithm rather than a heuristic. The tools that exist either produce merely-feasible timetables or do not speak Albanian.

What I built

One runtime, no build step. A FastAPI backend serves a Vue 3 frontend with Vue and the icon set vendored locally, so the whole thing runs offline with no Node.js anywhere in the stack. Persistence is JSON files. A Windows batch file starts it.

The solver is a Google OR-Tools CP-SAT model. Before it runs, a pre-flight validator catches structural impossibility and says what is wrong in plain language — curriculum hours that do not match the weekly total, teacher demand exceeding availability, or a lab shortfall reported as "add N more rooms". Failing early with a reason beats a solver that returns INFEASIBLE twenty seconds later.

The interface is nine tabbed sections in Albanian, ending in a master grid: every teacher as a row, every day and period as a column. Clicking any cell opens an editor to reassign the subject, class or room. The change is persisted, stats are recomputed server-side, and the class view, teacher view and reports all update immediately with conflicts highlighted — because a timetable that cannot be hand-corrected at 7am is not a timetable an administrator will use.

The hard part

One inequality removes every student gap

The model uses a boolean per lesson-hour per slot, plus a second family for room selection. Teacher availability costs nothing to enforce, because a blocked slot simply never gets a variable created — the constraint is structural rather than penalised, which makes it absolutely hard by construction.

The gap rule is the elegant part. Instead of modelling gaps directly, the solver introduces an occupancy boolean per class per slot and imposes monotonicity across the day: a period may only be occupied if the next one is too. That forces each class's day into a contiguous block starting at the first period. One inequality delivers two separate requirements at once — zero student gaps, and every class starting simultaneously at 08:00 — with no additional constraint needed for the second. Everything softer lives in a weighted objective: teacher gaps reified through a linearised three-way AND, day preferences, room changes and load balance, with the weights exposed to the administrator rather than hard-coded.

Outcome

  • Optimal solutions at 8, 18, 25 and 40 classes in roughly 0.4s, 1.6s, 3s and 17s — with zero teacher gaps at every size.
  • Tested to 40 classes and over 1,280 lesson-hours per week.
  • A stored 12-class school of 28 teachers and 144 curriculum hours solves OPTIMAL in 0.89 seconds, placing 384 lesson-hours with no gaps and no conflicts.
  • 10 of the specification's 13 tracked requirements complete, 2 of those partially, 3 deliberately deferred to a second phase.

Want something like this built? I take on a small number of projects at a time.