505 lines
14 KiB
Markdown
505 lines
14 KiB
Markdown
# 複習時間算法完整設計方案
|
||
|
||
## 🎯 **核心設計原則**
|
||
|
||
1. **漸進式增長**: 避免過快跳躍,符合記憶曲線
|
||
2. **簡單有效**: 邏輯清晰易懂,便於實作和維護
|
||
3. **智能糾錯**: 根據表現動態調整
|
||
4. **科學依據**: 基於間隔重複記憶理論
|
||
|
||
## 📐 **核心算法公式**
|
||
|
||
### **基本公式(簡化版)**
|
||
```
|
||
新間隔 = 舊間隔 × 增長係數 × 表現係數
|
||
```
|
||
|
||
這個公式很簡單:
|
||
- **舊間隔**: 上次復習間隔天數
|
||
- **增長係數**: 根據當前間隔階段決定
|
||
- **表現係數**: 根據答題表現決定
|
||
|
||
## 📊 **完整算法流程圖**
|
||
|
||
```mermaid
|
||
graph TD
|
||
A[開始復習] --> B[獲取詞彙資訊]
|
||
B --> C[計算難易度係數]
|
||
C --> D[進行復習測試]
|
||
D --> E[記錄答題結果]
|
||
E --> F[計算表現係數]
|
||
F --> G[計算新的復習間隔]
|
||
G --> H[更新熟悉程度]
|
||
H --> I[設定下次復習時間]
|
||
I --> J[結束]
|
||
|
||
C --> C1[詞彙CEFR等級]
|
||
C --> C2[學習者程度]
|
||
C --> C3[歷史表現]
|
||
|
||
F --> F1[翻卡題評分]
|
||
F --> F2[客觀題正確率]
|
||
F --> F3[反應時間]
|
||
|
||
G --> G1[前次間隔]
|
||
G --> G2[難易度係數]
|
||
G --> G3[表現係數]
|
||
G --> G4[階段調整係數]
|
||
```
|
||
|
||
## 🧮 **詳細算法設計**
|
||
|
||
### **1. 難易度係數計算**
|
||
|
||
```typescript
|
||
interface DifficultyCalculation {
|
||
wordLevel: CEFRLevel // 詞彙等級
|
||
learnerLevel: CEFRLevel // 學習者程度
|
||
wordFrequency: number // 詞彙使用頻率
|
||
personalHistory: number // 個人歷史表現
|
||
}
|
||
|
||
function calculateDifficultyFactor(params: DifficultyCalculation): number {
|
||
const levels = ['A1', 'A2', 'B1', 'B2', 'C1', 'C2']
|
||
const wordIndex = levels.indexOf(params.wordLevel)
|
||
const learnerIndex = levels.indexOf(params.learnerLevel)
|
||
|
||
// 基礎難度差異
|
||
const levelDifference = wordIndex - learnerIndex
|
||
const baseFactor = 1.0 + (levelDifference * 0.15)
|
||
|
||
// 詞頻調整(高頻詞較容易)
|
||
const frequencyAdjustment = params.wordFrequency > 1000 ? -0.1 : 0.1
|
||
|
||
// 個人歷史調整
|
||
const historyAdjustment = (params.personalHistory - 0.7) * 0.2
|
||
|
||
return Math.max(0.8, Math.min(2.2,
|
||
baseFactor + frequencyAdjustment + historyAdjustment
|
||
))
|
||
}
|
||
```
|
||
|
||
### **2. 表現係數計算**
|
||
|
||
```typescript
|
||
interface PerformanceData {
|
||
questionType: QuestionType
|
||
isCorrect: boolean
|
||
responseTime: number // 反應時間(秒)
|
||
confidence: number // 信心程度(1-5)
|
||
}
|
||
|
||
function calculatePerformanceFactor(data: PerformanceData): number {
|
||
let baseFactor: number
|
||
|
||
switch (data.questionType) {
|
||
case 'flipcard':
|
||
// 翻卡題:根據信心程度
|
||
const confidenceFactors = [0.5, 0.7, 1.0, 1.2, 1.4]
|
||
baseFactor = confidenceFactors[data.confidence - 1]
|
||
break
|
||
|
||
case 'multiple_choice':
|
||
case 'fill_blank':
|
||
case 'listening':
|
||
// 客觀題:正確/錯誤 + 反應時間
|
||
if (data.isCorrect) {
|
||
// 反應時間越快,表現越好
|
||
const timeBonus = data.responseTime < 3 ? 0.1 :
|
||
data.responseTime < 8 ? 0.0 : -0.1
|
||
baseFactor = 1.1 + timeBonus
|
||
} else {
|
||
baseFactor = 0.6
|
||
}
|
||
break
|
||
|
||
default:
|
||
baseFactor = data.isCorrect ? 1.0 : 0.6
|
||
}
|
||
|
||
return Math.max(0.4, Math.min(1.5, baseFactor))
|
||
}
|
||
```
|
||
|
||
### **3. 階段調整係數**
|
||
|
||
```mermaid
|
||
graph LR
|
||
A[當前間隔] --> B{間隔階段}
|
||
B -->|1-7天| C[初期階段<br/>係數: 1.8-2.2]
|
||
B -->|8-30天| D[成長階段<br/>係數: 1.4-1.8]
|
||
B -->|31-90天| E[穩定階段<br/>係數: 1.2-1.5]
|
||
B -->|91-365天| F[熟練階段<br/>係數: 1.1-1.3]
|
||
```
|
||
|
||
```typescript
|
||
function getStageAdjustment(currentInterval: number): number {
|
||
if (currentInterval <= 7) return 2.0 // 初期快速增長
|
||
if (currentInterval <= 30) return 1.6 // 成長期中等增長
|
||
if (currentInterval <= 90) return 1.35 // 穩定期緩慢增長
|
||
return 1.15 // 熟練期微調
|
||
}
|
||
```
|
||
|
||
### **4. 完整間隔計算公式**
|
||
|
||
```typescript
|
||
function calculateNextInterval(params: {
|
||
previousInterval: number
|
||
difficulty: DifficultyCalculation
|
||
performance: PerformanceData
|
||
reviewCount: number
|
||
}): number {
|
||
|
||
const difficultyFactor = calculateDifficultyFactor(params.difficulty)
|
||
const performanceFactor = calculatePerformanceFactor(params.performance)
|
||
const stageAdjustment = getStageAdjustment(params.previousInterval)
|
||
|
||
// 主要公式
|
||
let nextInterval = params.previousInterval *
|
||
difficultyFactor *
|
||
performanceFactor *
|
||
stageAdjustment
|
||
|
||
// 最小間隔保護
|
||
nextInterval = Math.max(1, nextInterval)
|
||
|
||
// 最大間隔限制
|
||
nextInterval = Math.min(365, nextInterval)
|
||
|
||
// 四捨五入到整天
|
||
return Math.round(nextInterval)
|
||
}
|
||
```
|
||
|
||
## 📈 **熟悉程度計算重新設計**
|
||
|
||
### **多維度熟悉度模型**
|
||
|
||
```mermaid
|
||
pie title 熟悉程度組成 (100%)
|
||
"復習成功次數" : 40
|
||
"當前間隔長度" : 25
|
||
"正確率一致性" : 20
|
||
"最近表現趨勢" : 15
|
||
```
|
||
|
||
```typescript
|
||
function calculateMasteryLevel(params: {
|
||
successfulReviews: number
|
||
currentInterval: number
|
||
totalReviews: number
|
||
recentPerformance: number[] // 最近5次表現
|
||
}): number {
|
||
|
||
// 1. 成功次數分數 (40%)
|
||
const successScore = Math.min(params.successfulReviews * 4, 40)
|
||
|
||
// 2. 間隔長度分數 (25%)
|
||
const intervalScore = Math.min((params.currentInterval / 365) * 25, 25)
|
||
|
||
// 3. 一致性分數 (20%)
|
||
const accuracy = params.totalReviews > 0 ?
|
||
params.successfulReviews / params.totalReviews : 0
|
||
const consistencyScore = accuracy * 20
|
||
|
||
// 4. 趨勢分數 (15%)
|
||
const recentAvg = params.recentPerformance.length > 0 ?
|
||
params.recentPerformance.reduce((a, b) => a + b) / params.recentPerformance.length : 0.7
|
||
const trendScore = recentAvg * 15
|
||
|
||
return Math.min(100, Math.round(
|
||
successScore + intervalScore + consistencyScore + trendScore
|
||
))
|
||
}
|
||
```
|
||
|
||
## 📅 **復習時間線對比**
|
||
|
||
### **現有算法 vs 新算法**
|
||
|
||
| 復習次數 | 現有算法 | 新算法(理想情況) | 新算法(困難詞彙) | 新算法(簡單詞彙) |
|
||
|---------|---------|-----------------|-----------------|-----------------|
|
||
| 1次成功 | 2天 | 2天 | 2天 | 3天 |
|
||
| 2次成功 | 4天 | 4天 | 3天 | 6天 |
|
||
| 3次成功 | 8天 | 7天 | 5天 | 12天 |
|
||
| 4次成功 | 16天 | 12天 | 8天 | 24天 |
|
||
| 5次成功 | 32天 | 21天 | 13天 | 42天 |
|
||
| 6次成功 | 64天 | 35天 | 22天 | 75天 |
|
||
| 7次成功 | 128天 | 60天 | 35天 | 130天 |
|
||
| 8次成功 | 256天 | 95天 | 55天 | 200天 |
|
||
| 9次成功 | 512天 | 145天 | 85天 | 300天 |
|
||
| 10次成功 | 1024天 | 220天 | 130天 | 365天 |
|
||
|
||
## 🎮 **答題表現評分系統**
|
||
|
||
### **翻卡題評分流程**
|
||
|
||
```mermaid
|
||
graph TD
|
||
A[顯示詞彙] --> B[用戶自我評估]
|
||
B --> C{選擇信心程度}
|
||
C -->|1| D[完全不記得<br/>係數: 0.5]
|
||
C -->|2| E[有印象但不確定<br/>係數: 0.7]
|
||
C -->|3| F[記得但需思考<br/>係數: 1.0]
|
||
C -->|4| G[清楚記得<br/>係數: 1.2]
|
||
C -->|5| H[非常熟悉<br/>係數: 1.4]
|
||
|
||
D --> I[計算新間隔]
|
||
E --> I
|
||
F --> I
|
||
G --> I
|
||
H --> I
|
||
```
|
||
|
||
### **客觀題評分流程**
|
||
|
||
```mermaid
|
||
graph TD
|
||
A[開始答題] --> B[記錄開始時間]
|
||
B --> C[用戶選擇答案]
|
||
C --> D[記錄結束時間]
|
||
D --> E[計算反應時間]
|
||
E --> F{答案正確?}
|
||
|
||
F -->|正確| G[基礎係數: 1.1]
|
||
F -->|錯誤| H[基礎係數: 0.6]
|
||
|
||
G --> I{反應時間}
|
||
I -->|< 3秒| J[快速正確<br/>+0.1獎勵]
|
||
I -->|3-8秒| K[正常速度<br/>無調整]
|
||
I -->|> 8秒| L[緩慢回答<br/>-0.1懲罰]
|
||
|
||
H --> M[錯誤分析]
|
||
M --> N[記錄錯題類型]
|
||
|
||
J --> O[最終係數計算]
|
||
K --> O
|
||
L --> O
|
||
N --> O
|
||
```
|
||
|
||
## 🔄 **完整學習循環**
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant U as 用戶
|
||
participant S as 系統
|
||
participant A as 算法引擎
|
||
participant D as 資料庫
|
||
|
||
U->>S: 開始今日復習
|
||
S->>D: 查詢到期詞彙
|
||
D->>S: 返回復習列表
|
||
S->>A: 選擇復習題型
|
||
A->>S: 返回題目配置
|
||
|
||
loop 每個詞彙
|
||
S->>U: 展示題目
|
||
U->>S: 提交答案
|
||
S->>A: 分析表現
|
||
A->>A: 計算新間隔
|
||
A->>A: 更新熟悉度
|
||
A->>D: 保存復習記錄
|
||
end
|
||
|
||
S->>U: 復習完成報告
|
||
```
|
||
|
||
## 📋 **實作階段規劃**
|
||
|
||
### **階段1: 基礎優化 (Week 1)**
|
||
|
||
#### **目標**: 改進現有算法,保持系統穩定
|
||
|
||
```typescript
|
||
// 簡化版漸進算法
|
||
function calculateNextIntervalV1(
|
||
previousInterval: number,
|
||
isCorrect: boolean,
|
||
confidence: number = 3
|
||
): number {
|
||
let growthFactor: number
|
||
|
||
// 階段性增長係數
|
||
if (previousInterval <= 7) {
|
||
growthFactor = 1.8 // 初期較快
|
||
} else if (previousInterval <= 30) {
|
||
growthFactor = 1.4 // 中期放緩
|
||
} else {
|
||
growthFactor = 1.2 // 後期緩慢
|
||
}
|
||
|
||
// 表現調整
|
||
const performanceFactors = [0.5, 0.7, 1.0, 1.2, 1.4]
|
||
const performanceFactor = isCorrect ?
|
||
performanceFactors[confidence - 1] : 0.6
|
||
|
||
const nextInterval = previousInterval * growthFactor * performanceFactor
|
||
return Math.max(1, Math.min(365, Math.round(nextInterval)))
|
||
}
|
||
```
|
||
|
||
### **階段2: 個人化增強 (Week 2-3)**
|
||
|
||
#### **新增功能**:
|
||
1. **詞彙難度分析**
|
||
2. **學習者程度評估**
|
||
3. **個人化係數調整**
|
||
|
||
```typescript
|
||
// 完整版算法
|
||
class SpacedRepetitionEngine {
|
||
calculateNextInterval(params: {
|
||
flashcard: Flashcard
|
||
learner: LearnerProfile
|
||
performance: PerformanceData
|
||
history: ReviewHistory[]
|
||
}): number {
|
||
|
||
const difficulty = this.analyzeDifficulty(params.flashcard, params.learner)
|
||
const performance = this.analyzePerformance(params.performance)
|
||
const trend = this.analyzeTrend(params.history)
|
||
|
||
return this.computeInterval(difficulty, performance, trend)
|
||
}
|
||
}
|
||
```
|
||
|
||
### **階段3: 智能優化 (Week 4)**
|
||
|
||
#### **高級功能**:
|
||
1. **遺忘曲線預測**
|
||
2. **最佳復習時機推薦**
|
||
3. **學習效率分析**
|
||
|
||
## 📈 **效果預測圖表**
|
||
|
||
### **學習進度曲線對比**
|
||
|
||
```
|
||
熟悉程度 (%)
|
||
100 | ╭─── 新算法
|
||
| ╭───╯
|
||
80 | ╭───╯
|
||
| ╭───╯
|
||
60 | ╭───╯
|
||
|╭───╯
|
||
40 |╯
|
||
|
|
||
20 | ╭── 現有算法
|
||
| ╭───╯
|
||
0 +─────────────────────────→
|
||
0 5 10 15 20 25 30 復習次數
|
||
|
||
新算法特點:
|
||
- 更平滑的進度曲線
|
||
- 避免過早達到100%
|
||
- 提供更多中間階段
|
||
```
|
||
|
||
### **復習間隔增長對比**
|
||
|
||
```
|
||
間隔天數
|
||
400 |
|
||
| ●── 現有算法 (過快)
|
||
300 | ╱
|
||
| ╱
|
||
200 |╱
|
||
|
|
||
100 | ╭──●──●──●── 新算法 (平滑)
|
||
| ╱
|
||
50 |╱
|
||
|
|
||
0 +────────────────────→
|
||
1 5 10 15 20 復習次數
|
||
```
|
||
|
||
## 🎯 **關鍵改進點**
|
||
|
||
### **1. 更科學的增長曲線**
|
||
- **初期**: 較快增長建立信心
|
||
- **中期**: 穩定增長鞏固記憶
|
||
- **後期**: 緩慢增長保持長期記憶
|
||
|
||
### **2. 個人化學習路徑**
|
||
```
|
||
A1學習者 + C1詞彙 = 較慢增長 + 更多練習
|
||
C1學習者 + A1詞彙 = 較快增長 + 適度練習
|
||
```
|
||
|
||
### **3. 智能錯誤恢復**
|
||
```
|
||
連續錯誤 → 重置到較短間隔
|
||
偶爾錯誤 → 輕微調整
|
||
長期正確 → 加速進展
|
||
```
|
||
|
||
## 🔧 **實作考量**
|
||
|
||
### **資料庫設計調整**
|
||
```sql
|
||
-- 新增欄位到 Flashcard 表
|
||
ALTER TABLE Flashcards ADD COLUMN EasinessFactor REAL DEFAULT 2.5;
|
||
ALTER TABLE Flashcards ADD COLUMN ConsecutiveCorrect INTEGER DEFAULT 0;
|
||
ALTER TABLE Flashcards ADD COLUMN LastPerformanceScore REAL DEFAULT 0.0;
|
||
|
||
-- 新增復習記錄表
|
||
CREATE TABLE ReviewSessions (
|
||
Id TEXT PRIMARY KEY,
|
||
FlashcardId TEXT,
|
||
ReviewedAt DATETIME,
|
||
QuestionType TEXT,
|
||
IsCorrect BOOLEAN,
|
||
ResponseTimeMs INTEGER,
|
||
ConfidenceLevel INTEGER,
|
||
PreviousInterval INTEGER,
|
||
NewInterval INTEGER,
|
||
FOREIGN KEY (FlashcardId) REFERENCES Flashcards(Id)
|
||
);
|
||
```
|
||
|
||
### **API 設計**
|
||
```typescript
|
||
// 復習API
|
||
POST /api/flashcards/{id}/review
|
||
{
|
||
questionType: 'flipcard' | 'multiple_choice' | 'fill_blank',
|
||
isCorrect: boolean,
|
||
responseTimeMs: number,
|
||
confidenceLevel?: number, // 1-5, 僅翻卡題
|
||
selectedAnswer?: string, // 客觀題的選擇
|
||
}
|
||
|
||
// 響應
|
||
{
|
||
success: boolean,
|
||
data: {
|
||
newInterval: number,
|
||
nextReviewDate: string,
|
||
masteryLevel: number,
|
||
improvementTip?: string
|
||
}
|
||
}
|
||
```
|
||
|
||
## 🧪 **測試與驗證計畫**
|
||
|
||
### **A/B測試設計**
|
||
1. **控制組**: 使用現有算法
|
||
2. **實驗組**: 使用新算法
|
||
3. **測試指標**:
|
||
- 學習完成率
|
||
- 長期記憶保持率
|
||
- 用戶滿意度
|
||
- 復習頻率合理性
|
||
|
||
### **參數調優策略**
|
||
1. **收集用戶數據** (2週)
|
||
2. **分析學習模式** (1週)
|
||
3. **調整算法參數** (1週)
|
||
4. **驗證效果** (2週)
|
||
|
||
這個設計提供了更科學、更個人化、更有效的復習時間管理系統! |