@dytsou/intern-corner-scheduler
v1.3.2
Published
Round-table Scheduler (CP-SAT) - Python CLI and web interface using OR-Tools CP-SAT to generate round-table seating across rounds with fixed hosts, balanced tables, and pair-wise constraints
Maintainers
Readme
Round-table Scheduler (CP-SAT)
Python CLI and web interface using OR-Tools CP-SAT to generate round-table seating across rounds with fixed hosts, balanced tables, and pair-wise constraints.
Input (stdin)
- Line 1:
a b c - Line 2:
d(number of same-once pairs) - Next
dlines:e_i f_i - Next line:
x(number of never-together pairs) - Next
xlines:y_i z_i
Interpretation:
a: participants 1..ab: tables 1..b; participants 1..b are hosts, fixed at their table number each roundc: number of rounds- Same-once pairs: each pair should be seated together in exactly one round if possible
- Never-together pairs: must never be seated together
Output (stdout)
JSON with fields:
participants,tables,roundstable_sizes: balanced per tableassignments: list per round, each a list per table of participant IDssatisfied_same_once_pairs,unsatisfied_same_once_pairsnever_together_violations(should be empty)objective_value,solver_status
Install
make installRun
Docker development stack (web UI + separate API)
make run # builds and starts the web UI and the separate API in Docker
# web UI: http://localhost:${WEB_PORT:-5173}
# API: http://localhost:${API_PORT:-8000} (not used by browser scheduling)
make run-down # stop the Docker containersCLI
Pipe input into the program:
# example
cat <<EOF | make run-cli
6 2 3
1
3 5
1
4 6
EOFOr directly:
cd python && python3 main.py < input.txtWeb Interface
The React + Vite frontend solves schedules in the user's browser with OR-Tools CP-SAT compiled to WebAssembly. Cloudflare Pages serves static files; it does not run the Python API or receive schedule inputs.
Run the Frontend Locally
pnpm install --frozen-lockfile
pnpm devTo build and preview the production files locally:
pnpm build
pnpm previewThe production output is written to docs/. The public/_headers file adds the COOP and COEP response headers needed for browser isolation.
Cloudflare Pages Settings
Connect the repository to Cloudflare Pages with these build settings:
| Setting | Value |
| --- | --- |
| Build command | pnpm run build:cloudflare |
| Build output directory | docs |
| NODE_VERSION | 22 |
| PNPM_VERSION | 10.20.0 |
| SKIP_DEPENDENCY_INSTALL | 1 |
The build command installs locked dependencies and generates docs/ in one step. SKIP_DEPENDENCY_INSTALL=1 prevents Pages from running a second dependency install. Keep the Pages project static: no Pages Functions or Worker API are needed for browser scheduling.
Python API and CLI
The Python CLI, FastAPI service, and Docker setup remain available as separate tools. Start the API locally with make serve-backend; its documentation is available at http://localhost:8000/docs. The browser frontend does not need a backend URL or API server.
API Documentation
The FastAPI backend provides a REST API for scheduling. When the server is running, interactive API documentation is available at:
- Swagger UI:
http://localhost:8000/docs - ReDoc:
http://localhost:8000/redoc
API Endpoint
POST /api/schedule
Generate a schedule based on constraints.
Request Body:
{
"participants": 6,
"tables": 2,
"rounds": 3,
"same_once_pairs": [
{"u": 3, "v": 5}
],
"never_together_pairs": [
{"u": 4, "v": 6}
],
"time_limit_seconds": 60
}Response:
{
"participants": 6,
"tables": 2,
"rounds": 3,
"table_sizes": [3, 3],
"table_sizes_per_round": [[3, 3], [3, 3], [3, 3]],
"assignments": [
[[1, 3, 5], [2, 4, 6]],
[[1, 4, 5], [2, 3, 6]],
[[1, 3, 6], [2, 4, 5]]
],
"satisfied_same_once_pairs": [[3, 5]],
"unsatisfied_same_once_pairs": [],
"never_together_violations": [],
"objective_value": 1005,
"solver_status": "OPTIMAL"
}Health Check
GET /health
Returns the health status of the API.
Response:
{
"status": "healthy"
}Modeling Notes
- Hosts (1..b) are fixed to their own table every round.
- Tables are balanced: first
a % btables have sizea//b + 1, othersa//b. - Non-hosts do not sit at the same table in consecutive rounds.
- Objective maximizes how many same-once pairs are met exactly once; never-together is enforced strictly.
License
This project is licensed under the MIT License - see the LICENSE file for details.
