# 📚 Hướng Dẫn Quản Lý Nội Dung Giảng Dạy và Game ## Tổng Quan Kiến Trúc Hệ thống nội dung của bạn được xây dựng theo mô hình phân cấp: ``` Subject (Môn học/Giáo trình) └─ Chapter (Chương) └─ Lesson (Bài học) ├─ JSON Content → Game Engine render └─ URL Content → Video/PDF player ``` --- ## 📊 Cấu Trúc Models ### 1. Subject (Môn học) **File**: `models/Subject.js` **Table**: `subjects` ```javascript { id: UUID, subject_code: 'MATH_G1', // Mã môn học (unique) subject_name: 'Toán lớp 1', // Tên tiếng Việt subject_name_en: 'Math Grade 1', // Tên tiếng Anh description: TEXT, // Mô tả is_active: true, // Đang hoạt động is_premium: false, // Nội dung premium is_training: false, // Đào tạo nhân sự is_public: false, // Tự học công khai required_role: 'student', // Role yêu cầu min_subscription_tier: 'basic' // Gói tối thiểu } ``` ### 2. Chapter (Chương học) **File**: `models/Chapter.js` **Table**: `chapters` ```javascript { id: UUID, subject_id: UUID, // FK → subjects chapter_number: 1, // Số thứ tự chương chapter_title: 'Số và chữ số', // Tiêu đề chapter_description: TEXT, // Mô tả duration_minutes: 180, // Thời lượng (phút) is_published: true, // Đã xuất bản display_order: 1 // Thứ tự hiển thị } ``` ### 3. Lesson (Bài học) **File**: `models/Lesson.js` **Table**: `lessons` ```javascript { id: UUID, chapter_id: UUID, // FK → chapters lesson_number: 1, // Số thứ tự bài học lesson_title: 'Đếm từ 1 đến 5', // Tiêu đề lesson_type: 'json_content', // hoặc 'url_content' lesson_description: TEXT, // Dạng 1: JSON Content (tương tác) content_json: { type: 'counting_quiz', // PHẢI khớp với Game.type questions: [...], instructions: '...', pass_score: 70 }, // Dạng 2: URL Content (video/PDF/link) content_url: 'https://youtube.com/...', content_type: 'youtube', // video, audio, pdf, external_link duration_minutes: 15, is_published: true, is_free: true, // Học thử miễn phí display_order: 1, thumbnail_url: '...' } ``` ### 4. Game (Game Engine/Template) **File**: `models/Game.js` **Table**: `games` ```javascript { id: UUID, title: 'Trò chơi đếm số', description: TEXT, url: 'https://games.senaai.tech/counting-game/', // HTML5/Unity WebGL thumbnail: '...', type: 'counting_quiz', // PHẢI khớp với Lesson.content_json.type config: { engine: 'phaser3', features: ['sound', 'animation'], controls: ['touch', 'mouse'], max_time: 300 }, is_active: true, is_premium: false, min_grade: 1, // Cấp lớp tối thiểu max_grade: 3, // Cấp lớp tối đa difficulty_level: 'easy', // easy, medium, hard play_count: 0, rating: 4.5 } ``` --- ## 🎯 Cách 1: Thêm Nội Dung Giảng Dạy ### Bước 1: Tạo Subject (Môn học) ```javascript const { Subject, Chapter, Lesson } = require('./models'); // Tạo môn Toán lớp 1 const mathSubject = await Subject.create({ subject_code: 'MATH_G1', subject_name: 'Toán lớp 1', subject_name_en: 'Math Grade 1', description: 'Chương trình Toán học lớp 1 theo SGK mới', is_active: true, is_premium: false, is_public: true, min_subscription_tier: 'basic' }); ``` ### Bước 2: Tạo Chapter (Chương) ```javascript const chapter1 = await Chapter.create({ subject_id: mathSubject.id, chapter_number: 1, chapter_title: 'Số và chữ số', chapter_description: 'Làm quen với các số từ 1 đến 10', duration_minutes: 180, is_published: true, display_order: 1 }); const chapter2 = await Chapter.create({ subject_id: mathSubject.id, chapter_number: 2, chapter_title: 'Phép cộng trong phạm vi 10', chapter_description: 'Học cộng các số từ 1 đến 10', duration_minutes: 240, is_published: true, display_order: 2 }); ``` ### Bước 3a: Tạo Lesson với JSON Content (Tương tác) ```javascript const lesson1 = await Lesson.create({ chapter_id: chapter1.id, lesson_number: 1, lesson_title: 'Đếm từ 1 đến 5', lesson_type: 'json_content', lesson_description: 'Học đếm các số từ 1 đến 5 qua trò chơi', content_json: { type: 'counting_quiz', // Khớp với Game có type='counting_quiz' theme: 'fruits', questions: [ { id: 1, question: 'Có bao nhiêu quả táo?', image: 'https://cdn.senaai.tech/images/apples-3.png', correct_answer: 3, options: [2, 3, 4, 5] }, { id: 2, question: 'Có bao nhiêu quả cam?', image: 'https://cdn.senaai.tech/images/oranges-5.png', correct_answer: 5, options: [3, 4, 5, 6] } ], instructions: 'Nhìn vào hình và đếm số lượng vật, sau đó chọn đáp án đúng', pass_score: 70, max_attempts: 3, show_hints: true }, duration_minutes: 15, is_published: true, is_free: true, display_order: 1, thumbnail_url: 'https://cdn.senaai.tech/thumbnails/lesson-counting.jpg' }); ``` ### Bước 3b: Tạo Lesson với URL Content (Video/PDF) ```javascript // Video YouTube const lesson2 = await Lesson.create({ chapter_id: chapter1.id, lesson_number: 2, lesson_title: 'Video: Hướng dẫn đếm số', lesson_type: 'url_content', lesson_description: 'Video hướng dẫn cách đếm số từ 1 đến 10', content_url: 'https://www.youtube.com/watch?v=abc123xyz', content_type: 'youtube', duration_minutes: 10, is_published: true, is_free: false, display_order: 2 }); // PDF Document const lesson3 = await Lesson.create({ chapter_id: chapter1.id, lesson_number: 3, lesson_title: 'Tài liệu: Bảng số từ 1-10', lesson_type: 'url_content', content_url: 'https://cdn.senaai.tech/docs/number-chart-1-10.pdf', content_type: 'pdf', duration_minutes: 5, is_published: true, is_free: true, display_order: 3 }); // Audio const lesson4 = await Lesson.create({ chapter_id: chapter1.id, lesson_number: 4, lesson_title: 'Nghe: Phát âm các số', lesson_type: 'url_content', content_url: 'https://cdn.senaai.tech/audio/numbers-pronunciation.mp3', content_type: 'audio', duration_minutes: 8, is_published: true, display_order: 4 }); ``` ### Bước 3c: Các loại Content JSON khác ```javascript // Quiz trắc nghiệm const quizLesson = await Lesson.create({ chapter_id: chapter2.id, lesson_number: 1, lesson_title: 'Bài kiểm tra: Phép cộng', lesson_type: 'json_content', content_json: { type: 'multiple_choice_quiz', time_limit: 600, // 10 phút questions: [ { id: 1, question: '2 + 3 = ?', options: ['4', '5', '6', '7'], correct_answer: '5', explanation: 'Hai cộng ba bằng năm' }, { id: 2, question: '4 + 5 = ?', options: ['7', '8', '9', '10'], correct_answer: '9' } ], pass_score: 80 }, duration_minutes: 10, is_published: true }); // Bài tập tương tác const interactiveLesson = await Lesson.create({ chapter_id: chapter2.id, lesson_number: 2, lesson_title: 'Thực hành: Giải toán cộng', lesson_type: 'json_content', content_json: { type: 'math_practice', difficulty: 'easy', operations: ['addition'], range: { min: 1, max: 10 }, question_count: 20, show_solution_steps: true, allow_calculator: false }, duration_minutes: 20, is_published: true }); // Assignment (Bài tập về nhà) const assignmentLesson = await Lesson.create({ chapter_id: chapter2.id, lesson_number: 3, lesson_title: 'Bài tập về nhà: Tuần 1', lesson_type: 'json_content', content_json: { type: 'assignment', deadline_days: 7, tasks: [ { task_id: 1, title: 'Làm bài tập SGK trang 15', description: 'Hoàn thành các bài từ 1 đến 5', points: 10 }, { task_id: 2, title: 'Vẽ 5 quả táo và đếm', description: 'Vẽ hình và viết số', points: 5, requires_upload: true } ], total_points: 15, submission_type: 'photo' // photo, pdf, text }, duration_minutes: 30, is_published: true }); ``` --- ## 🎮 Cách 2: Thêm Game Engine ### Tạo Game Template ```javascript const { Game } = require('./models'); // Game 1: Đếm số const countingGame = await Game.create({ title: 'Trò chơi đếm số', description: 'Game tương tác giúp trẻ học đếm các vật thể', url: 'https://games.senaai.tech/counting-game/index.html', thumbnail: 'https://cdn.senaai.tech/game-thumbs/counting.jpg', type: 'counting_quiz', // Khớp với Lesson.content_json.type config: { engine: 'phaser3', version: '1.0.0', features: ['sound', 'animation', 'reward_stars'], controls: ['touch', 'mouse', 'keyboard'], responsive: true, max_time_per_question: 60, hints_enabled: true, save_progress: true }, is_active: true, is_premium: false, min_grade: 1, max_grade: 2, difficulty_level: 'easy', play_count: 0, rating: 0, display_order: 1 }); // Game 2: Quiz trắc nghiệm const quizGame = await Game.create({ title: 'Trả lời nhanh', description: 'Trò chơi trắc nghiệm với giới hạn thời gian', url: 'https://games.senaai.tech/quiz-game/index.html', thumbnail: 'https://cdn.senaai.tech/game-thumbs/quiz.jpg', type: 'multiple_choice_quiz', config: { engine: 'react', features: ['timer', 'leaderboard', 'achievements'], sound_effects: true, show_correct_answer: true, retry_allowed: true }, is_active: true, is_premium: false, min_grade: 1, max_grade: 12, difficulty_level: 'medium', display_order: 2 }); // Game 3: Thực hành Toán const mathPracticeGame = await Game.create({ title: 'Luyện tập Toán', description: 'Game luyện toán với nhiều cấp độ khó', url: 'https://games.senaai.tech/math-practice/index.html', thumbnail: 'https://cdn.senaai.tech/game-thumbs/math.jpg', type: 'math_practice', config: { engine: 'unity_webgl', features: ['adaptive_difficulty', 'step_by_step_solution', 'scratch_pad'], controls: ['touch', 'mouse'], performance_tracking: true }, is_active: true, is_premium: true, min_grade: 1, max_grade: 6, difficulty_level: 'medium', display_order: 3 }); // Game 4: Word Puzzle const wordPuzzleGame = await Game.create({ title: 'Ghép chữ', description: 'Trò chơi ghép chữ và học từ vựng', url: 'https://games.senaai.tech/word-puzzle/index.html', thumbnail: 'https://cdn.senaai.tech/game-thumbs/word.jpg', type: 'word_puzzle', config: { engine: 'phaser3', features: ['drag_drop', 'text_to_speech', 'pronunciation'], languages: ['vi', 'en'], difficulty_levels: ['easy', 'medium', 'hard'] }, is_active: true, is_premium: false, min_grade: 1, max_grade: 5, difficulty_level: 'easy', display_order: 4 }); ``` --- ## 🔄 Luồng Hoạt Động ### Frontend Flow ```javascript // 1. Học viên chọn môn học GET /api/subjects/:subject_id → Trả về thông tin Subject // 2. Xem danh sách chương GET /api/subjects/:subject_id/chapters → Trả về danh sách Chapter // 3. Xem danh sách bài học trong chương GET /api/chapters/:chapter_id/lessons → Trả về danh sách Lesson // 4. Học một bài cụ thể GET /api/lessons/:lesson_id → Trả về chi tiết Lesson // 5a. Nếu lesson_type = 'json_content' const lessonType = lesson.content_json.type; // vd: 'counting_quiz' // Tìm game engine phù hợp GET /api/games?type=counting_quiz → Trả về Game có type khớp // Load game và truyền content vào