File size: 6,317 Bytes
4b94493
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
---
title: SolverForge Lessons
emoji: 📚
colorFrom: blue
colorTo: green
sdk: docker
app_port: 7860
pinned: false
license: apache-2.0
short_description: SolverForge lesson scheduling example
---

# SolverForge Lessons

![SolverForge Lessons screenshot](docs/screenshot.png)

`solverforge-lessons` is a SolverForge lesson-timetabling app with retained
jobs, cohort timetable views, and a browser schedule workspace.

It answers one concrete question:

"Given lessons, teachers, student groups, rooms, and weekly timeslots, which
timeslot and room should each lesson receive?"

## Acknowledgement

Thanks to `@benabel` (Prof. Benjamin Abel), whose referral is also credited in
the core SolverForge README.

## Quick Start

```sh
make run-release
```

Then open `http://localhost:7860`.

To inspect the supported command surface:

```sh
make help
```

## Documentation Map

- `README.md`
  Quick start, model concepts, validation, REST API, and solver policy.
- `WIREFRAME.md`
  As-built architecture and runtime/data flow across backend, runtime, and UI.
- `AGENTS.md`
  Codex-facing maintenance, validation, and documentation rules.
- `Makefile`
  Supported local commands for development, validation, Docker, and Space work.
- `Dockerfile`
  Docker Space image build using Rust 1.95 and the declared crates.io line.

## Current Dependency Shape

- Package: `solverforge-lessons`; version is declared in `Cargo.toml`
- Release binary: `solverforge-lessons`
- Rust: `1.95`
- SolverForge runtime: `solverforge` `0.13.1`
- Browser UI assets: `solverforge-ui` `0.6.5`
- Scaffold metadata: `solverforge-cli` `2.0.4` in `solverforge.app.toml`

The app serves registry-backed Rust dependencies, local static browser modules,
and Axum API routes from one process.

## Model Concepts

- `Timeslot`, `Teacher`, `Group`, and `Room` are problem facts: input data the
  solver reads but does not move.
- `Lesson` is the planning entity: each subject meeting needs a timeslot and a
  room.
- `Lesson.timeslot_idx` is a scalar planning variable: the timeslot index
  SolverForge changes.
- `Lesson.room_idx` is a scalar planning variable: the room index SolverForge
  changes.
- `Plan` is the planning solution with the current `HardMediumSoftScore`.

The app ships one deterministic `LARGE` dataset with 300 lessons, 12 student
groups, 40 weekly timeslots, and 10 typed rooms. It starts with every lesson
unassigned, so the initial score is `0hard/-600medium/0soft`.

## Constraints

Hard constraints:

- Teachers can teach only in available timeslots.
- Student groups can attend only in available timeslots.
- A room must be large enough for the assigned group.
- A teacher cannot teach overlapping lessons.
- A group cannot attend overlapping lessons.
- A room cannot host overlapping lessons.

Medium constraints:

- Every lesson should receive a timeslot.
- Every lesson should receive a room.

Soft constraints:

- Room kind should match the subject.
- Lessons should avoid late-day slots when possible.
- The same subject should not repeat twice in one day for a cohort.

## REST API

- `GET /health`
- `GET /info`
- `GET /demo-data`
- `GET /demo-data/{id}`
- `POST /jobs`
- `GET /jobs/{id}`
- `DELETE /jobs/{id}`
- `GET /jobs/{id}/status`
- `GET /jobs/{id}/snapshot`
- `GET /jobs/{id}/analysis`
- `POST /jobs/{id}/pause`
- `POST /jobs/{id}/resume`
- `POST /jobs/{id}/cancel`
- `GET /jobs/{id}/events`

`snapshot_revision={n}` is optional for snapshots and analysis. SSE clients
receive a bootstrap event and then live retained-job events.

## Solver Policy

`solver.toml` is embedded by `Plan` and is the runtime source of truth.

- `cheapest_insertion` assigns timeslots and rooms during construction.
- `construction_obligation = "assign_when_candidate_exists"` makes
  construction fill variables when a legal candidate exists.
- `value_candidate_limit = 40` bounds construction candidate scanning.
- Local search uses `late_acceptance` with an accepted-count forager.
- Solving stops after 30 seconds.

The slow acceptance test expects solving to reach hard and medium feasibility
from the fully unassigned public instance while soft penalties continue to
represent timetable quality.

## Validation

Standard validation:

```sh
make test
```

Full local validation:

```sh
make ci-local
```

Slow acceptance solve:

```sh
make test-slow
```

`make test` runs Rust tests, frontend syntax checks, and a Playwright browser
smoke. `make ci-local` adds formatting, clippy, release build, and Docker image
build. `make pre-release` runs `ci-local` plus the slow acceptance solve.

## Hugging Face Space Deployment

This repo is Docker-Space ready. The Space reads the README front matter,
builds `Dockerfile`, and expects the app to bind `PORT=7860`.

Local Space-equivalent commands:

```sh
make space-build
make space-run
```

## Read The Code In This Order

1. `src/domain/mod.rs`
   The `planning_model!` manifest and public domain exports.
2. `src/domain/plan.rs`
   The `Plan` solution, fact collections, lesson entities, and normalized
   index fields.
3. `src/domain/lesson.rs`
   The planning entity and the two scalar planning variables.
4. `src/domain/{timeslot,teacher,group,room}.rs`
   The problem facts the constraints join against.
5. `src/constraints/mod.rs` and `src/constraints/*.rs`
   The score model, one timetable rule per file.
6. `src/data/data_seed/entrypoints.rs`
   Public demo-data IDs and generator dispatch.
7. `src/data/data_seed/large.rs`
   The published instance builder.
8. `src/solver/service.rs`
   Retained-job orchestration over `SolverManager<Plan>`.
9. `src/api/routes.rs`, `src/api/dto.rs`, and `src/api/sse.rs`
   HTTP routes, transport DTOs, and live-event streaming.
10. `static/app.js` and `static/views.js`
    Browser boot sequence, solver controls, and timetable rendering.

## Project Shape

- `src/domain/`
  Planning model, domain types, planning variables, and derived indexes.
- `src/constraints/`
  Incremental SolverForge scoring rules.
- `src/data/`
  Deterministic lesson timetable demo-data generator.
- `src/solver/`
  Retained-job facade and runtime event payload formatting.
- `src/api/`
  Axum routes, DTOs, and SSE endpoint.
- `static/`
  Browser workspace built on stock `solverforge-ui` assets.
- `tests/e2e/`
  Playwright browser smoke for the served app.