dramaling-vocab-learning/複習算法完整設計方案.md

14 KiB
Raw Blame History

複習時間算法完整設計方案

🎯 核心設計原則

  1. 漸進式增長: 避免過快跳躍,符合記憶曲線
  2. 簡單有效: 邏輯清晰易懂,便於實作和維護
  3. 智能糾錯: 根據表現動態調整
  4. 科學依據: 基於間隔重複記憶理論

📐 核心算法公式

基本公式(簡化版)

新間隔 = 舊間隔 × 增長係數 × 表現係數

這個公式很簡單:

  • 舊間隔: 上次復習間隔天數
  • 增長係數: 根據當前間隔階段決定
  • 表現係數: 根據答題表現決定

📊 完整算法流程圖

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. 難易度係數計算

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. 表現係數計算

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. 階段調整係數

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]
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. 完整間隔計算公式

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)
}

📈 熟悉程度計算重新設計

多維度熟悉度模型

pie title 熟悉程度組成 (100%)
    "復習成功次數" : 40
    "當前間隔長度" : 25
    "正確率一致性" : 20
    "最近表現趨勢" : 15
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天

🎮 答題表現評分系統

翻卡題評分流程

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

客觀題評分流程

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

🔄 完整學習循環

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)

目標: 改進現有算法,保持系統穩定

// 簡化版漸進算法
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. 個人化係數調整
// 完整版算法
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. 智能錯誤恢復

連續錯誤 → 重置到較短間隔
偶爾錯誤 → 輕微調整
長期正確 → 加速進展

🔧 實作考量

資料庫設計調整

-- 新增欄位到 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 設計

// 復習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週)

這個設計提供了更科學、更個人化、更有效的復習時間管理系統!