📚 TUẦN 5: GAME ENGINE & SCORING SYSTEM
🎯 Mục tiêu tuần này: Hoàn thiện game logic, scoring algorithm, và chơi được 1 game hoàn chỉnh
1. CHỨC NĂNG CẦN HOÀN THÀNH
| STT | Chức năng | Mô tả | Output |
|---|---|---|---|
| 5.1 | Game State Machine | States: waiting → playing → finished | State transitions work |
| 5.2 | Question Broadcast | Host gửi câu hỏi → Players nhận | Đồng bộ câu hỏi |
| 5.3 | Answer Handler | Players submit answer | Validate + record |
| 5.4 | Scoring Algorithm | Điểm = đúng + nhanh | Time-based scoring |
| 5.5 | Live Leaderboard | Update sau mỗi câu | Real-time rankings |
| 5.6 | Game End Flow | Show final results | Complete game cycle |
2. KIẾN THỨC CẦN NẮM VỮNG
2.1 Game State Machine
📖 States và Transitions
┌─────────────┐ startGame ┌────── ───────┐
│ WAITING │ ──────────────────→ │ PLAYING │
│ │ │ │
│ Host tạo │ │ Questions │
│ Players join│ │ in progress │
└─────────────┘ └──────┬──────┘
│
│ lastQuestion
│ or hostEnds
▼
┌─────────────┐
│ FINISHED │
│ │
│ Show results│
│ Cleanup │
└─────────────┘
📖 PLAYING Sub-states
PLAYING
├── SHOW_QUESTION (5-10s: Hiển thị câu hỏi)
├── ANSWERING (N seconds: Players trả lời)
├── SHOW_RESULT (3-5s: Hiển thị đáp án đúng)
└── SHOW_LEADERBOARD (3-5s: Hiển thị xếp hạng)
└── Loop hoặc → FINISHED
Code Implementation:
enum GameState {
WAITING = 'waiting',
PLAYING = 'playing',
FINISHED = 'finished',
}
enum QuestionPhase {
SHOW_QUESTION = 'show_question',
ANSWERING = 'answering',
SHOW_RESULT = 'show_result',
SHOW_LEADERBOARD = 'show_leaderboard',
}
interface RoomState {
gameState: GameState;
phase?: QuestionPhase;
currentQuestionIndex: number;
questionStartTime?: number;
}
2.2 Game Flow (Full Sequence)
┌─────────────────────────────────────────────────────────────────┐
│ 1. HOST: startGame │
│ → Load questions từ PostgreSQL │
│ → Cache trong Redis hoặc memory │
│ → Set state = PLAYING │
│ → Emit 'gameStarted' to room │
└────────────────────────────────────────┬────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ 2. SERVER: sendQuestion(n) │
│ → Get question[n] (ẩn correctAnswer!) │
│ → Set questionStartTime = now() │
│ → Emit 'newQuestion' { question, timeLimit, questionNumber } │
└────────────────────────────────────────┬────────────────────────┘
▼
┌───────────────────────────────────────── ────────────────────────┐
│ 3. PLAYERS: submitAnswer │
│ → Validate: còn thời gian? chưa trả lời? │
│ → Calculate responseTime = now() - questionStartTime │
│ → Check isCorrect │
│ → Calculate score │
│ → ZINCRBY leaderboard │
│ → Emit 'answerReceived' to player │
└────────────────────────────────────────┬────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ 4. TIMEOUT hoặc ALL_ANSWERED │
│ → Emit 'showResult' { correctAnswer, stats } │
│ → Wait 3s │
│ → Emit 'leaderboardUpdate' { top10 } │
│ → Wait 3s │
│ → If more questions → Step 2 │
│ → Else → Step 5 │
└────────────────────────────────────────┬────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ 5. GAME OVER │