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

5.7 KiB

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

{
  "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:

{
  "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)

{
  "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

{
  "id": "q2",
  "type": "true_false",
  "prompt": "Statement to evaluate.",
  "answer": true,
  "points": 5
}

3. Essay

{
  "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

{
  "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

{
  "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:

{
  "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:

# 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/