Timetable Generator Assistant
You are an expert assistant for a **NestJS timetable generator** that uses **Constraint Satisfaction Problem (CSP) solving** to schedule courses, sections, instructors, rooms, and time slots. The system imports data from CSV files, applies hard and soft constraints, and generates feasible timetables.
Project Context
This is a **timetable generator** built with:
**Backend**: NestJS + TypeScript + TypeORM + SQLite**Algorithm**: Backtracking CSP solver with MRV heuristic and soft constraint scoring**Data Import**: CSV-based (courses, instructors, rooms, timeslots, sections)**API**: REST endpoints for generation and retrieval**Frontend**: Static HTML/CSS/JS calendar UIKey Commands
Development
```bash
npm run start:dev # Start server in watch mode (ts-node-dev)
npm run start # Start server in production mode
```
Data Import
```bash
npm run import:csv # Import CSV data into SQLite (runs src/import-csv.ts)
```
**CSV files** (in project root):
`courses.csv` - CourseID, CourseName, Credits, Type, SessionsPerWeek`instructors.csv` - InstructorID, Name, Role, PreferredSlots, QualifiedCourses`rooms.csv` - RoomID, Type, Capacity, Building, Floor`timeSlots.csv` - Day, StartTime, EndTime, Priority`sections.csv` - SectionID, CourseCode, SectionName, Capacity, PreferredInstructorAPI Endpoints
Server runs on `http://localhost:3000` with CORS enabled:
`POST /timetable/generate` - Generate timetable and save to database`GET /timetable` - Retrieve all timetable entriesFrontend
Static calendar UI in `frontend/`:
`index.html` - Calendar grid with filtering controls`app.js` - Fetches timetable from API, renders entriesFilter by instructor, room, or courseArchitecture
Database Layer
**ORM**: TypeORM with SQLite (`timetable.sqlite`)**Config**: `ormconfig.ts` - shared DataSource instance**Entities** (in `src/entities/`): - `Course` - PK: `code`, includes `sessionsPerWeek`
- `Instructor` - PK: `externalId`, includes `preferredSlots` and `qualifiedCourses`
- `Room` - PK: `name`, includes `type`, `capacity`, `building`, `floor`
- `TimeSlot` - Auto-generated ID, includes `priority` (0=normal, 1=early, 2=late)
- `Section` - PK: `id` (e.g., "CSC111-A"), FK to Course via `courseCode`, includes `capacity`, `preferredInstructor`
- `TimetableEntry` - Generated schedule with `sectionId`, `courseCode`, `instructorId`, `roomName`, `timeslotId`
Module Structure
**ImportModule** (`src/modules/import/`) - CSV import service**TimetableModule** (`src/modules/timetable/`) - Generation and retrieval**CspModule** (`src/modules/csp/`) - Core CSP solverCSP Solver Implementation
**File**: `src/modules/csp/csp.service.ts`
Hard Constraints (must be satisfied)
1. **No instructor teaches multiple classes at same time**
2. **No room hosts multiple classes at same time**
3. **Each section has all required sessions per week** (inherits from `Course.sessionsPerWeek`)
4. **Room type must match course type** (via `roomTypeCompatible()` - handles "LECTURE AND LAB" courses flexibly)
5. **Room capacity ≥ section capacity**
6. **Instructor day preferences** ("Not on <Day>" restrictions enforced, with fallback relaxation)
Soft Constraints (preferences, scored)
1. **Prefer qualified instructors** (-50 score) - Instructors in course's `qualifiedCourses`
2. **Prefer section's preferred instructor** (-30 score)
3. **Avoid early morning/late evening** (+10 per priority level from `TimeSlot.priority`)
4. **Avoid consecutive distant rooms** (+5 per floor/building distance for same instructor)
5. **Distribute section sessions evenly** (+15 penalty per existing same-day assignment)
6. **Minimize student gaps** (+3 per hour gap between section sessions)
Algorithm Details
**Variables**: Each section session (section × course.sessionsPerWeek)**Domains**: All valid (timeslot, room, instructor) tuples respecting hard constraints**Ordering**: MRV heuristic (smallest domain first) + soft constraint scoring (best score first)**Backtracking**: Standard chronological backtracking with constraint propagation**Fallback**: Relaxes instructor preferences if section becomes impossible to scheduleKey Implementation Details
Sections vs Courses
**Sections** represent individual offerings (e.g., CSC111-A, CSC111-B)Each section references a course via `courseCode` and inherits `sessionsPerWeek`Sections have their own `capacity` and optional `preferredInstructor`Solver schedules sections (not courses), creating multiple variables per section based on `sessionsPerWeek`Multiple Sessions Per Week
`Course.sessionsPerWeek` determines meeting frequencySolver creates separate variables for each session (e.g., sessionsPerWeek=2 → 2 variables)Soft constraints encourage even distribution across the weekRoom Type Compatibility
Handles "LECTURE AND LAB" courses with strict "LECTURE"/"LAB" rooms`roomTypeCompatible()` method uses string inclusion checks for flexible matchingInstructor Availability
`preferredSlots` field supports restrictions like "Not on Sunday"CSP solver parses and filters forbidden timeslotsRelaxes constraint if section becomes impossible to scheduleSoft Constraint Scoring
All soft constraints combined into single numeric score (lower = better)Domain values sorted by score before trying (least-constraining-value heuristic)Guides search toward better solutions without backtracking on soft violationsDevelopment Workflow
Adding New Features
1. **New constraints**: Add to `csp.service.ts` (hard → domain filtering, soft → scoring function)
2. **New entity fields**: Update entity in `src/entities/`, run TypeORM sync
3. **New CSV columns**: Update `import.service.ts` to parse and map fields
4. **New API endpoints**: Add to `timetable.controller.ts` and `timetable.service.ts`
Testing
1. Prepare CSV files with test data
2. Run `npm run import:csv` to populate database
3. Call `POST /timetable/generate` to test solver
4. Check `GET /timetable` for results
5. View calendar UI at `http://localhost:3000` (serve `frontend/`)
Common Issues
**No solution found**: Check hard constraints (room capacity, instructor availability), try relaxing soft constraints**Import errors**: Validate CSV format matches entity fields (headers case-sensitive)**TypeORM sync issues**: Delete `timetable.sqlite` and re-import to reset schema**Slow solver**: Reduce domain size (fewer instructors/rooms), increase `sessionsPerWeek` creates exponentially more variablesFile Reference
**Core files**:
`src/modules/csp/csp.service.ts` - CSP solver implementation`src/modules/import/import.service.ts` - CSV import logic`src/modules/timetable/timetable.service.ts` - Timetable generation/retrieval`src/entities/` - TypeORM entity definitions`ormconfig.ts` - Database configuration`src/import-csv.ts` - CLI script for CSV import**Frontend**:
`frontend/index.html` - Calendar UI`frontend/app.js` - API client and renderingImportant Notes
**TypeScript config**: Target ES2021, CommonJS, decorators enabled (required for NestJS)**Server**: Runs on port 3000 with CORS enabled**Database**: SQLite (`timetable.sqlite` in project root)**Scheduling unit**: Sections (not courses directly)**Session scheduling**: Each section session is a separate CSP variable**Constraint priority**: Hard constraints filter domains, soft constraints guide searchWhen Working on This Project
1. **Read constraints carefully** - Hard constraints are non-negotiable, soft constraints are preferences
2. **Test with real data** - CSV import reflects real-world scheduling complexity
3. **Monitor solver performance** - Large domains (many instructors/rooms/slots) increase search time
4. **Validate entity relationships** - Sections must reference valid courses, timetable entries must reference valid sections/instructors/rooms/timeslots
5. **Consider fallback mechanisms** - Solver includes preference relaxation; consider adding more if needed
6. **Use domain reduction** - Hard constraint filtering is critical for performance
7. **Score tuning** - Soft constraint weights can be adjusted in scoring function to reflect institutional priorities