Files
lnet_tutor/exam_system/README.md
2025-10-22 20:14:31 +08:00

204 lines
4.8 KiB
Markdown

# Exam System (Single Docker Environment)
## Overview
A minimal exam system using Django + Angular + Nginx in a unified Docker environment. Reads exam JSON files, renders online exams, autosaves progress, and outputs bundled results.
## Architecture
- **exam_server**: Django REST API (port 8000 internal)
- **exam_web**: Angular SPA (port 4200 internal)
- **nginx**: Reverse proxy (port 80 external)
- `/` → exam_web
- `/api/` → exam_server
## Folder Structure
```
exam_system/
├── exam_server/ # Django REST API
│ ├── Dockerfile
│ ├── requirements.txt
│ └── env.example
├── exam_web/ # Angular SPA
│ ├── Dockerfile
│ └── package.json
├── data/ # File-based storage
│ ├── input/ # Source exam JSON files
│ ├── attempts/ # In-progress attempts
│ ├── output/ # Final bundled results
│ ├── progress/ # User progress snapshots
│ └── manifest.json # Exam registry
├── nginx.conf # Nginx reverse proxy config
├── Dockerfile.nginx # Nginx container
├── docker-compose.yml # Orchestration
└── README.md
```
## Quick Start
### Prerequisites
- Docker 20.10+
- Docker Compose 2.0+
### 1. Build and Start
```bash
cd exam_system
docker-compose up --build
```
This starts all three services in one environment:
- Nginx listening on http://localhost
- Django backend (internal)
- Angular frontend (internal)
### 2. Access
- **Main app**: http://localhost (via Nginx)
- Access logs: `docker-compose logs -f`
### 3. Stop
```bash
docker-compose down
```
## Development
### Backend (exam_server)
```bash
# Shell access
docker-compose exec exam_server bash
# Run migrations (when Django app is initialized)
docker-compose exec exam_server python manage.py migrate
# Create superuser
docker-compose exec exam_server python manage.py createsuperuser
```
### Frontend (exam_web)
```bash
# Shell access
docker-compose exec exam_web sh
# Install new dependencies
docker-compose exec exam_web npm install <package>
```
### View Logs
```bash
# All services
docker-compose logs -f
# Specific service
docker-compose logs -f exam_server
docker-compose logs -f exam_web
docker-compose logs -f nginx
```
## Data Management
### Add an Exam
1. Place exam JSON file in `data/input/your-exam.json` (see `/docs/exam-format.md` for format)
2. Update `data/manifest.json`:
```json
{
"exams": [
{
"examId": "your-exam",
"path": "input/your-exam.json",
"published": true,
"version": "1.0.0"
}
],
"users": {}
}
```
### View Results
- Output bundles written to `data/output/{examId}_{attemptId}.json`
- Contains `{ exam, attempt }` with all answers
### Reset User Progress
- Remove user from `manifest.json` `users` object
- Delete corresponding files in `data/attempts/{userId}/` and `data/output/`
## Production
### Environment Variables
Copy `exam_server/env.example` to `exam_server/.env` and update:
- `DEBUG=False`
- `SECRET_KEY=<strong-random-key>`
- `ALLOWED_HOSTS=yourdomain.com`
- `CORS_ALLOWED_ORIGINS=https://yourdomain.com`
### Production Build
For production, modify `exam_web/Dockerfile` to use production build:
```dockerfile
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build --prod
FROM nginx:alpine
COPY --from=builder /app/dist/exam-web /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
```
### Backup
```bash
# Backup data folder
tar -czf backup-$(date +%Y%m%d).tar.gz data/
```
## Documentation
See `/docs` folder for detailed specifications:
- `exam-format.md` - Exam JSON format (5 question types)
- `stack-architecture.md` - System architecture overview
- `django-backend-spec.md` - Backend API endpoints
- `angular-frontend-spec.md` - Frontend routes and behavior
- `json-io-and-state.md` - State machine and file structure
- `deploy-minimal.md` - Deployment guide
## Workflow
1. Create exam JSON → place in `data/input/`
2. Publish exam → update `manifest.json`
3. User starts exam → creates attempt in `data/attempts/`
4. Autosave progress → updates attempt JSON
5. Submit exam → writes bundle to `data/output/`
## Troubleshooting
### Port 80 already in use
```bash
# Edit docker-compose.yml
# Change "80:80" to "8080:80" under nginx ports
# Then access via http://localhost:8080
```
### Permission errors
```bash
# Fix data folder permissions
chmod -R 755 data/
```
### Container won't start
```bash
# Check logs
docker-compose logs exam_server
# Rebuild from scratch
docker-compose down -v
docker-compose up --build
```
### Can't access from browser
```bash
# Verify all containers running
docker-compose ps
# Should show 3 services: exam_server, exam_web, nginx
```
## License
MIT