# 智能複習系統 - 技術規格書 (TSD) **目標讀者**: 後端開發工程師、系統架構師 **版本**: 1.0 **日期**: 2025-09-25 --- ## 🏗️ **系統架構** ### **核心服務** ``` ┌─────────────────────┐ │ 復習記錄 API │ └─────────┬───────────┘ │ ┌─────▼─────┐ │ 輸入驗證層 │ └─────┬─────┘ │ ┌───────▼────────┐ │ SpacedRepetition │ │ Service │ │ ┌─────────────┐ │ │ │ 逾期檢測 │ │ │ │ 間隔計算 │ │ │ │ 熟悉度更新 │ │ │ └─────────────┘ │ └───────┬────────┘ │ ┌─────▼─────┐ │ 數據持久化 │ └───────────┘ ``` ### **關鍵類別設計** #### **SpacedRepetitionService** ```csharp public class SpacedRepetitionService { public ReviewResult ProcessReview(ReviewRequest request) { // 1. 計算逾期天數 (明確時間基準) var actualReviewDate = DateTime.Now.Date; // 復習行為當日 var overdueDays = (actualReviewDate - request.NextReviewDate.Date).Days; // 2. 應用記憶衰減 var adjustedMastery = ApplyMemoryDecay(request.CurrentMastery, overdueDays); // 3. 計算新間隔 var newInterval = CalculateNewInterval( request.CurrentInterval, request.IsCorrect, request.ConfidenceLevel, overdueDays ); // 4. 更新熟悉程度 var newMastery = CalculateMasteryLevel( request.TimesCorrect + (request.IsCorrect ? 1 : 0), request.TotalReviews + 1, newInterval ); return new ReviewResult { NewInterval = newInterval, NextReviewDate = actualReviewDate.AddDays(newInterval), // 以復習當日為基準 MasteryLevel = newMastery, IsOverdue = overdueDays > 0, OverdueDays = Math.Max(0, overdueDays) }; } } ``` --- ## 🔌 **API 設計** ### **POST /api/flashcards/{id}/review** #### **請求格式** ```json { "isCorrect": boolean, "confidenceLevel": number, // 1-5, 翻卡題必須 "questionType": "flipcard" | "multiple_choice" | "fill_blank" } ``` #### **響應格式** ```json { "success": true, "data": { "newInterval": 15, "nextReviewDate": "2025-10-10", "masteryLevel": 65, "isOverdue": false, "overdueDays": 0 } } ``` #### **錯誤響應** ```json { "success": false, "error": { "code": "VALUE_OUT_OF_RANGE", "message": "信心程度必須在 1-5 範圍內", "field": "confidenceLevel" } } ``` --- ## 🛡️ **安全與驗證** ### **輸入驗證規則** ```csharp public class ReviewRequestValidator : AbstractValidator { public ReviewRequestValidator() { RuleFor(x => x.IsCorrect).NotNull(); RuleFor(x => x.ConfidenceLevel) .InclusiveBetween(1, 5) .When(x => x.QuestionType == "flipcard"); RuleFor(x => x.QuestionType) .Must(BeValidQuestionType) .WithMessage("questionType 必須是 flipcard, multiple_choice 或 fill_blank"); } } ``` ### **錯誤處理策略** - **4xx 錯誤**: 客戶端輸入錯誤,返回詳細錯誤訊息 - **5xx 錯誤**: 服務器錯誤,記錄日誌並返回通用錯誤訊息 - **資料庫錯誤**: 重試機制,最多3次重試 --- ## 💾 **資料庫設計** ### **資料表更新** ```sql -- 現有 Flashcards 表需要的欄位 ALTER TABLE Flashcards ADD COLUMN LastReviewDate DATETIME, -- 上次實際復習日期 OverdueCount INT DEFAULT 0, -- 逾期次數統計 ConsecutiveOverdue INT DEFAULT 0; -- 連續逾期次數 ``` ### **索引優化** ```sql -- 提升查詢到期詞卡的性能 CREATE INDEX IX_Flashcards_NextReviewDate ON Flashcards(NextReviewDate, UserId); -- 提升逾期統計查詢性能 CREATE INDEX IX_Flashcards_OverdueStats ON Flashcards(LastReviewDate, NextReviewDate); ``` --- ## ⚙️ **配置管理** ### **appsettings.json 配置** ```json { "SpacedRepetition": { "GrowthFactors": { "ShortTerm": 1.8, "MediumTerm": 1.4, "LongTerm": 1.2, "VeryLongTerm": 1.1 }, "OverduePenalties": { "Light": 0.9, // 1-3天 "Medium": 0.75, // 4-7天 "Heavy": 0.5, // 8-30天 "Extreme": 0.3 // >30天 }, "MemoryDecayRate": 0.05, // 每天5%衰減 "MaxInterval": 365 } } ``` --- ## 🔍 **監控與日誌** ### **關鍵指標監控** ```csharp public class ReviewMetrics { [Counter("reviews_processed_total")] public static readonly Counter ReviewsProcessed; [Histogram("review_calculation_duration_ms")] public static readonly Histogram CalculationDuration; [Gauge("overdue_reviews_current")] public static readonly Gauge OverdueReviews; } ``` ### **日誌記錄** - **INFO**: 正常復習記錄 - **WARN**: 逾期復習、異常參數 - **ERROR**: 計算失敗、資料庫錯誤 --- ## 🚀 **部署需求** ### **性能要求** - **API 響應時間**: P95 < 100ms - **並發處理**: 支援 1000+ 同時用戶 - **資料庫連線**: 連線池最大 50 連線 ### **環境配置** - **.NET 8+** 運行環境 - **SQLite/PostgreSQL** 資料庫 - **Memory/Redis** 緩存 (可選) ### **部署檢查清單** - [ ] 資料庫遷移腳本執行 - [ ] 配置文件更新 - [ ] 監控指標接入 - [ ] 日誌收集配置 - [ ] 性能測試通過 --- **實施時間**: 2-3個工作日 **測試時間**: 1個工作日 **上線影響**: 零停機時間部署