# Phân Hệ Quản Lý Bài Làm Của Học Viên & Chấm Bài Thi
## 02. Quy Tắc Nghiệp Vụ & Logic Tính Điểm (Business Logic & Scoring Rules)

---

### 1. Vòng Đời Trạng Thái Bài Thi & Xử Lý Điểm (Exam Lifecycle)

Mỗi bài thi của học viên trong bảng `student_score` trải qua các trạng thái phối hợp chặt chẽ giữa 3 trường thông tin:

```mermaid
stateDiagram-v2
    [*] --> ChoNop: Học viên bắt đầu làm bài (exam_status = 0)
    ChoNop --> KhongNop: Quá hạn không nộp (exam_status = 2)
    ChoNop --> DaNop: Học viên nộp bài (exam_status = 1)

    DaNop --> DangXuLy: Chờ chấm / Đang chấm (score_processing_status = 0)
    DangXuLy --> HoanTat: GV hoàn tất chấm (score_processing_status = 1)
    
    HoanTat --> GiaoChamLai: Yêu cầu phúc khảo / QA rà soát (score_processing_status = 2)
    GiaoChamLai --> HoanTat: QA duyệt điểm chính thức (score_processing_status = 1)
    
    DangXuLy --> DaHuy: Vi phạm quy chế / Gian lận (score_processing_status = 3)
    GiaoChamLai --> DaHuy: Hủy kết quả bài thi (score_processing_status = 3)
```

| Cột Trạng Thái | Giá Trị | Ý Nghĩa Nghiệp Vụ |
| :--- | :---: | :--- |
| **`exam_status`** | **0** | **Chờ nộp**: Học viên chưa nộp bài hoặc đang trong thời gian làm bài. |
| | **1** | **Đã nộp**: Học viên đã gửi bài thi lên hệ thống thành công. |
| | **2** | **Không nộp**: Học viên không hoàn thành bài thi trước hạn chót. |
| **`submission_status`** | **0** | **Đúng hạn**: Nộp bài trong khung thời gian hợp lệ (`start_date` ➔ `deadline`). |
| | **1** | **Trễ hạn**: Nộp bài sau thời gian deadline quy định. |
| **`score_processing_status`** | **0** | **Đang xử lý**: Bài thi đang chờ gán giáo viên hoặc đang trong quá trình chấm điểm. |
| | **1** | **Hoàn tất**: Tất cả các kỹ năng tự luận đã được chấm xong; điểm Overall đã được chốt. |
| | **2** | **Giao chấm lại**: Bài thi được đưa vào quy trình phúc khảo / QA review. |
| | **3** | **Đã hủy**: Bài thi bị hủy kết quả do gian lận hoặc sự cố kỹ thuật. |

---

### 2. Phân Loại Contest Type & Thang Điểm (Scoring Scale & Contest Types)

Hệ thống hỗ trợ nhiều loại kỳ thi (Contest Type) thông qua các Contest Services chuyên biệt:

| Contest Type ID | Loại Kỳ Thi | Mô Tả & Đặc Thù Chấm Điểm | Service Xử Lý |
| :---: | :--- | :--- | :--- |
| **19** | IELTS Mocktest Standard | Bài thi chuẩn 4 kỹ năng (L, R, W, S) theo format quốc tế. | `ContestType19` |
| **21** | IELTS Listening / Reading Skill | Bài thi chuyên biệt kỹ năng Nghe / Đọc chấm tự động 100%. | `ContestType21` |
| **23** | IELTS Writing Full Test | Bài thi Viết gồm Task 1 và Task 2 chấm theo Rubric 4 tiêu chí. | `ContestType23` |
| **25** | IELTS Speaking Full Test | Bài thi Nói gồm Part 1, 2, 3 chấm qua ghi âm theo 4 tiêu chí. | `ContestType25` |
| **27, 29** | Round Mix Overall Service | Bài thi tổng hợp nhiều vòng (Easy IELTS, Round Mix) với công thức quy đổi điểm riêng biệt. | `ContestType27`, `ContestType29` |
| **35, 36** | Advanced Custom Assessment | Đề thi nâng cao tùy biến thang điểm theo khung chuẩn nội bộ. | `ContestType35`, `ContestType36` |

---

### 3. Logic Tính Điểm IELTS Overall & Quy Tắc Làm Tròn Chuẩn Quốc Tế

#### 3.1. Công thức tính điểm trung bình cộng 4 kỹ năng:
$$\text{Raw Overall} = \frac{\text{Listening} + \text{Reading} + \text{Writing} + \text{Speaking}}{4}$$

#### 3.2. Quy tắc làm tròn IELTS Band Score (IELTS Rounding Rule):
Điểm tổng (Overall Band Score) được làm tròn về mốc `.0` hoặc `.5` gần nhất theo thuật toán chính thức của IELTS:

| Phần thập phân của Raw Overall | Quy tắc làm tròn | Ví dụ minh họa |
| :---: | :---: | :--- |
| **$[.000, .125)$** | Làm tròn xuống `.0` | $6.10 \rightarrow \mathbf{6.0}$ |
| **$[.125, .250)$** | Làm tròn lên `.5` | $6.125 \rightarrow \mathbf{6.5}$ |
| **$[.250, .625)$** | Làm tròn về `.5` | $6.25 \rightarrow \mathbf{6.5}$ <br> $6.375 \rightarrow \mathbf{6.5}$ |
| **$[.625, .750)$** | Làm tròn lên `.0` tiếp theo | $6.625 \rightarrow \mathbf{7.0}$ <br> $6.75 \rightarrow \mathbf{7.0}$ |
| **$[.750, .999]$** | Làm tròn lên `.0` tiếp theo | $6.875 \rightarrow \mathbf{7.0}$ |

*Đoạn mã xử lý quy chuẩn trong PHP (`RoundMixOverallService` / `ScoringScaleFactory`):*
```php
public static function roundIeltsScore(float $score): float
{
    $integerPart = floor($score);
    $decimalPart = $score - $integerPart;

    if ($decimalPart < 0.125) {
        return (float) $integerPart;
    } elseif ($decimalPart < 0.625) {
        return (float) ($integerPart + 0.5);
    } else {
        return (float) ($integerPart + 1.0);
    }
}
```

---

### 4. Quy Tắc Chấm & Tính Điểm Chi Tiết Cho Từng Kỹ Năng

#### 4.1. Kỹ Năng Writing (Skill 15)
Điểm của từng Task trong bài thi Writing được tính dựa trên **4 tiêu chí Rubric chuẩn quốc tế**:
1. **TR / TA (Task Response / Task Achievement)**: Mức độ đáp ứng yêu cầu đề bài.
2. **CC (Coherence & Cohesion)**: Tính mạch lạc và liên kết câu/đoạn.
3. **LR (Lexical Resource)**: Vốn từ vựng và độ chính xác ngữ cảnh.
4. **GRA (Grammatical Range & Accuracy)**: Độ đa dạng và chính xác của cấu trúc ngữ pháp.

$$\text{Task Score} = \frac{\text{TR} + \text{CC} + \text{LR} + \text{GRA}}{4}$$

Điểm tổng kết kỹ năng Writing (Writing Overall Score) có trọng số:
$$\text{Final Writing Score} = \frac{\text{Task 1 Score} \times 1 + \text{Task 2 Score} \times 2}{3}$$
*(Kết quả sau đó được làm tròn theo quy tắc Band Score)*.

---

#### 4.2. Kỹ Năng Speaking (Skill 16)
Điểm của bài thi Speaking (gồm các Part 1, 2, 3) được chấm theo **4 tiêu chí Rubric**:
1. **FC (Fluency & Coherence)**: Độ lưu loát và mạch lạc khi nói.
2. **LR (Lexical Resource)**: Khả năng sử dụng từ vựng linh hoạt.
3. **GRA (Grammatical Range & Accuracy)**: Ngữ pháp trong văn nói.
4. **PR (Pronunciation)**: Phát âm, ngữ điệu, trọng âm từ và câu.

$$\text{Speaking Final Score} = \frac{\text{FC} + \text{LR} + \text{GRA} + \text{PR}}{4}$$

---

### 5. Phân Quyền Chấm Bài Của Giáo Viên (Teacher Grading Permissions)

Để đảm bảo tính bảo mật và tính chuyên môn hóa:
1. **Phân quyền theo Part / Kỹ năng**: Giáo viên chỉ được cấp quyền chấm đúng Part (Writing Task 1, Task 2 hoặc Speaking) mà cán bộ vận hành đã phân công trong bảng `teacher_assigned_histories` và `student_exam_history_teachers`.
2. **Kiểm tra `can_grade` tại Runtime**: Khi mở modal chấm thi (`openTeacherExamDetail`), hệ thống gọi API `getTeacherAssignedOverview`. Nếu giáo viên không có quyền hoặc bài thi đã bị chuyển giao cho giáo viên khác (`can_grade === false`), hệ thống tự động khóa giao diện và hiển thị thông báo lỗi:
   > *"Bạn không có quyền chấm bài thi này hoặc bài thi đã được chuyển giao cho giáo viên khác!"*

---

### 6. Cơ Chế Lưu Lịch Sử Chấm & Audit Trail (Grading History)

Mỗi lần có hành động cập nhật điểm (bởi AI, Giáo viên chấm lần 1, Giáo viên chấm lần 2, hoặc QA phúc khảo), hệ thống **bắt buộc ghi nhận một bản ghi lịch sử bất biến** vào bảng `student_score_grading_histories`:

| Trường Thông Tin | Mục Đích Lưu Trữ |
| :--- | :--- |
| `student_score_id` | ID bài thi gốc. |
| `grader_id` | ID tài khoản thực hiện chấm (User ID của Giáo viên hoặc QA). |
| `grader_role` | Vai trò khi chấm (`teacher`, `qa`, `ai_system`). |
| `skill` | Kỹ năng được chấm (`15: Writing`, `16: Speaking`). |
| `old_score` | Điểm trước khi sửa đổi. |
| `new_score` | Điểm sau khi lưu kết quả mới. |
| `criteria_breakdown`| Chi tiết điểm số từng tiêu chí (JSON Snapshot). |
| `comment` | Nhận xét chung và nhận xét từng tiêu chí của người chấm. |
| `audio_comment_url` | Đường dẫn file ghi âm nhận xét của giáo viên. |

---

### 7. Logic Xử Lý Nghi Vấn Gian Lận (Cheating Detection & Evidence)

Hệ thống cung cấp cơ chế giám sát và xử lý nghi vấn gian lận thi cử:
1. **Gán cờ gian lận (`cheating_status`)**:
   - `0`: Bài thi bình thường.
   - `1`: Bài thi có nghi vấn gian lận (bị phát hiện chuyển tab, mở ứng dụng khác, giọng nói lạ, hoặc nội dung bài viết sao chép).
2. **Bằng chứng gian lận (`cheating_reports` / Evidence Files)**:
   - Giáo viên hoặc hệ thống AI có thể đính kèm ảnh chụp màn hình vi phạm (`cheatingEvidenceFiles`) hoặc file log giám sát.
   - Khi bài thi bị xác nhận gian lận nghiêm trọng, cán bộ vận hành có thể chuyển `score_processing_status = 3` (Đã hủy kết quả).

---

### 8. Logic Đồng Bộ Điểm Sang Hệ Thống ICL / Zeus (`IclScoreService`)

Sau khi bài thi hoàn tất quá trình chấm và tính toán điểm Overall:
1. **Điều kiện đồng bộ**: `score_processing_status = 1` và học viên có liên kết hợp lệ sang hệ thống ICL.
2. **Payload đồng bộ**: Bao gồm `student_id`, `quiz_id`, `overall_score`, `listening_score`, `reading_score`, `writing_score`, `speaking_score`, kèm link chứng chỉ/báo cáo kết quả.
3. **Nhật ký đồng bộ (`student_score_icl_logs`)**: Ghi nhận toàn bộ `payload`, `response` mã lỗi hoặc mã thành công để phục vụ giám sát và retry khi mất kết nối mạng.
