# 共同API規格

## 📋 概述

**文檔名稱**: 跨平台API規格定義  
**建立日期**: 2025-09-09  
**適用平台**: Mobile App / Web App  
**API版本**: v1  
**基礎URL**: `https://api.dramaling.com/api/v1`  

本文檔定義了Drama Ling系統中所有平台通用的API接口規格。

## 🔧 通用設計原則

### RESTful 設計
- 使用標準HTTP方法 (GET, POST, PUT, DELETE)
- 資源導向的URL設計
- 統一的狀態碼使用
- JSON格式的請求和回應

### 認證機制
- JWT Bearer Token認證
- 訪問令牌有效期: 1小時
- 刷新令牌有效期: 30天
- 自動令牌刷新機制

### 錯誤處理
- 統一的錯誤回應格式
- 多語言錯誤訊息支援
- 詳細的錯誤碼系統

### 回應格式
```typescript
interface APIResponse<T> {
  success: boolean;
  data?: T;
  error?: APIError;
  message: string;
  meta: {
    timestamp: string;
    requestId: string;
    version: string;
  };
}

interface APIError {
  code: string;
  message: string;
  details?: any;
}
```

## 🔐 認證相關API

### 用戶註冊
```http
POST /auth/register
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "securePassword123",
  "username": "learner123",
  "nativeLanguage": "zh-TW",
  "learningLanguages": ["en"]
}
```

**回應**:
```typescript
interface RegisterResponse {
  userId: string;
  username: string;
  email: string;
  accessToken: string;
  refreshToken: string;
  expiresIn: number;
  userRole: string;
}
```

### 用戶登入
```http
POST /auth/login
Content-Type: application/json

{
  "email": "user@example.com", 
  "password": "securePassword123",
  "platform": "mobile" | "web",
  "rememberMe": boolean
}
```

### Token刷新
```http
POST /auth/refresh
Authorization: Bearer <refresh_token>
```

### 第三方登入
```http
POST /auth/social
Content-Type: application/json

{
  "provider": "google" | "apple" | "facebook",
  "token": "social_provider_token",
  "platform": "mobile" | "web"
}
```

## 👤 用戶資料API

### 獲取用戶資料
```http
GET /users/profile
Authorization: Bearer <access_token>
```

### 更新用戶資料
```http
PUT /users/profile
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "username": "newUsername",
  "nativeLanguage": "zh-TW",
  "learningLanguages": ["en", "ja"],
  "profile": {
    "firstName": "John",
    "lastName": "Doe",
    "bio": "Language learning enthusiast"
  }
}
```

### 獲取學習進度
```http
GET /users/progress
Authorization: Bearer <access_token>
Query Parameters:
- skill: string (optional) - vocabulary|dialogue|pronunciation
- timeframe: string (optional) - day|week|month|all
```

**回應**:
```typescript
interface ProgressResponse {
  overallProgress: number;
  skillProgress: {
    vocabulary: SkillProgress;
    dialogue: SkillProgress; 
    pronunciation: SkillProgress;
  };
  recentAchievements: Achievement[];
  nextGoals: Goal[];
}
```

### 獲取遊戲統計
```http
GET /users/game-stats
Authorization: Bearer <access_token>
```

## 📚 學習內容API

### 獲取階段列表
```http
GET /stages
Authorization: Bearer <access_token>
Query Parameters:
- language: string (required) - 語言代碼
- includeProgress: boolean (optional) - 是否包含進度資訊
```

**回應**:
```typescript
interface StagesList {
  stages: Array<{
    stageId: string;
    stageName: string;
    description: string;
    order: number;
    totalScripts: number;
    unlockedScripts: number;
    completedScripts: number;
    isUnlocked: boolean;
    progress: {
      percentage: number;
      starsEarned: number;
      totalStars: number;
    };
  }>;
  userProgress: {
    currentStageId: string;
    overallProgress: number;
    totalStarsEarned: number;
  };
}
```

### 獲取劇本列表
```http
GET /scripts
Authorization: Bearer <access_token>
Query Parameters:
- stageId: string (required) - 階段ID
- includeProgress: boolean (optional)
```

**回應**:
```typescript
interface ScriptsList {
  scripts: Array<{
    scriptId: string;
    scriptName: string;
    sceneDescription: {
      english: string;
      chinese: string;
    };
    plotOutline: string;
    difficulty: number;
    estimatedTime: number;
    levels: {
      vocabulary: LevelStatus;
      mastery: LevelStatus;
      speaking?: LevelStatus;      // 可選關卡
      dialogue: LevelStatus;
    };
    isUnlocked: boolean;
    requiredVocabulary: string[]; // 詞彙預覽
  }>;
}

interface LevelStatus {
  isUnlocked: boolean;
  isCompleted: boolean;
  stars: number;
  bestScore?: number;
}
```

### 獲取劇本詳情
```http
GET /scripts/{scriptId}
Authorization: Bearer <access_token>
```

**回應**:
```typescript
interface ScriptDetail {
  scriptId: string;
  scriptName: string;
  sceneDescription: {
    english: string;
    chinese: string;
  };
  plotOutline: string;
  openingDialogue: Array<{
    character: string;
    english: string;
    chinese: string;
    userRole: boolean;
  }>;
  plotTasks: Array<{
    taskDescription: string;
    exampleEnglish: string;
    exampleChinese: string;
  }>;
  requiredVocabulary: VocabularyDetail[];
  levels: {
    vocabulary: DetailedLevelInfo;
    mastery: DetailedLevelInfo;
    speaking?: DetailedLevelInfo;
    dialogue: DetailedLevelInfo;
  };
}

interface DetailedLevelInfo {
  levelType: string;
  isUnlocked: boolean;
  isCompleted: boolean;
  stars: number;
  lifePointsCost: number;
  diamondsCost?: number;        // 僅口說練習關卡
  description: string;
  estimatedTime: number;
  prerequisites: string[];
  rewards: {
    xp: number;
    diamonds?: number;
    items?: string[];
  };
}
```

### 獲取詞彙列表
```http
GET /vocabulary
Authorization: Bearer <access_token>
Query Parameters:
- language: string (required) - 語言代碼
- level: string (optional) - CEFR等級 (A1/A2/B1/B2/C1/C2)
- category: string (optional) - 詞彙分類
- stageId: string (optional) - 關卡ID (用於獲取特定關卡的詞彙)
- limit: number (optional) - 返回數量限制 (預設5)
- offset: number (optional) - 偏移量
```

### 獲取詞彙詳情
```http
GET /vocabulary/{vocabularyId}
Authorization: Bearer <access_token>
```

**回應**:
```typescript
interface VocabularyDetail {
  id: string;
  word: string;                 // 詞彙本體 (原形)
  level: string;               // CEFR等級 (A1/A2/B1/B2/C1/C2)
  phonetic: string;            // IPA音標
  definition: string;          // 英文定義
  originalSentence: string;    // Source句子 (學習者遇到的真實語境)
  originalHighlight: string;   // Source句子中要標註的詞
  exampleSentence: string;     // Example句子 (教學例句)
  exampleHighlight: string;    // Example句子中要標註的詞
  audioFiles: {
    word: string;              // 詞彙發音音檔URL
    example: string;           // Example句子音檔URL
  };
  imageUrl?: string;           // Example句子配圖URL
  userProgress?: {
    masteryLevel: number;
    lastStudied: string;
    studyCount: number;
    completed: boolean;        // 是否已完成瀏覽
  };
}
```

### 獲取對話列表
```http
GET /dialogues
Authorization: Bearer <access_token>
Query Parameters:
- difficulty: number (optional)
- scenario: string (optional)
- completed: boolean (optional)
```

### 獲取對話詳情
```http
GET /dialogues/{dialogueId}
Authorization: Bearer <access_token>
```

### 搜索學習內容
```http
GET /content/search
Authorization: Bearer <access_token>
Query Parameters:
- query: string (required) - 搜索關鍵詞
- type: string (optional) - vocabulary|dialogue|all
- language: string (required)
```

## 🎯 學習活動API

### 開始學習會話
```http
POST /learning/sessions
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "type": "vocabulary" | "dialogue" | "review",
  "contentId": "content_uuid",
  "stageId": "stage_uuid",     // 關卡ID (適用於詞彙學習)
  "settings": {
    "difficulty": number,
    "timeLimit": number,
    "hints": boolean,
    "autoPlay": boolean        // 自動播放音檔設定
  }
}
```

**回應**:
```typescript
interface SessionResponse {
  sessionId: string;
  content: LearningContent;
  vocabularyList?: VocabularyDetail[]; // 詞彙學習專用
  questions: Question[];               // 對話學習專用
  timeLimit: number;
  lifePointsCost: number;
  totalItems: number;                  // 總項目數
  currentIndex: number;                // 當前項目索引
}
```

### 記錄詞彙瀏覽進度
```http
POST /learning/vocabulary/{vocabularyId}/viewed
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "sessionId": "session_uuid",
  "timeSpent": number,           // 瀏覽時間(秒)
  "audioPlayed": {
    "word": boolean,             // 是否播放詞彙音檔
    "example": boolean           // 是否播放例句音檔
  }
}
```

**回應**:
```typescript
interface VocabularyViewResponse {
  viewed: boolean;
  progress: {
    current: number;             // 當前進度
    total: number;               // 總項目數
    percentage: number;          // 完成百分比
  };
  nextVocabularyId?: string;     // 下一個詞彙ID
  stageCompleted: boolean;       // 是否完成關卡
}
```

### 提交答案 (對話學習專用)
```http
POST /learning/sessions/{sessionId}/answers
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "questionId": "question_uuid",
  "answer": any,
  "responseTime": number,
  "hintsUsed": number
}
```

**回應**:
```typescript
interface AnswerResponse {
  correct: boolean;
  correctAnswer?: any;
  explanation?: string;
  scoreGained: number;
  lifePointsLost: number;
  nextQuestion?: Question;
}
```

### 完成學習會話
```http
POST /learning/sessions/{sessionId}/complete
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "completedItems": string[],    // 已完成的詞彙ID列表
  "totalTimeSpent": number,      // 總學習時間(秒)
  "sessionType": "vocabulary" | "dialogue" | "review"
}
```

**回應**:
```typescript
interface SessionCompleteResponse {
  finalScore: number;
  accuracy: number;
  xpGained: number;
  diamondsGained: number;
  starsEarned: number;               // 獲得星星數 (詞彙學習固定3星)
  vocabulariesMastered: number;      // 掌握的詞彙數量
  achievementsUnlocked: Achievement[];
  nextRecommendations: Recommendation[];
  stageCompleted: boolean;           // 是否完成關卡
  nextStageId?: string;              // 下一關卡ID
}
```

### 獲取複習內容
```http
GET /learning/review
Authorization: Bearer <access_token>
Query Parameters:
- type: string (optional) - vocabulary|dialogue|all
- limit: number (optional)
```

## 🏆 遊戲化系統API

### 獲取成就列表
```http
GET /achievements
Authorization: Bearer <access_token>
Query Parameters:
- category: string (optional)
- completed: boolean (optional)
```

### 獲取用戶道具
```http
GET /inventory
Authorization: Bearer <access_token>
```

### 使用道具
```http
POST /inventory/use
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "itemId": "item_uuid",
  "quantity": number,
  "context": {
    "sessionId": "session_uuid"
  }
}
```

### 購買道具
```http
POST /store/purchase
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "itemId": "item_uuid",
  "quantity": number,
  "paymentMethod": "diamonds" | "learning_coins" | "real_money"
}
```

### 獲取排行榜
```http
GET /leaderboard
Authorization: Bearer <access_token>
Query Parameters:
- type: string - xp|vocabulary|dialogue|streak
- timeframe: string - day|week|month|all
- limit: number (optional)
```

### 使用時光卷
```http
POST /items/time-warp/use
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "itemId": "time_warp_scroll_uuid",
  "preferredStages": string[]     // 用戶偏好的階段ID (可選)
}
```

**回應**:
```typescript
interface TimeWarpChallengeResponse {
  challengeId: string;
  selectedScript: {
    scriptId: string;
    scriptName: string;
    stageId: string;
    stageName: string;
    isFromPreviousStage: boolean;
  };
  challenge: {
    type: "dialogue";            // 目前固定為對話訓練
    timeLimit: number;           // 挑戰時間限制(秒)
    specialRewards: {
      bonus_xp: number;
      bonus_diamonds: number;
      vocabulary_review: boolean; // 詞彙加入複習清單
    };
  };
  sessionData: any;              // 關卡具體數據
}
```

## 📺 廣告系統API

### 請求觀看廣告
```http
POST /ads/request
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "adType": "life_points_restore" | "bonus_rewards" | "unlock_content",
  "context": {
    "currentLifePoints": number,
    "maxLifePoints": number,
    "sessionId"?: string,
    "itemType"?: string         // 額外獎勵的道具類型
  }
}
```

**回應**:
```typescript
interface AdRequestResponse {
  adAvailable: boolean;
  adId?: string;
  adProvider: "google_admob" | "unity_ads" | "facebook_ads";
  estimatedDuration: number;    // 預估廣告時長(秒)
  rewards: {
    lifePoints?: number;        // 恢復的命條數量
    diamonds?: number;          // 獲得鑽石
    xp?: number;               // 額外經驗值
    items?: string[];          // 獲得道具ID列表
  };
  cooldownTime?: number;        // 下次可觀看時間(秒)
  dailyLimit: {
    watched: number;
    maximum: number;
  };
}
```

### 完成廣告觀看
```http
POST /ads/complete
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "adId": string,
  "adProvider": string,
  "watchDuration": number,      // 實際觀看時長(秒)
  "completed": boolean,         // 是否完整觀看
  "rewardClaimed": boolean      // 是否領取獎勵
}
```

**回應**:
```typescript
interface AdCompleteResponse {
  success: boolean;
  rewardsGranted: {
    lifePoints?: number;
    diamonds?: number;
    xp?: number;
    items?: Array<{
      itemId: string;
      quantity: number;
      name: string;
    }>;
  };
  updatedUserStats: {
    currentLifePoints: number;
    totalDiamonds: number;
    totalXP: number;
  };
  nextAdAvailableAt?: string;   // ISO timestamp
}
```

### 獲取廣告狀態
```http
GET /ads/status
Authorization: Bearer <access_token>
Query Parameters:
- adType: string (optional)
```

**回應**:
```typescript
interface AdStatusResponse {
  dailyStats: {
    adsWatched: number;
    maxAdsPerDay: number;
    resetTime: string;          // ISO timestamp
  };
  availableAdTypes: Array<{
    type: string;
    available: boolean;
    cooldownEndsAt?: string;    // ISO timestamp
    estimatedReward: any;
  }>;
  userPreferences: {
    adsEnabled: boolean;
    preferredProviders: string[];
  };
}
```

## 📊 分析與報告API

### 獲取學習分析
```http
GET /analytics/learning
Authorization: Bearer <access_token>
Query Parameters:
- startDate: string (YYYY-MM-DD)
- endDate: string (YYYY-MM-DD)
- granularity: string - day|week|month
```

**回應**:
```typescript
interface LearningAnalytics {
  timeRange: {
    start: string;
    end: string;
  };
  summary: {
    totalStudyTime: number;
    wordsLearned: number;
    dialoguesCompleted: number;
    overallAccuracy: number;
    streakDays: number;
  };
  skillBreakdown: SkillAnalytics[];
  progressTrend: DataPoint[];
  weakAreas: WeakArea[];
  recommendations: string[];
}
```

### 導出學習數據
```http
GET /analytics/export
Authorization: Bearer <access_token>
Query Parameters:
- format: string - json|csv|pdf
- startDate: string
- endDate: string
- includePersonal: boolean
```

## 🗣️ 口說評分系統API

### 提交語音進行評分
```http
POST /speaking/evaluate
Authorization: Bearer <access_token>
Content-Type: multipart/form-data

{
  "audioFile": File,              // 語音文件 (wav/mp3)
  "sessionId": "session_uuid",    // 學習會話ID
  "contentType": "vocabulary" | "dialogue" | "pronunciation",
  "targetText": string,           // 預期文本內容
  "language": "en" | "zh-TW",
  "evaluationType": "five_dimension" | "basic"
}
```

**回應**:
```typescript
interface SpeakingEvaluation {
  sessionId: string;
  overallScore: number;           // 0-100 總分
  dimensions: {
    pronunciation: number;        // 發音評分
    completeness: number;        // 完整度評分
    fluency: number;            // 流暢度評分
    prosody: number;            // 韻律評分
    accuracy: number;           // 準確度評分
  };
  detailedFeedback: {
    problemWords: Array<{
      word: string;
      issues: string[];          // 發音問題描述
      phonemes: string[];        // 問題音素
    }>;
    suggestions: string[];       // 改善建議
    strengths: string[];         // 優點反饋
  };
  rewards?: {
    diamonds: number;
    xp: number;
    items?: string[];           // 獲得道具 (如時光卷)
  };
}
```

### 獲取口說評分歷史
```http
GET /speaking/history
Authorization: Bearer <access_token>
Query Parameters:
- contentType: string (optional)
- limit: number (optional)
- offset: number (optional)
```

## 🎭 語用分析系統API

### 對話語用分析
```http
POST /dialogue/pragmatic-analysis
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "sessionId": "session_uuid",
  "userMessage": string,
  "dialogueContext": {
    "scenario": string,
    "previousTurns": Array<{
      "speaker": "user" | "ai",
      "message": string,
      "timestamp": string
    }>,
    "intents": string[]          // 預期完成的意圖任務
  }
}
```

**回應**:
```typescript
interface PragmaticAnalysis {
  sessionId: string;
  analysisId: string;
  dimensions: {
    smallTalk: {
      present: boolean;
      examples?: string[];
      suggestions?: string[];
    };
    indirectness: {
      level: "direct" | "moderately_indirect" | "highly_indirect";
      examples?: string[];
      culturalNotes?: string[];
    };
    fillers: {
      count: number;
      types: string[];
      appropriateness: "natural" | "excessive" | "insufficient";
    };
    backchanneling: {
      present: boolean;
      effectiveness: "good" | "adequate" | "needs_improvement";
      examples?: string[];
    };
    hedging: {
      level: "confident" | "appropriately_cautious" | "overly_cautious";
      examples?: string[];
    };
    idioms: {
      used: Array<{
        idiom: string;
        appropriateness: "perfect" | "good" | "awkward";
        culturalFit: boolean;
      }>;
      suggestions?: string[];
    };
  };
  overallAssessment: {
    communicativeEffectiveness: "excellent" | "good" | "adequate" | "needs_work";
    culturalApproppriateness: "excellent" | "good" | "adequate" | "needs_work";
    suggestions: string[];
    strengths: string[];
  };
  intentCompletion: {
    completedIntents: string[];
    partialIntents: string[];
    missedIntents: string[];
    completionRate: number;     // 0-100
  };
}
```

### 獲取語用分析建議
```http
GET /dialogue/pragmatic-suggestions
Authorization: Bearer <access_token>
Query Parameters:
- scenario: string
- userLevel: string (optional) - beginner|intermediate|advanced
```

## 🔄 實時功能API

### WebSocket連接 (適用於Web端)
```
WSS /ws/learning
Authorization: Bearer <access_token>
```

**支援事件**:
- `session_start` - 學習會話開始
- `question_answered` - 回答題目
- `achievement_unlocked` - 解鎖成就
- `life_point_restored` - 命條恢復
- `friend_activity` - 好友活動通知

### 推送通知API (適用於Mobile端)
```http
POST /notifications/register
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "deviceToken": "fcm_device_token",
  "platform": "ios" | "android",
  "preferences": {
    "studyReminders": boolean,
    "achievements": boolean,
    "friends": boolean
  }
}
```

## 🌐 多語言支援API

### 獲取語言包
```http
GET /localization/{languageCode}
Query Parameters:
- version: string (optional) - 語言包版本號
```

### 獲取支援語言列表
```http
GET /localization/languages
```

## 🛡️ 資料保護API

### 請求數據導出
```http
POST /privacy/export-request
Authorization: Bearer <access_token>
```

### 請求帳戶刪除
```http
POST /privacy/delete-request
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "reason": string,
  "confirmPassword": string
}
```

### 更新隱私設定
```http
PUT /privacy/settings
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "dataCollection": boolean,
  "analytics": boolean,
  "marketing": boolean,
  "thirdPartySharing": boolean
}
```

## 📈 API限流規則

### 頻率限制
| 端點類別 | 限制 | 時間窗口 |
|---------|------|----------|
| 認證相關 | 5次 | 每分鐘 |
| 學習內容 | 100次 | 每分鐘 |
| 學習活動 | 50次 | 每分鐘 |
| 分析報告 | 10次 | 每分鐘 |
| 通用查詢 | 200次 | 每分鐘 |

### 限流回應
```http
HTTP/1.1 429 Too Many Requests
Retry-After: 60

{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Request rate limit exceeded"
  }
}
```

## 🔍 錯誤碼參考

### 認證錯誤 (4xx)
- `INVALID_CREDENTIALS` (401) - 登入憑證錯誤
- `TOKEN_EXPIRED` (401) - Token已過期
- `TOKEN_INVALID` (401) - Token格式錯誤
- `INSUFFICIENT_PERMISSIONS` (403) - 權限不足

### 業務邏輯錯誤 (4xx)
- `INSUFFICIENT_LIFE_POINTS` (402) - 命條不足
- `CONTENT_NOT_FOUND` (404) - 學習內容不存在
- `SESSION_EXPIRED` (410) - 學習會話已過期
- `INVALID_ANSWER_FORMAT` (422) - 答案格式錯誤

### 系統錯誤 (5xx)
- `INTERNAL_SERVER_ERROR` (500) - 內部伺服器錯誤
- `DATABASE_ERROR` (503) - 資料庫連接錯誤
- `THIRD_PARTY_SERVICE_ERROR` (503) - 第三方服務錯誤

## 📋 API測試

### 測試端點
```
開發環境: https://dev-api.dramaling.com/api/v1
測試環境: https://test-api.dramaling.com/api/v1  
生產環境: https://api.dramaling.com/api/v1
```

### 測試帳號
```
測試用戶: test@dramaling.com
測試密碼: TestUser123456
測試Token: 開發環境提供長效測試Token
```

### Postman Collection
- 完整API集合下載: `/docs/api/postman-collection.json`
- 環境變數設定: `/docs/api/postman-environment.json`

---

**文檔狀態**: 🟢 已完成  
**最後更新**: 2025-09-12  
**版本**: v2.0 - 新增口說評分、語用分析、階段系統、廣告系統API
**相關文檔**: 
- `business-rules.md` - 業務邏輯規則
- `data-models.md` - 數據結構定義
- `progressive-stage-system.md` - 線性闖關學習系統
- `speaking-evaluation-specs.md` - 口說評分系統規格
- `pragmatic-analysis-specs.md` - 語用分析系統規格
- `../mobile/` - 移動端功能規格
- `../web/` - Web端功能規格
- `/swagger-ui.html` - 互動式API文檔