# 03. KỸ THUẬT BÓC TÁCH JSON & SKILLS ENGINE

Tài liệu này giải thích chi tiết cấu trúc dữ liệu JSON bài thi, mã nhận diện kỹ năng (Skill IDs), phân loại câu hỏi (`quiz_type`) và cơ chế bóc tách bài làm của học sinh trong file [`exam-detail-modal-v3.js`](file:///var/www/html/hocmai_testsite/public/js/exam-history/exam-detail-modal-v3.js).

---

## 1. Bảng Mã Kỹ Năng Hệ Thống (Skill Configuration)

| Skill ID | Tên Kỹ năng | Màu sắc UI | Kiểu Chấm | Hàm Render tương ứng |
|:---:|---|---|---|---|
| **13** | **Listening** (Nghe) | `sky` (Xanh da trời) | Tự động qua JSON | `displayListeningDetails(history, skillColor)` |
| **14** | **Reading** (Đọc) | `emerald` (Xanh lá) | Tự động qua JSON | `displayReadingDetails(history, skillColor)` |
| **15** | **Writing** (Viết) | `indigo` (Xanh tím) | Giáo viên / Tester chấm | `displayWritingDetails(history, skillColor)` |
| **16** | **Speaking** (Nói) | `orange` (Cam) | Giáo viên chấm 1-1 | `displaySpeakingDetails(history, skillColor)` |
| **17** | **Vocabulary** (Từ vựng) | `teal` (Xanh mòng két) | Tự động qua JSON | `displayVocabularyDetails(history, skillColor)` |

---

## 2. Cấu Trúc Payload JSON Của Bài Kiểm Tra

Mỗi bản ghi bài làm của học sinh chứa 2 mảng chính:
1. `listQuestion`: Chứa danh sách đề bài, đoạn văn (passage), câu hỏi và các lựa chọn đáp án.
2. `listQuestionGraded`: Chứa thông tin bài làm thực tế của học sinh (`userAnswer`), đáp án đúng/sai (`isTrue`).

### 🌲 Mô Hình Cây Câu Hỏi (Question Hierarchy)

```
listQuestion (Passage / Phần lớn)
  └── listQuestionChildren (Cụm câu hỏi hoặc Câu hỏi độc lập)
        └── listQuestionChildren (Câu hỏi con lồng bên trong - nếu có)
              ├── listSelectOptions (Các phương án trắc nghiệm)
              └── listShortAnswer (Từ khóa đáp án điền từ)
```

---

## 3. Phân Loại `quiz_type` và Hàm Render Tương Ứng

### 📌 1. Câu hỏi Trắc nghiệm (`quiz_type: 1` hoặc `2`)
- **Đặc điểm**: Có mảng `listSelectOptions`.
  - `quiz_type: 1`: Chọn 1 đáp án (Single Choice, True/False/Not Given).
  - `quiz_type: 2`: Chọn nhiều đáp án (Multiple Choice).
- **Hàm render**: `renderReadingMCQ(child, uAns, label)`
- **Logic kiểm tra lựa chọn**:
  - `isSelected = Array.isArray(uAns.answer) ? uAns.answer.includes(opt.answer_id) : uAns.answer == opt.answer_id`
  - `isTrue = opt.is_true`

### 📌 2. Câu hỏi Điền từ vào chỗ trống (`quiz_type: 4`)
- **Đặc điểm**: Có object `listShortAnswer` chứa mảng từ khóa đúng `listKeyword`.
- **Hàm render**: `renderReadingShortAnswer(child, uAns, label)`
- **Hiển thị**:
  - So sánh chuỗi học sinh điền (`uAns.answer`) với danh sách đáp án hợp lệ (`listKeyword.join(' / ')`).

### 📌 3. Nhóm câu hỏi Container (`quiz_type: 7` hoặc `14`)
- **Đặc điểm**: Chứa tiêu đề nhóm câu hỏi (`child.text`) và mảng các câu hỏi con `child.listQuestionChildren`.
- **Hàm điều phối**: `renderReadingQuestionByQuizType(sub, uAns, label)`

---

## 4. Thuật Toán Bóc Tách Bài Làm (`getReadingUserAnswer`)

Hệ thống hỗ trợ tự động nhận diện cả **Cấu trúc phẳng (1 cấp)** lẫn **Cấu trúc nhóm lồng (2 cấp)**:

```javascript
function getReadingUserAnswer(history, qId, targetId) {
    if (!history || !targetId) return null;
    const graded = (history.listQuestionGraded || []).find(g => g.idQuestion == qId);
    if (!graded || !graded.userAnswer) return null;

    for (const group of graded.userAnswer) {
        // 1. Khớp trực tiếp cấp 1 (Passage 1, các câu hỏi đơn)
        if (group.idChildQuestion == targetId) {
            return group;
        }
        // 2. Khớp trong nhóm lồng nhau cấp 2 (Passage 3 cụm nhóm)
        if (Array.isArray(group.answer)) {
            const match = group.answer.find(a => typeof a === 'object' && a !== null && a.idChildQuestion == targetId);
            if (match) return match;
        }
    }
    return null; // Bỏ qua / Chưa làm
}
```

---

## 5. Công Cụ Kiểm Thử Trực Quan (JSON Sandbox Tester)

Hệ thống đã tích hợp sẵn trang công cụ kiểm thử độc lập tại:
- **Đường dẫn**: [`public/exam-json-tester.html`](file:///var/www/html/hocmai_testsite/public/exam-json-tester.html)
- **URL truy cập**: `http://<domain>/exam-json-tester.html`
- **Tính năng**:
  - Giao diện 2 cột: Cột trái nhập/format JSON và chọn kỹ năng $\leftrightarrow$ Cột phải render thời gian thực.
  - Tích hợp sẵn Preset mẫu Reading (20 câu IELTS), Listening và Vocabulary để test nhanh với 1-click.
