first working version
This commit is contained in:
290
exam_system/HOW_TO_ADD_EXAMS.md
Normal file
290
exam_system/HOW_TO_ADD_EXAMS.md
Normal file
@@ -0,0 +1,290 @@
|
||||
# How to Add Exams
|
||||
|
||||
## ✅ All Previous Exams Removed
|
||||
|
||||
The system has been reset:
|
||||
- ✓ Input folder cleaned
|
||||
- ✓ Output folder cleaned
|
||||
- ✓ Attempts cleaned
|
||||
- ✓ Manifest reset
|
||||
|
||||
## Adding a New Exam
|
||||
|
||||
### Step 1: Create Exam JSON
|
||||
|
||||
Create a file in `data/input/` following this format:
|
||||
|
||||
**Example: `data/input/my-first-exam.json`**
|
||||
|
||||
```json
|
||||
{
|
||||
"examId": "my-first-exam",
|
||||
"subject": "python",
|
||||
"title": "My First Exam",
|
||||
"difficulty": "beginner",
|
||||
"durationMinutes": 30,
|
||||
"sections": [
|
||||
{
|
||||
"id": "sec-1",
|
||||
"title": "Multiple Choice",
|
||||
"questions": [
|
||||
{
|
||||
"id": "q1",
|
||||
"type": "single_choice",
|
||||
"prompt": "What is 2 + 2?",
|
||||
"choices": [
|
||||
{ "key": "A", "text": "3" },
|
||||
{ "key": "B", "text": "4" },
|
||||
{ "key": "C", "text": "5" }
|
||||
],
|
||||
"answer": "B",
|
||||
"points": 10
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "sec-2",
|
||||
"title": "True/False",
|
||||
"questions": [
|
||||
{
|
||||
"id": "q2",
|
||||
"type": "true_false",
|
||||
"prompt": "Python is a programming language.",
|
||||
"answer": true,
|
||||
"points": 5
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "sec-3",
|
||||
"title": "Essay",
|
||||
"questions": [
|
||||
{
|
||||
"id": "q3",
|
||||
"type": "essay",
|
||||
"prompt": "Explain what you learned today.",
|
||||
"rubric": {
|
||||
"criteria": [
|
||||
{ "name": "Clarity", "weight": 0.5 },
|
||||
{ "name": "Completeness", "weight": 0.5 }
|
||||
],
|
||||
"maxPoints": 10
|
||||
},
|
||||
"points": 10
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"createdAt": "2025-10-20T00:00:00Z",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: Update Manifest
|
||||
|
||||
Edit `data/manifest.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"exams": [
|
||||
{
|
||||
"examId": "my-first-exam",
|
||||
"path": "input/my-first-exam.json",
|
||||
"published": true,
|
||||
"version": "1.0.0"
|
||||
}
|
||||
],
|
||||
"users": {}
|
||||
}
|
||||
```
|
||||
|
||||
**Important:**
|
||||
- `examId` must match the filename (without .json)
|
||||
- `published: true` makes it visible
|
||||
- `published: false` hides it (draft mode)
|
||||
|
||||
### Step 3: Refresh Browser
|
||||
|
||||
Go to http://localhost - your exam will appear!
|
||||
|
||||
## Question Type Reference
|
||||
|
||||
### 1. Single Choice (MCQ)
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "q1",
|
||||
"type": "single_choice",
|
||||
"prompt": "Your question here?",
|
||||
"choices": [
|
||||
{ "key": "A", "text": "Option A" },
|
||||
{ "key": "B", "text": "Option B" },
|
||||
{ "key": "C", "text": "Option C" }
|
||||
],
|
||||
"answer": "B",
|
||||
"points": 10
|
||||
}
|
||||
```
|
||||
|
||||
### 2. True/False
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "q2",
|
||||
"type": "true_false",
|
||||
"prompt": "Statement to evaluate.",
|
||||
"answer": true,
|
||||
"points": 5
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Essay
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "q3",
|
||||
"type": "essay",
|
||||
"prompt": "Write about...",
|
||||
"rubric": {
|
||||
"criteria": [
|
||||
{ "name": "Correctness", "weight": 0.6 },
|
||||
{ "name": "Clarity", "weight": 0.4 }
|
||||
],
|
||||
"maxPoints": 20
|
||||
},
|
||||
"points": 20
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Simple Coding
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "q4",
|
||||
"type": "code_simple",
|
||||
"language": "python",
|
||||
"prompt": "Write a function that...",
|
||||
"tests": [
|
||||
{ "input": "function(5)", "expected": "10", "visibility": "hidden" }
|
||||
],
|
||||
"points": 15
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Coding Exercise
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "q5",
|
||||
"type": "code_exercise",
|
||||
"language": "python",
|
||||
"prompt": "Implement a complex function...",
|
||||
"constraints": "Must be O(n) time complexity",
|
||||
"tests": [
|
||||
{ "input": "func([1,2,3])", "expected": "[1,4,9]", "visibility": "hidden", "weight": 1 }
|
||||
],
|
||||
"rubric": {
|
||||
"criteria": [
|
||||
{ "name": "Correctness", "weight": 0.6 },
|
||||
{ "name": "Efficiency", "weight": 0.4 }
|
||||
],
|
||||
"maxPoints": 25
|
||||
},
|
||||
"points": 25
|
||||
}
|
||||
```
|
||||
|
||||
## Multiple Exams
|
||||
|
||||
To add multiple exams, create multiple JSON files and add all to manifest:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"exams": [
|
||||
{
|
||||
"examId": "python-basics",
|
||||
"path": "input/python-basics.json",
|
||||
"published": true,
|
||||
"version": "1.0.0"
|
||||
},
|
||||
{
|
||||
"examId": "django-fundamentals",
|
||||
"path": "input/django-fundamentals.json",
|
||||
"published": true,
|
||||
"version": "1.0.0"
|
||||
},
|
||||
{
|
||||
"examId": "angular-intro",
|
||||
"path": "input/angular-intro.json",
|
||||
"published": false,
|
||||
"version": "1.0.0"
|
||||
}
|
||||
],
|
||||
"users": {}
|
||||
}
|
||||
```
|
||||
|
||||
## Publishing/Unpublishing
|
||||
|
||||
**Publish an exam:**
|
||||
- Set `"published": true` in manifest
|
||||
|
||||
**Hide an exam (draft):**
|
||||
- Set `"published": false` in manifest
|
||||
|
||||
Changes take effect immediately (refresh browser).
|
||||
|
||||
## Tips
|
||||
|
||||
1. **Use a template:** Copy an existing exam JSON and modify it
|
||||
2. **Validate JSON:** Use a JSON validator or `python -m json.tool < your-exam.json`
|
||||
3. **Test incrementally:** Add one question at a time
|
||||
4. **Check format:** See `/docs/exam-format.md` for complete spec
|
||||
5. **Unique IDs:** Make sure all question IDs are unique within an exam
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
Before adding an exam, verify:
|
||||
- [ ] Valid JSON format
|
||||
- [ ] All required fields present (`examId`, `title`, `durationMinutes`, `sections`)
|
||||
- [ ] Each section has `id`, `title`, `questions`
|
||||
- [ ] Each question has `id`, `type`, `prompt`, `points`
|
||||
- [ ] Type-specific fields included (choices, answer, rubric, tests, etc.)
|
||||
- [ ] All IDs are unique
|
||||
- [ ] Points are positive integers
|
||||
- [ ] File saved in `data/input/` with `.json` extension
|
||||
- [ ] Manifest updated with exam entry
|
||||
|
||||
## Quick Test
|
||||
|
||||
After adding an exam:
|
||||
|
||||
```bash
|
||||
# Validate JSON
|
||||
python3 -m json.tool < data/input/your-exam.json
|
||||
|
||||
# Check manifest
|
||||
cat data/manifest.json
|
||||
|
||||
# Restart if needed (usually not required)
|
||||
docker-compose restart exam_server
|
||||
|
||||
# Open browser
|
||||
open http://localhost
|
||||
```
|
||||
|
||||
Your exam should appear in the list!
|
||||
|
||||
## Example: Complete Exam Template
|
||||
|
||||
See `/docs/exam-format.md` for a complete example with all 5 question types.
|
||||
|
||||
---
|
||||
|
||||
**Current Status:** System is clean and ready for your exams!
|
||||
**Next Step:** Create your first exam JSON in `data/input/`
|
||||
|
||||
Reference in New Issue
Block a user