dramaling-vocab-learning/note/複習系統/技術實作規格.md

353 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 複習系統技術實作規格書
**版本**: 1.0
**對應PRD**: 產品需求規格.md
**目標讀者**: 開發者、技術主管
**最後更新**: 2025-10-03
---
## 📊 **核心算法和公式**
### **進度條計算公式**
```typescript
進度百分比 = (今日完成) / (今日完成 + 今日到期) * 100
```
**實作範例**:
```typescript
const progressPercentage = completedToday / (completedToday + dueToday) * 100
```
### **複習間隔算法**
```typescript
下一次複習時間 = 當前時間 + (2^成功複習次數)
```
**實作範例**:
```typescript
const nextReviewDate = new Date()
nextReviewDate.setDate(nextReviewDate.getDate() + Math.pow(2, successCount))
```
---
## 🏷️ **卡片狀態管理機制**
### **延遲註記系統**
**新增延遲註記的情況**:
1. 用戶點選 "跳過" → 卡片標記 `isDelayed: true`
2. 用戶答錯題目 → 卡片標記 `isDelayed: true`
**延遲註記的影響**:
```typescript
// 撈取下一個複習卡片時排除延遲卡片
const nextCards = allCards.filter(card => !card.isDelayed)
```
**消除延遲註記**:
```typescript
// 用戶答對題目時
if (isCorrect) {
card.isDelayed = false
card.successCount++
card.nextReviewDate = calculateNextReviewDate(card.successCount)
}
```
---
## 🎯 **測驗模式實作**
### **階段1: 翻卡記憶 (已實作)**
**數據結構**:
```typescript
interface FlashcardData {
id: string
word: string
definition: string
example: string
exampleTranslation: string
pronunciation: string
synonyms: string[]
cefr: string
}
```
**狀態管理**:
```typescript
const [isFlipped, setIsFlipped] = useState(false)
const [selectedConfidence, setSelectedConfidence] = useState<number | null>(null)
const [cardHeight, setCardHeight] = useState<number>(400)
```
**信心度評分映射**:
```typescript
const confidenceToScore = {
1: 0, // 完全不懂 → 答錯
2: 0, // 模糊 → 答錯
3: 1, // 一般 → 答對
4: 1, // 熟悉 → 答對
5: 1 // 非常熟悉 → 答對
}
```
### **階段2: 詞彙選擇題 (計劃中)**
**選項生成算法**:
```typescript
// 暫時使用固定選項 (MVP階段)
const mockOptions = ['apple', 'orange', 'banana', correctAnswer]
const shuffledOptions = shuffle(mockOptions)
```
**未來升級方案**:
```typescript
// 基於詞性和CEFR等級生成干擾項
const generateDistractors = (correctWord, allWords) => {
const samePOS = allWords.filter(w => w.partOfSpeech === correctWord.partOfSpeech)
const sameCEFR = allWords.filter(w => w.cefr === correctWord.cefr)
return selectRandom([...samePOS, ...sameCEFR], 3)
}
```
---
## 🎨 **UI/UX實作規格**
### **翻卡動畫參數**
```css
/* 3D翻卡動畫 - 已調校的完美參數 */
.flip-card {
perspective: 1000px;
transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}
.flip-card.flipped {
transform: rotateY(180deg);
}
```
### **響應式高度計算**
```typescript
const calculateCardHeight = () => {
const backHeight = backRef.current?.scrollHeight || 0
const minHeight = window.innerWidth <= 480 ? 300 :
window.innerWidth <= 768 ? 350 : 400
return Math.max(minHeight, backHeight)
}
```
### **信心度按鈕配色**
```typescript
const confidenceColors = {
1: 'bg-red-100 text-red-700 border-red-200', // 完全不懂
2: 'bg-orange-100 text-orange-700 border-orange-200', // 模糊
3: 'bg-yellow-100 text-yellow-700 border-yellow-200', // 一般
4: 'bg-blue-100 text-blue-700 border-blue-200', // 熟悉
5: 'bg-green-100 text-green-700 border-green-200' // 非常熟悉
}
```
---
## 📱 **API設計規格** (階段3實作)
### **獲取複習卡片API**
```typescript
GET /api/flashcards/due?limit=10
Response:
{
"success": true,
"data": {
"flashcards": FlashcardData[],
"count": number
},
"timestamp": string
}
```
### **記錄複習結果API**
```typescript
POST /api/flashcards/{id}/review
Request:
{
"confidence": number, // 1-5
"isCorrect": boolean, // 基於confidence >= 3判斷
"reviewType": "flip-memory",
"responseTimeMs": number
}
Response:
{
"success": boolean,
"nextReviewDate": string,
"newSuccessCount": number
}
```
---
## 🗄️ **數據存儲設計**
### **階段1: 內存狀態 (當前)**
```typescript
// 純React狀態會話結束即消失
const [currentIndex, setCurrentIndex] = useState(0)
const [score, setScore] = useState({ correct: 0, total: 0 })
```
### **階段2: 本地存儲 (計劃)**
```typescript
// localStorage持久化
const saveProgress = (progress: ReviewProgress) => {
localStorage.setItem('review-progress', JSON.stringify({
currentIndex,
score,
timestamp: Date.now()
}))
}
```
### **階段3: 後端同步 (遠期)**
```typescript
// 與後端API同步
const syncProgress = async (progress: ReviewProgress) => {
await api.post('/api/user/review-progress', progress)
}
```
---
## 🔒 **業務邏輯約束**
### **狀態轉換規則**
```typescript
// 卡片狀態轉換
enum CardState {
PENDING = 'pending', // 未開始
COMPLETED = 'completed', // 已完成
DELAYED = 'delayed' // 延遲 (跳過或答錯)
}
// 狀態轉換邏輯
const handleAnswer = (confidence: number) => {
if (confidence >= 3) {
// 答對: 移除延遲標記,標記完成
card.state = CardState.COMPLETED
card.isDelayed = false
card.successCount++
} else {
// 答錯: 添加延遲標記
card.isDelayed = true
card.state = CardState.DELAYED
}
}
```
### **隊列管理邏輯**
```typescript
// 下一張卡片選擇邏輯
const getNextCard = (cards: FlashCard[]) => {
// 1. 優先選擇未延遲的卡片
const normalCards = cards.filter(c => !c.isDelayed && c.state === CardState.PENDING)
if (normalCards.length > 0) {
return normalCards[0]
}
// 2. 如果沒有正常卡片,選擇延遲卡片
const delayedCards = cards.filter(c => c.isDelayed)
return delayedCards[0] || null
}
```
---
## ⚡ **性能和優化規格**
### **載入性能要求**
```typescript
// 性能指標
const PERFORMANCE_TARGETS = {
INITIAL_LOAD: 2000, // 初始載入 < 2秒
CARD_FLIP: 500, // 翻卡響應 < 500ms
CONFIDENCE_SELECT: 200, // 按鈕響應 < 200ms
NAVIGATION: 300 // 頁面切換 < 300ms
}
```
### **記憶體管理**
```typescript
// 避免記憶體洩漏
useEffect(() => {
const timer = setTimeout(updateHeight, 100)
const resizeHandler = () => updateHeight()
window.addEventListener('resize', resizeHandler)
return () => {
clearTimeout(timer)
window.removeEventListener('resize', resizeHandler)
}
}, [dependencies])
```
---
## 🧪 **測試規格** (TDD Implementation)
### **測試覆蓋要求**
- **核心邏輯**: 100% 測試覆蓋
- **UI組件**: 關鍵交互測試
- **API調用**: Mock測試
- **狀態管理**: 狀態轉換測試
### **測試案例範例**
```typescript
// 翻卡邏輯測試
describe('FlipCard Component', () => {
test('應該在點擊時切換翻轉狀態', () => {
const { result } = renderHook(() => useFlipCard())
act(() => result.current.flip())
expect(result.current.isFlipped).toBe(true)
})
test('應該在選擇信心度時觸發提交', () => {
const onSubmit = jest.fn()
const card = render(<FlipCard onSubmit={onSubmit} />)
card.selectConfidence(4)
expect(onSubmit).toHaveBeenCalledWith(4)
})
})
```
---
## 📋 **實作檢查清單**
### **每個功能完成時檢查**
- [ ] 功能符合產品需求規格
- [ ] 遵循技術約束和算法
- [ ] 通過所有相關測試
- [ ] 性能指標達標
- [ ] 無記憶體洩漏
- [ ] 錯誤處理完善
### **代碼品質標準**
- [ ] TypeScript 無錯誤
- [ ] ESLint 無警告
- [ ] 組件 < 200行
- [ ] 函數 < 20行
- [ ] 嵌套層次 < 3層
---
*技術實作規格維護者: 開發團隊*
*版本控制: 與產品需求規格同步更新*
*目的: 確保實作準確性避免開發失控*