Thiết Kế Bài Test Chẩn Đoán 4 Loại Bệnh Tiếng Anh
Date: 2026-01-09 Status: Design Complete - Ready for Implementation Duration: 5-10 phút (adaptive based on performance) Philosophy: "Proving they haven't been taught correctly" NOT "proving they're bad"
Constants Reference: Xem
definitions.mdcho tất cả constants và enums.
Tổng Quan
Bài test chẩn đoán 4 loại "bệnh" tiếng Anh (Mù/Điếc/Câm/Yếu phản xạ) để cá nhân hóa lộ trình học 120 ngày. Test sử dụng adaptive logic với progressive gate để tối ưu thời gian và tâm lý người học.
Triết Lý Thiết Kế
Core Principles:
- Không ai bị "loại" - chỉ có "được hỏi ít hơn"
- Micro-step difficulty increase - tăng độ khó rất chậm
- Foundation-first strictness - Mù/Điếc khắt khe, Câm/Phản xạ nhân văn
- Empathy in UI - không hiển thị % điểm, không dùng từ "skip" hay "fail"
I. Cấu Trúc Test - Progressive Gate Logic
Gate Flow Architecture
START
↓
┌─────────────────────────────────┐
│ GATE 1: MÙ (Vocabulary) │
│ Duration: 2-3 phút │
│ Questions: 8-12 câu (adaptive) │
└──────────┬──────────────────────┘
↓
┌──────┴──────┐
│ Evaluate │
│ Score │
└──────┬──────┘
↓
≥60% │ 40-59% │ <40%
────┬─┴─┬────────┴────
↓ ↓ ↓
Full Reduced Flag: Mù Nặng
Next Difficulty Shorten Rest
↓
┌─────────────────────────────────┐
│ GATE 2: ĐIẾC (Listening) │
│ Duration: 2-3 phút │
│ Questions: 8-10 câu (adaptive) │
└──────────┬──────────────────────┘
↓
≥55% │ 35-54% │ <35%
────┬─┴─┬────────┴────
Normal Fewer Qs Flag: Điếc Nền
Slower
↓
┌─────────────────────────────────┐
│ GATE 3: CÂM (Speaking) │
│ Duration: 1-3 phút │
│ Questions: Adaptive 1-4 câu │
│ │
│ • Mù+Điếc OK → 3-4 câu │
│ • 1 yếu → 1-2 câu │
│ • Cả 2 yếu → 1 câu có hint │
└──────────┬──────────────────────┘
↓
┌─────────────────────────────────┐
│ GATE 4: PHẢN XẠ (Speed) │
│ Duration: 1-2 phút │
│ Questions: 3-5 câu (adaptive) │
│ │
│ • Nếu nền yếu: không countdown │
│ • Luôn có ít nhất 1 câu │
└──────────┬──────────────────────┘
↓
┌────────┐
│ RESULT │
└────────┘
Thời Gian Tổng (Trong Khung 5-10 Phút)
| User Profile | Tổng Thời Gian | Lý Do |
|---|---|---|
| Mù nặng (<40%) | 4-5 phút | Rút gọn Câm/Phản xạ |
| Mù+Điếc yếu | 6-7 phút | Test đủ 4 phần, giảm số câu |
| Qua nền (≥60%) | 8-10 phút | Full test tất cả phần |
Key Insight: Không ai cảm thấy bị "tra khảo" - thời gian tự điều chỉnh tự nhiên.
II. Chi Tiết Từng Phần Test
A. GATE 1 - MÙ (Vocabulary / Reading Comprehension)
Mục tiêu: Đánh giá vốn từ vựng và khả năng đọc hiểu cơ bản
Số Lượng Câu Hỏi
- Baseline: 10 câu
- Adaptive: 8-12 câu tùy performance
- Đúng 2-3 câu liên tiếp → tăng độ khó
- Sai 2-3 câu liên tiếp → giữ nguyên/giảm nhẹ
Loại Câu Hỏi (2 Types)
Type 1: Word Recognition (Image + 4 Words) - 60% câu
[Hiển thị hình ảnh quả táo]
Question: What is this?
A) apple ✓
B) orange
C) banana
D) grape
Difficulty levels:
- Pre-A1: apple/cat/dog
- Pre-A1+: table/chair/door
- A1-: beautiful/difficult/important
- A1: approach/consider/develop
- A1+: circumstance/acknowledge/efficient
Type 2: Word Definition Matching - 40% câu
Question: Match the word "teacher" with its meaning
A) A person who teaches ✓
B) A large building
C) An animal that flies
D) A type of food
Difficulty levels:
- Pre-A1: Simple nouns (teacher/student/doctor)
- A1-: Action verbs (run/jump/swim)
- A1: Abstract concepts (happiness/freedom/truth)
- A1+: Complex meanings (analyze/interpret/establish)
Adaptive Logic (Micro-Steps)
# Pseudocode
current_level = "A1-" # Start at medium
consecutive_correct = 0
consecutive_wrong = 0
for question in questions:
if answer_correct:
consecutive_correct += 1
consecutive_wrong = 0
if consecutive_correct >= 3:
current_level = increase_level_by_one_step(current_level)
# Pre-A1 → Pre-A1+ → A1- → A1 → A1+
consecutive_correct = 0
else:
consecutive_wrong += 1
consecutive_correct = 0
if consecutive_wrong >= 3:
current_level = decrease_level_by_one_step(current_level)
consecutive_wrong = 0
Gate Thresholds
≥ 60% correct → Full test tiếp theo
40-59% correct → Test tiếp, giảm độ khó
< 40% correct → Flag: Mù nặng, rút gọn Câm/Phản xạ
Question Bank Requirements
- Pre-A1: 30 câu (15 image + 15 definition)
- Pre-A1+: 20 câu (12 image + 8 definition)
- A1-: 20 câu (10 image + 10 definition)
- A1: 15 câu (7 image + 8 definition)
- A1+: 15 câu (6 image + 9 definition)
- Total: 100 câu
B. GATE 2 - ĐIẾC (Listening Comprehension)
Mục tiêu: Đánh giá khả năng nghe hiểu và phân biệt âm thanh
Số Lượng Câu Hỏi
- Baseline: 9 câu
- Adaptive: 8-10 câu
- Nếu Mù ≥ 60%: 10 câu full
- Nếu Mù 40-59%: 9 câu
- Nếu Mù < 40%: 8 câu, tốc độ chậm hơn
Loại Câu Hỏi (2 Types)
Type 1: Word Recognition (Audio → Choose Image) - 70% câu
[Play audio: "apple"]
[Show 4 images: apple, orange, banana, grape]
User clicks correct image
Audio settings:
- Pre-A1: Slow speed (0.75x), clear pronunciation
- A1-: Normal speed (1x)
- A1+: Natural speed with slight accent variation
Type 2: Sound Discrimination (Same/Different) - 30% câu
[Play audio 1: "ship"]
[Play audio 2: "sheep"]
Question: Are these words the same or different?
A) Same
B) Different ✓
Common pairs for Vietnamese:
- ship/sheep (khó nhất cho người Việt)
- bad/bed
- cat/cut
- lock/rock
- very/berry
Adaptive Logic
# Similar to Mù, but with audio speed adjustment
if score < 50%:
audio_speed = 0.8 # Slower
add_visual_transcript = True # Show text for last 2 questions
else:
audio_speed = 1.0 # Normal
Gate Thresholds
≥ 55% correct → Bình thường
35-54% correct → Giảm câu + tăng nghe chậm
< 35% correct → Flag: Điếc nền
Question Bank Requirements
- Pre-A1: 25 câu (18 audio→image + 7 discrimination)
- A1-: 20 câu (14 audio→image + 6 discrimination)
- A1+: 15 câu (10 audio→image + 5 discrimination)
- Total: 60 câu
C. GATE 3 - CÂM (Speaking / Pronunciation)
Mục tiêu: Xác nhận xu hướng, KHÔNG đánh giá năng lực nói đầy đủ
⚠️ Important: Phần này adaptive dựa trên kết quả Mù + Điếc
Số Lượng Câu Hỏi (Highly Adaptive)
| Trạng thái Mù + Điếc | Số câu Câm |
|---|---|
| Cả 2 ≥ 55% (OK) | 3-4 câu |
| 1 trong 2 yếu | 1-2 câu |
| Cả 2 < 40% (yếu) | 1 câu demo có hint |
Loại Câu Hỏi (2 Types)
Type 1: Word Pronunciation (Single Word) - 60% câu
[Show image: apple]
[Show text: "apple"]
[Play sample audio]
[Mic button: "Tap to speak"]
User speaks: "apple"
Azure Speech API scores: 0-100
Scoring:
- 80-100: Excellent
- 60-79: Good
- 40-59: Fair (needs work)
- 0-39: Needs improvement
Type 2: Sentence Reading - 40% câu
[Show text: "I like coffee."]
[Play sample audio - optional]
[Mic button: "Tap to read this sentence"]
User reads sentence
AI scores: pronunciation + intonation
Focus areas for Vietnamese:
- /th/ sound (think, that)
- Final consonants (cat, dog, book)
- Word linking (an apple → "anapple")
Mic Permission & Fallback
If mic permission denied:
→ Skip Câm section entirely
→ Show message: "Không thể test phát âm. Kết quả dựa trên các phần khác."
→ Câm score = "Not tested"
Question Bank Requirements
- Pre-A1: 15 words + 5 sentences
- A1: 10 words + 5 sentences
- A1+: 5 words + 5 sentences
- Total: 45 items
D. GATE 4 - PHẢN XẠ (Response Speed)
Mục tiêu: Kiểm tra tốc độ nhận diện và phản ứng (foundation skill check)
⚠️ Key Rule: Luôn có ít nhất 1 câu, nhưng nếu nền yếu thì không đo tốc độ
Số Lượng Câu Hỏi
| Trạng thái nền | Số câu | Có countdown? |
|---|---|---|
| Mù+Điếc ≥ 55% | 5 câu | Yes (3s/câu) |
| 1 yếu | 3 câu | No countdown |
| Cả 2 < 40% | 1 câu | No countdown, có hint |
Loại Câu Hỏi (2 Types)
Type 1: Flash Card (Image → Choose Word Fast) - 60% câu
[Show image: apple for 2 seconds]
[Fade image to 20% opacity]
[Show 4 options]
Countdown: 3 seconds (nếu nền tốt)
A) apple ✓
B) orange
C) banana
D) grape
Score calculation:
- Correct + < 2s = 100%
- Correct + 2-3s = 80%
- Correct + > 3s = 60%
- Wrong = 0%
Type 2: Audio Response (Hear → Choose Fast) - 40% câu
[Play audio: "apple"]
[Show 4 images immediately]
User clicks image quickly
Countdown: 3 seconds (nếu nền tốt)
Similar scoring as Type 1
Adaptive Behavior
if foundation_weak: # Mù hoặc Điếc < 40%
show_countdown = False
questions = 1 # Demo only
show_hint = True # Highlight correct answer area
message = "Phản xạ chưa hình thành - điều này bình thường!"
else:
show_countdown = True
questions = 3-5
show_hint = False
Question Bank Requirements
- Pre-A1: 15 flashcards + 10 audio
- A1: 10 flashcards + 10 audio
- Total: 45 items
III. Thuật Toán Tính Điểm & Phân Loại
A. Scoring System (Backend - Internal)
Formula: severity_score = 100 - correct_percentage
def calculate_severity_score(correct_count, total_questions):
"""
Returns internal severity score (0-100)
Higher score = more severe disease
"""
correct_percentage = (correct_count / total_questions) * 100
severity_score = 100 - correct_percentage
return severity_score
# Example:
# User gets 7/10 correct on Mù
# correct_percentage = 70%
# severity_score = 100 - 70 = 30
# → Mù severity: 30/100 (Nhẹ)
B. Threshold Mapping (UI - User-Facing)
Philosophy: Foundation skills (Mù/Điếc) strict, Output skills (Câm/Phản xạ) humane
| Disease | Nặng (Severe) | Trung Bình (Moderate) | Nhẹ (Mild) |
|---|---|---|---|
| MÙ | < 50% correct | 50-70% correct | > 70% correct |
| ĐIẾC | < 45% correct | 45-65% correct | > 65% correct |
| CÂM | < 30% correct | 30-55% correct | > 55% correct |
| PHẢN XẠ | < 30% correct | 30-60% correct | > 60% correct |
Rationale:
- Mù (strictest): No vocabulary = everything else is useless
- Điếc (slightly easier): Listening is harder than reading
- Câm (forgiving): People understand but can't speak - common pattern
- Phản xạ (most forgiving): Develops last, needs time
def map_to_severity_category(disease_name, correct_percentage):
"""
Maps correct percentage to user-facing category
"""
thresholds = {
"Mù": {"Nặng": 50, "Trung bình": 70},
"Điếc": {"Nặng": 45, "Trung bình": 65},
"Câm": {"Nặng": 30, "Trung bình": 55},
"Phản xạ": {"Nặng": 30, "Trung bình": 60},
}
t = thresholds[disease_name]
if correct_percentage < t["Nặng"]:
return "Nặng"
elif correct_percentage < t["Trung bình"]:
return "Trung bình"
else:
return "Nhẹ"
IV. Kê Đơn Thuốc (Prescription Logic)
A. Prescription Types (5 Types Total)
| Prescription ID | Tên Đơn | Khi Nào Kê | Thời Lượng |
|---|---|---|---|
RX_MU |
Đơn Mù - Học Từ Vựng | Mù nặng nhất | 120 ngày (ưu tiên từ vựng 70%) |
RX_DIEC |
Đơn Điếc - Luyện Nghe | Điếc nặng nhất | 120 ngày (ưu tiên nghe 50%) |
RX_CAM |
Đơn Câm - Luyện Phát Âm | Câm nặng nhất | 120 ngày (ưu tiên phát âm 60%) |
RX_PHAN_XA |
Đơn Phản Xạ | Phản xạ nặng nhất | 120 ngày (ưu tiên phản xạ 60%) |
RX_FOUNDATION |
Đơn Nền Tảng | Mù + Điếc cùng nặng | 120 ngày (cân bằng) |
Lưu ý quan trọng: Tất cả đơn thuốc đều kéo dài 120 ngày. Sự khác biệt nằm ở tỷ trọng thời gian dành cho mỗi kỹ năng, không phải tổng thời lượng. Xem Section C để biết chi tiết về tỷ trọng daily content.
B. Prescription Algorithm
def determine_prescription(test_results):
"""
Determines which prescription to give based on test results
Args:
test_results = {
"Mù": {"correct_pct": 35, "severity": "Nặng", "score": 65},
"Điếc": {"correct_pct": 40, "severity": "Nặng", "score": 60},
"Câm": {"correct_pct": 50, "severity": "Trung bình", "score": 50},
"Phản xạ": {"correct_pct": 45, "severity": "Trung bình", "score": 55}
}
Returns:
prescription_id, focus_areas, duration_days
"""
# Step 1: Check if all skills are good (> 70%)
if all(r["severity"] == "Nhẹ" for r in test_results.values()):
return "NOT_SUITABLE", "User already has foundation", 0
# Step 2: Count severe diseases
severe_diseases = [
name for name, result in test_results.items()
if result["severity"] == "Nặng"
]
# Step 3: Decision logic
if len(severe_diseases) == 0:
# No severe, pick highest moderate
highest = max(test_results.items(), key=lambda x: x[1]["score"])
return f"RX_{map_disease_to_id(highest[0])}", [highest[0]], 60
elif len(severe_diseases) == 1:
# One severe disease
disease = severe_diseases[0]
return f"RX_{map_disease_to_id(disease)}", [disease], 90
elif len(severe_diseases) >= 2:
# Multiple severe - check if Mù + Điếc combo
if "Mù" in severe_diseases and "Điếc" in severe_diseases:
return "RX_FOUNDATION", ["Mù", "Điếc"], 120
else:
# Use priority hierarchy internally
priority = ["Mù", "Điếc", "Câm", "Phản xạ"]
for disease in priority:
if disease in severe_diseases:
return f"RX_{map_disease_to_id(disease)}", [disease], 90
def map_disease_to_id(disease_name):
mapping = {
"Mù": "MU",
"Điếc": "DIEC",
"Câm": "CAM",
"Phản xạ": "PHAN_XA"
}
return mapping[disease_name]
C. Prescription Affects Daily Content
Mỗi đơn thuốc ảnh hưởng đến nội dung học hàng ngày như sau:
| Đơn Thuốc | Từ Vựng | Nghe | Phát Âm | Phản Xạ | Daily New Words |
|---|---|---|---|---|---|
| RX_MU | 70% | 10% | 10% | 10% | 25 |
| RX_DIEC | 20% | 50% | 20% | 10% | 10 |
| RX_CAM | 20% | 10% | 60% | 10% | 10 |
| RX_PHAN_XA | 20% | 10% | 10% | 60% | 10 |
| RX_FOUNDATION | 35% | 35% | 15% | 15% | 15 |
Ví dụ cụ thể:
User nhận RX_MU sẽ có bài học hàng ngày:
- 25 từ vựng mới (như mô tả trong
don-mu-vocabulary.md) - 2-3 bài nghe ngắn (10%)
- 2-3 từ luyện phát âm (10%)
- 1-2 bài phản xạ nhanh (10%)
User nhận RX_DIEC sẽ có bài học hàng ngày:
- 10 từ vựng mới (20%)
- 10-15 bài nghe đa dạng (50%)
- 5 từ luyện phát âm (20%)
- 2-3 bài phản xạ (10%)
User nhận RX_CAM sẽ có bài học hàng ngày:
- 10 từ vựng mới (20%)
- 2-3 bài nghe (10%)
- 15-20 từ luyện phát âm với feedback chi tiết (60%)
- 2-3 bài phản xạ (10%)
User nhận RX_PHAN_XA sẽ có bài học hàng ngày:
- 10 từ vựng mới (20%)
- 2-3 bài nghe (10%)
- 2-3 từ luyện phát âm (10%)
- 15-20 bài luyện phản xạ với tốc độ tăng dần (60%)
User nhận RX_FOUNDATION sẽ có bài học hàng ngày cân bằng:
- 15 từ vựng mới (35%)
- 8-10 bài nghe (35%)
- 5 từ luyện phát âm (15%)
- 3-5 bài phản xạ (15%)
D. Prescription ID Mapping
| Code Reference | Database Value | Display Name (VI) | Display Name (EN) |
|---|---|---|---|
| RX_MU | don_mu |
Đơn Mù - Học Từ Vựng | Vocabulary Prescription |
| RX_DIEC | don_diec |
Đơn Điếc - Luyện Nghe | Listening Prescription |
| RX_CAM | don_cam |
Đơn Câm - Luyện Phát Âm | Speaking Prescription |
| RX_PHAN_XA | don_yeu_phan_xa |
Đơn Phản Xạ | Reflex Prescription |
| RX_FOUNDATION | don_foundation |
Đơn Nền Tảng | Foundation Prescription |
Naming Convention:
- Disease name: "Yếu phản xạ" (full name - tên bệnh)
- Prescription name: "Đơn Phản Xạ" (short name - tên đơn thuốc)
- Database value:
don_yeu_phan_xa(matches disease for consistency)
E. Tie-Breaking Rules
User-Facing: KHÔNG bắt user chọn. Hệ thống quyết định một cách nhân văn.
Internal Priority Hierarchy (only for system logic):
Mù > Điếc > Câm > Phản xạ
Used for:
- Lesson ordering (Mù lessons first)
- Time weighting (Mù gets 40% of study time)
- Progress tracking priority
NOT used for: UI display or user messaging
V. Results Display (UI/UX Design)
A. Medical Report Style
Layout Structure:
┌─────────────────────────────────────────────────┐
│ Kết Quả Chẩn Đoán Của Bạn │
├─────────────────────────────────────────────────┤
│ │
│ [Empathy message] │
│ "Chúng tôi hiểu bạn đã cố gắng nhiều lần. │
│ Đây là kết quả chẩn đoán để giúp bạn bắt │
│ đầu đúng cách lần này." │
│ │
├─────────────────────────────────────────────────┤
│ │
│ 📚 TỪ VỰNG (Mù) [Nặng] │
│ Bạn đang thiếu từ vựng nền tảng │
│ → Chúng tôi sẽ giúp bạn học 1,500-3,000 từ │
│ │
│ 👂 NGHE HIỂU (Điếc) [Trung bình] │
│ Bạn nghe được một số từ đơn giản │
│ → Chúng tôi sẽ cải thiện khả năng nghe │
│ │
│ 🗣️ PHÁT ÂM (Câm) [Nhẹ] │
│ Bạn có thể phát âm khá tốt! │
│ → Chúng tôi sẽ giúp bạn hoàn thiện │
│ │
│ ⚡ PHẢN XẠ [Trung bình] │
│ Phản xạ của bạn đang hình thành │
│ → Chúng tôi sẽ luyện tốc độ phản ứng │
│ │
├─────────────────────────────────────────────────┤
│ │
│ 💊 ĐƠN THUỐC CHO BẠN │
│ │
│ [Icon Đơn Mù] │
│ "Đơn Từ Vựng Nền Tảng" │
│ 60-90 ngày | 1,500-3,000 từ Oxford │
│ │
│ [Button: Bắt Đầu Ngay] │
│ │
└─────────────────────────────────────────────────┘
B. Visual Design Specifications
Color Coding (Severity Levels):
.severity-nang {
background: #FEE2E2; /* Red-50 */
border-left: 4px solid #DC2626; /* Red-600 */
color: #991B1B; /* Red-800 */
}
.severity-trung-binh {
background: #FEF3C7; /* Yellow-50 */
border-left: 4px solid #F59E0B; /* Amber-500 */
color: #92400E; /* Amber-900 */
}
.severity-nhe {
background: #D1FAE5; /* Green-50 */
border-left: 4px solid #10B981; /* Green-500 */
color: #065F46; /* Green-900 */
}
Icons (Disease Types):
📚 Mù (Vocabulary) - Book icon
👂 Điếc (Listening) - Ear icon
🗣️ Câm (Speaking) - Speaking head icon
⚡ Phản xạ (Reflex) - Lightning bolt icon
C. Copy Guidelines
✅ DO USE:
- "Chúng tôi đã có đủ thông tin để hiểu cách bạn học tốt nhất"
- "Bạn đang gặp khó khăn với..." (not "bạn yếu/kém")
- "Chúng tôi sẽ giúp bạn khắc phục trong X ngày"
- "Phản xạ chưa hình thành - điều này bình thường!"
❌ DON'T USE:
- "Bạn không đủ điều kiện làm tiếp"
- "Skipped due to low score"
- "Điểm của bạn: 25%"
- "Bạn thất bại ở phần..."
- Any form of shame or judgment
D. Edge Case: User Too Good (All > 70%)
┌─────────────────────────────────────────────────┐
│ Kết Quả Của Bạn │
├─────────────────────────────────────────────────┤
│ │
│ 🎉 Chúc mừng! │
│ │
│ Bạn đã có nền tảng tiếng Anh khá tốt │
│ (A2-B1 level). Chương trình Learn English │
│ Zero được thiết kế cho người mất gốc hoàn │
│ toàn. │
│ │
│ Chúng tôi gợi ý bạn: │
│ │
│ • Học IELTS/TOEIC để có chứng chỉ │
│ • Thử các khóa B2+ trên Coursera │
│ • Xem kênh YouTube: [list channels] │
│ │
│ [Button: Tìm Hiểu Thêm] │
│ │
└─────────────────────────────────────────────────┘
VI. Edge Cases & Error Handling
A. Technical Issues
| Issue | Handling | User Message |
|---|---|---|
| Mic permission denied | Skip Câm section | "Không thể test phát âm. Kết quả dựa trên các phần khác." |
| Audio playback fails | Retry 3 times, then skip question | "Đang tải lại audio..." |
| Internet disconnect | Save progress, resume on reconnect | "Mất kết nối. Đang lưu tiến trình..." |
| API timeout (Azure) | Use fallback scoring | Silent fallback, no user message |
B. User Behavior Edge Cases
| Scenario | Detection | Handling |
|---|---|---|
| Random clicking | < 1s per answer, all wrong | Flag test as invalid, ask to retake |
| Tab switching | Blur event > 30s | Pause timer, show warning |
| Mic test fail | Silent audio input | Show mic setup guide |
| Leaves mid-test | Save progress | Resume from last gate on return |
C. Retesting Policy
Rule: Initial diagnostic test is locked after completion
┌─────────────────────────────────────────────────┐
│ ⚠️ Test Đã Hoàn Thành │
├─────────────────────────────────────────────────┤
│ │
│ Bạn đã hoàn thành test chẩn đoán. │
│ │
│ Test này chỉ làm 1 lần để đảm bảo kết quả │
│ chính xác và "đơn thuốc" phù hợp nhất. │
│ │
│ • Bạn sẽ có "mini-check" mỗi 30 ngày │
│ để theo dõi tiến bộ │
│ │
│ • Kết quả sẽ được cập nhật tự động │
│ │
│ [Button: Xem Kết Quả Hiện Tại] │
│ │
└─────────────────────────────────────────────────┘
Monthly Mini-Checks (separate feature):
- Same format but shorter (3-4 phút)
- 5 questions per disease type
- Tracks progress over time
- Does NOT change prescription
VII. Data Model & Storage
A. Database Schema
# diagnosis_test table
class DiagnosisTest(Base):
__tablename__ = "diagnosis_tests"
id = Column(UUID, primary_key=True)
user_id = Column(UUID, ForeignKey("users.id"))
test_type = Column(String) # "initial" | "monthly_check"
# Test metadata
started_at = Column(DateTime)
completed_at = Column(DateTime)
duration_seconds = Column(Integer)
# Raw scores (internal)
mu_correct = Column(Integer)
mu_total = Column(Integer)
mu_score = Column(Float) # Severity score (0-100)
diec_correct = Column(Integer)
diec_total = Column(Integer)
diec_score = Column(Float)
cam_correct = Column(Integer)
cam_total = Column(Integer)
cam_score = Column(Float)
phan_xa_correct = Column(Integer)
phan_xa_total = Column(Integer)
phan_xa_score = Column(Float)
# Categorized results (user-facing)
mu_severity = Column(String) # "Nặng" | "Trung bình" | "Nhẹ"
diec_severity = Column(String)
cam_severity = Column(String)
phan_xa_severity = Column(String)
# Prescription
prescription_id = Column(String) # RX_MU, RX_FOUNDATION, etc.
prescription_focus = Column(JSON) # ["Mù", "Điếc"]
prescription_duration_days = Column(Integer)
# Adaptive test metadata
questions_asked = Column(JSON) # Array of question IDs
gate_adjustments = Column(JSON) # Track difficulty changes
# Flags
is_valid = Column(Boolean) # False if cheating detected
invalid_reason = Column(String)
# test_question_responses table
class TestQuestionResponse(Base):
__tablename__ = "test_question_responses"
id = Column(UUID, primary_key=True)
test_id = Column(UUID, ForeignKey("diagnosis_tests.id"))
question_id = Column(UUID)
# Question details
disease_type = Column(String) # "Mù" | "Điếc" | "Câm" | "Phản xạ"
question_type = Column(String) # "word_recognition", "sound_discrimination", etc.
difficulty_level = Column(String) # "Pre-A1", "A1-", etc.
# Response
user_answer = Column(JSON)
correct_answer = Column(JSON)
is_correct = Column(Boolean)
response_time_ms = Column(Integer)
# Audio/pronunciation specific
audio_url = Column(String) # For Điếc/Câm
pronunciation_score = Column(Float) # For Câm (0-100 from Azure)
created_at = Column(DateTime)
# question_bank table
class QuestionBankItem(Base):
__tablename__ = "question_bank"
id = Column(UUID, primary_key=True)
disease_type = Column(String)
question_type = Column(String)
difficulty_level = Column(String)
# Question content
question_data = Column(JSON)
# Example for Mù word_recognition:
# {
# "image_url": "/assets/images/apple.jpg",
# "correct_answer": "apple",
# "options": ["apple", "orange", "banana", "grape"]
# }
correct_answer = Column(JSON)
# Audio for Điếc/Câm
audio_url = Column(String)
audio_speed = Column(Float) # 0.75, 1.0, etc.
# Metadata
usage_count = Column(Integer)
avg_correct_rate = Column(Float)
is_active = Column(Boolean)
created_at = Column(DateTime)
B. Question Bank Statistics (Target)
| Disease | Difficulty | Count | Ratio |
|---|---|---|---|
| Mù | Pre-A1 | 30 | 30% |
| Pre-A1+ | 20 | 20% | |
| A1- | 20 | 20% | |
| A1 | 15 | 15% | |
| A1+ | 15 | 15% | |
| Total | 100 | ||
| Điếc | Pre-A1 | 25 | 42% |
| A1- | 20 | 33% | |
| A1+ | 15 | 25% | |
| Total | 60 | ||
| Câm | Pre-A1 | 20 | 44% |
| A1 | 15 | 33% | |
| A1+ | 10 | 23% | |
| Total | 45 | ||
| Phản xạ | Pre-A1 | 25 | 56% |
| A1 | 20 | 44% | |
| Total | 45 | ||
| GRAND TOTAL | 250 |
VIII. Testing & Validation
A. Pre-Launch Testing
Test with 10 Beta Users:
- 3 người mất gốc hoàn toàn (Pre-A1)
- 3 người có chút kiến thức (A1)
- 2 người khá tốt (A2+)
- 2 người giỏi (B1+)
Metrics to Track:
- Average completion time per profile
- Gate transition rates
- Prescription distribution
- User feedback on difficulty
- Emotional response to UI copy
B. Quality Assurance Checklist
- All 250 questions reviewed by English teacher
- Audio recordings clear and accurate
- Image assets appropriate and clear
- Thresholds validated with sample data
- Gate logic produces expected results
- UI copy reviewed for empathy
- Mobile responsive on iOS/Android
- Mic permission flow tested
- Edge cases handled gracefully
- Data persists correctly
C. Success Metrics (Post-Launch)
| Metric | Target | Measurement |
|---|---|---|
| Completion rate | > 85% | % who finish all 4 gates |
| Average duration | 6-8 min | Median completion time |
| Prescription distribution | Balanced | Should see mix of all 5 types |
| User sentiment | Positive | Post-test survey (1-5 scale) |
| Technical errors | < 2% | % tests with API failures |
IX. Implementation Roadmap
Phase 1: Question Bank Creation (Week 1-2)
- Create 100 Mù questions (images + definitions)
- Record 60 Điếc audio files
- Create 45 Câm pronunciation items
- Create 45 Phản xạ flashcards/audio
- Review all content with native speaker
Phase 2: Backend API (Week 2-3)
- Implement adaptive test engine
- Build gate logic with thresholds
- Create prescription algorithm
- Setup Azure Speech integration for Câm
- Database schema + migrations
Phase 3: Frontend UI (Week 3-4)
- Test flow screens (4 gates)
- Results display (medical report style)
- Prescription reveal screen
- Mic permission + audio playback
- Mobile responsive design
Phase 4: Testing & Refinement (Week 4-5)
- Internal testing (team)
- Beta testing (10 users)
- Refine thresholds based on data
- Fix bugs and edge cases
- Polish UI copy
Phase 5: Launch (Week 6)
- Deploy to production
- Monitor metrics
- Collect user feedback
- Iterate based on real data
X. Open Questions & Future Iterations
Questions for User Research
- Is the medical metaphor (Mù/Điếc/Câm) clear and not offensive?
- Does the "not suitable" message for advanced users feel good?
- Is 5-10 minutes the right length?
- Should we show progress bar during test?
Future Enhancements (V2)
- AI-generated question variants (hybrid approach)
- Video-based questions for Câm (facial recognition)
- Accent detection (North/South Vietnam)
- Peer comparison (anonymized)
- Gamification elements in monthly checks
Research Needed
- Validate thresholds with 100+ users (adjust if needed)
- A/B test different UI approaches for results
- Study correlation between test results and 120-day completion
- Analyze which prescription types have best outcomes
Appendix A: Example Test Flow (Full Walkthrough)
User Profile: Người mất gốc, học từ cấp 2-cấp 3 nhưng quên hết
START TEST
Gate 1: Mù (2.5 phút)
Questions 1-3 (Pre-A1 level):
- Q1: [Image: apple] → Correct (✓)
- Q2: Match "teacher" → Correct (✓)
- Q3: [Image: cat] → Correct (✓)
System: 3 consecutive correct → increase to Pre-A1+
Questions 4-6 (Pre-A1+ level):
- Q4: [Image: chair] → Correct (✓)
- Q5: Match "beautiful" → Wrong (✗)
- Q6: [Image: door] → Correct (✓)
Questions 7-10 (Pre-A1+ level maintained):
- Q7-10: Mixed results (2 correct, 2 wrong)
Result: 7/10 correct = 70% → Severity: Nhẹ
Gate 1 decision: Score ≥ 60% → Full test for Gate 2
Gate 2: Điếc (2.5 phút)
Questions 1-3 (Pre-A1 level, slow audio):
- Q1: Hear "apple" → Choose image → Correct (✓)
- Q2: Discrimination: ship/sheep → Wrong (✗)
- Q3: Hear "cat" → Choose image → Correct (✓)
Questions 4-9 (Pre-A1 maintained):
- Q4-9: Mixed results (3 correct, 3 wrong)
Result: 5/9 correct = 56% → Severity: Trung Bình
Gate 2 decision: Score 55-65% range → Proceed to Câm with normal questions
Gate 3: Câm (2 phút)
Mù OK + Điếc OK → 3 questions
Question 1: Pronounce "apple"
- User speaks into mic
- Azure Speech score: 72/100
- Result: Good (✓)
Question 2: Read sentence "I like coffee"
- User reads
- Azure Speech score: 65/100
- Result: Fair (✓)
Question 3: Pronounce "beautiful"
- User speaks
- Azure Speech score: 55/100
- Result: Fair (✓)
Result: 3/3 attempted, avg score 64 → Severity: Trung Bình
Gate 4: Phản Xạ (1.5 phút)
Foundation moderate → 4 questions with countdown
Question 1: Flash [apple image 2s] → Choose word in 3s
- Response time: 2.1s → Correct (✓)
Question 2: Audio "cat" → Choose image in 3s
- Response time: 2.8s → Correct (✓)
Question 3: Flash [chair image 2s] → Choose word in 3s
- Response time: 3.5s (timeout) → Wrong (✗)
Question 4: Audio "dog" → Choose image in 3s
- Response time: 1.8s → Correct (✓)
Result: 3/4 correct = 75%, but avg time 2.55s → Severity: Nhẹ
RESULTS CALCULATION
test_results = {
"Mù": {
"correct_pct": 70,
"severity": "Nhẹ",
"score": 30 # 100 - 70
},
"Điếc": {
"correct_pct": 56,
"severity": "Trung bình",
"score": 44 # 100 - 56
},
"Câm": {
"correct_pct": 64,
"severity": "Trung bình",
"score": 36 # 100 - 64
},
"Phản xạ": {
"correct_pct": 75,
"severity": "Nhẹ",
"score": 25 # 100 - 75
}
}
# No severe diseases
# Highest score: Điếc (44)
prescription = "RX_DIEC"
focus = ["Điếc"]
duration = 60 # days
RESULTS SCREEN (UI)
┌─────────────────────────────────────────────────┐
│ Kết Quả Chẩn Đoán Của Bạn │
├─────────────────────────────────────────────────┤
│ │
│ Cảm ơn bạn đã hoàn thành test! Chúng tôi │
│ đã hiểu được điểm mạnh và điểm cần cải │
│ thiện của bạn. │
│ │
├─────────────────────────────────────────────────┤
│ │
│ 📚 TỪ VỰNG (Mù) [Nhẹ] │
│ Bạn có vốn từ vựng cơ bản khá tốt! │
│ → Chúng tôi sẽ giúp bạn mở rộng thêm │
│ │
│ 👂 NGHE HIỂU (Điếc) [Trung bình] ⚠️ │
│ Bạn cần cải thiện khả năng nghe │
│ → Chúng tôi sẽ tập trung vào kỹ năng này │
│ │
│ 🗣️ PHÁT ÂM (Câm) [Trung bình] │
│ Bạn phát âm được, nhưng cần luyện thêm │
│ → Chúng tôi sẽ cải thiện độ rõ ràng │
│ │
│ ⚡ PHẢN XẠ [Nhẹ] │
│ Phản xạ của bạn khá tốt! │
│ → Chúng tôi sẽ giúp bạn nhanh hơn nữa │
│ │
├─────────────────────────────────────────────────┤
│ │
│ 💊 ĐƠN THUỐC CHO BẠN │
│ │
│ 👂 "Đơn Luyện Nghe Nền Tảng" │
│ │
│ Trong 60 ngày, chúng tôi sẽ: │
│ • Luyện nghe 1,000 câu thông dụng │
│ • Phân biệt âm khó (ship/sheep, bad/bed) │
│ • Nghe hiểu podcast đơn giản │
│ │
│ [Button: Bắt Đầu Ngay →] │
│ │
└─────────────────────────────────────────────────┘
Total Duration: 8.5 phút (trong khung 5-10 phút ✓)
Appendix B: Technical Integration Checklist
Frontend Components Needed
-
DiagnosisTestContainer.tsx- Main test orchestrator -
GateMu.tsx- Mù test component -
GateDiec.tsx- Điếc test component (audio playback) -
GateCam.tsx- Câm test component (mic recording) -
GatePhanXa.tsx- Phản xạ test component (countdown) -
TestResults.tsx- Results display -
PrescriptionReveal.tsx- Prescription screen -
ProgressBar.tsx- Test progress indicator -
AudioPlayer.tsx- Reusable audio component -
MicRecorder.tsx- Reusable mic recording component
Backend API Endpoints
-
POST /api/v1/diagnosis/start- Initialize test session -
POST /api/v1/diagnosis/answer- Submit answer for question -
GET /api/v1/diagnosis/next-question- Get next adaptive question -
POST /api/v1/diagnosis/complete- Finalize test, calculate prescription -
GET /api/v1/diagnosis/results/{test_id}- Retrieve results -
POST /api/v1/pronunciation/score- Azure Speech scoring -
GET /api/v1/question-bank/random- Get random question by criteria
External Service Integration
- Azure Speech API (pronunciation scoring)
- Azure Blob Storage (audio files, images)
- Supabase Auth (user identification)
- Supabase PostgreSQL (data persistence)
Environment Variables
AZURE_SPEECH_KEY=
AZURE_SPEECH_REGION=
AZURE_STORAGE_CONNECTION_STRING=
SUPABASE_URL=
SUPABASE_ANON_KEY=
References & Related Documents
- definitions.md: Single source of truth cho tất cả constants và enums
- don-mu-vocabulary.md: Chi tiết lộ trình học từ vựng 120 ngày (cho RX_MU)
- database-schema.md: Schema database cho
user_diagnosis_resultsvà prescription types - ai-coach-behavior.md: AI Coach behavior sau khi nhận kết quả chẩn đoán
- user-flow.md: UI/UX flow cho màn hình test và results
- gamification.md: Milestones và streak system liên quan đến tiến độ sau chẩn đoán
Document Version: 1.1 Last Updated: 2026-01-09 Next Review: After beta testing (Week 5)
Contributors: Founder + Claude Code Status: ✅ Design Complete - Ready for Implementation