# 智能複習系統 - 技術規格書 (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 newBaseMastery = CalculateMasteryLevel(
request.TimesCorrect + (request.IsCorrect ? 1 : 0),
request.TotalReviews + 1,
newInterval
);
return new ReviewResult
{
NewInterval = newInterval,
NextReviewDate = actualReviewDate.AddDays(newInterval), // 以復習當日為基準
BaseMasteryLevel = newBaseMastery, // 基礎熟悉度
CurrentMasteryLevel = newBaseMastery, // 剛復習完,兩者相等
IsOverdue = overdueDays > 0,
OverdueDays = Math.Max(0, overdueDays)
};
}
///
/// 計算當前熟悉度 (實時計算,不存資料庫)
///
public int CalculateCurrentMasteryLevel(Flashcard flashcard)
{
var daysSinceLastReview = (DateTime.Now.Date - flashcard.LastReviewDate.Date).Days;
// 如果沒有時間經過,返回基礎熟悉度
if (daysSinceLastReview <= 0)
return flashcard.BaseMasteryLevel;
// 應用記憶衰減
return ApplyMemoryDecay(flashcard.BaseMasteryLevel, daysSinceLastReview);
}
}
```
---
## 🔌 **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",
"baseMasteryLevel": 65, // 基礎熟悉度 (存資料庫)
"currentMasteryLevel": 65, // 當前熟悉度 (實時計算)
"isOverdue": false,
"overdueDays": 0
}
}
```
### **GET /api/flashcards/{id}**
#### **響應格式**
```json
{
"success": true,
"data": {
"id": 123,
"word": "apple",
"definition": "蘋果",
"baseMasteryLevel": 75, // 基礎熟悉度 (資料庫值)
"currentMasteryLevel": 68, // 當前熟悉度 (考慮衰減)
"lastReviewDate": "2025-09-20",
"nextReviewDate": "2025-10-04",
"currentInterval": 14,
"timesCorrect": 8,
"totalReviews": 10,
"isOverdue": true,
"overdueDays": 1
}
}
```
#### **錯誤響應**
```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, -- 上次實際復習日期
BaseMasteryLevel INT DEFAULT 0, -- 基礎熟悉度 (上次復習時的值)
OverdueCount INT DEFAULT 0, -- 逾期次數統計
ConsecutiveOverdue INT DEFAULT 0; -- 連續逾期次數
-- 注意: CurrentMasteryLevel 不存資料庫,透過 API 實時計算
```
### **索引優化**
```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;
[Histogram("mastery_calculation_duration_ms")]
public static readonly Histogram MasteryCalculationDuration;
[Gauge("overdue_reviews_current")]
public static readonly Gauge OverdueReviews;
[Counter("mastery_calculations_total")]
public static readonly Counter MasteryCalculations;
}
```
### **日誌記錄**
- **INFO**: 正常復習記錄
- **WARN**: 逾期復習、異常參數
- **ERROR**: 計算失敗、資料庫錯誤
---
## 🚀 **部署需求**
### **性能要求**
- **API 響應時間**: P95 < 100ms
- **並發處理**: 支援 1000+ 同時用戶
- **資料庫連線**: 連線池最大 50 連線
### **環境配置**
- **.NET 8+** 運行環境
- **SQLite/PostgreSQL** 資料庫
- **Memory/Redis** 緩存 (可選)
### **部署檢查清單**
- [ ] 資料庫遷移腳本執行
- [ ] 配置文件更新
- [ ] 監控指標接入
- [ ] 日誌收集配置
- [ ] 性能測試通過
---
**實施時間**: 2-3個工作日
**測試時間**: 1個工作日
**上線影響**: 零停機時間部署