dramaling-app/apps/web-native/data/mockData.js

520 lines
15 KiB
JavaScript
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.

/**
* Drama Ling - 模擬數據
* 開發和測試用的模擬數據集
*/
/**
* 模擬用戶數據
*/
export const mockUsers = [
{
id: 'user_001',
email: 'demo@dramaling.com',
name: '張小明',
avatar: '/assets/media/images/avatar-1.png',
level: '中級',
joinDate: '2024-01-15',
preferences: {
language: 'zh-TW',
theme: 'auto',
soundEnabled: true,
notificationsEnabled: true
}
},
{
id: 'user_002',
email: 'sarah@example.com',
name: 'Sarah Chen',
avatar: '/assets/media/images/avatar-2.png',
level: '高級',
joinDate: '2023-11-20',
preferences: {
language: 'zh-TW',
theme: 'light',
soundEnabled: false,
notificationsEnabled: true
}
}
];
/**
* 模擬用戶統計數據
*/
export const mockUserStats = {
totalWords: 1247,
studyTime: 45, // 小時
achievements: 12,
streak: 7, // 連續學習天數
diamonds: 2580,
weeklyGoal: 5, // 每週學習時數目標
weeklyProgress: 3.5, // 本週已完成時數
levelProgress: 78, // 等級進度百分比
accuracy: 85, // 整體答題準確率
strongCategories: ['商務', '旅遊', '日常對話'],
weakCategories: ['科技', '醫療']
};
/**
* 模擬詞彙數據
*/
export const mockVocabulary = [
{
id: 'vocab_001',
word: 'appreciate',
definition: '感激;欣賞;理解',
pronunciation: '/əˈpriːʃieɪt/',
difficulty: 'intermediate',
category: 'business',
examples: [
{
english: 'I appreciate your hard work.',
chinese: '我很感激你的辛勤工作。'
},
{
english: 'Do you appreciate classical music?',
chinese: '你欣賞古典音樂嗎?'
}
],
audioUrl: '/assets/media/audio/appreciate.mp3',
imageUrl: '/assets/media/images/appreciate.jpg',
tags: ['emotion', 'business', 'common'],
addedDate: '2024-09-01',
masteryLevel: 0.8, // 0-1掌握程度
reviewCount: 5,
correctCount: 4,
lastReviewed: '2024-09-09'
},
{
id: 'vocab_002',
word: 'definitely',
definition: '當然;肯定地',
pronunciation: '/ˈdefɪnətli/',
difficulty: 'beginner',
category: 'daily',
examples: [
{
english: 'I will definitely come to your party.',
chinese: '我一定會參加你的派對。'
},
{
english: 'That was definitely the best movie I\'ve seen.',
chinese: '那絕對是我看過最好的電影。'
}
],
audioUrl: '/assets/media/audio/definitely.mp3',
imageUrl: '/assets/media/images/definitely.jpg',
tags: ['adverb', 'confirmation', 'common'],
addedDate: '2024-08-28',
masteryLevel: 0.95,
reviewCount: 8,
correctCount: 8,
lastReviewed: '2024-09-08'
},
{
id: 'vocab_003',
word: 'entrepreneur',
definition: '企業家;創業者',
pronunciation: '/ˌɒntrəprəˈː(r)/',
difficulty: 'advanced',
category: 'business',
examples: [
{
english: 'She is a successful entrepreneur.',
chinese: '她是一位成功的企業家。'
},
{
english: 'Many entrepreneurs start with small businesses.',
chinese: '許多企業家都是從小企業開始的。'
}
],
audioUrl: '/assets/media/audio/entrepreneur.mp3',
imageUrl: '/assets/media/images/entrepreneur.jpg',
tags: ['business', 'career', 'advanced'],
addedDate: '2024-09-05',
masteryLevel: 0.4,
reviewCount: 2,
correctCount: 1,
lastReviewed: '2024-09-07'
}
];
/**
* 模擬對話場景數據
*/
export const mockDialogues = [
{
id: 'dialogue_001',
title: '餐廳點餐',
category: 'restaurant',
difficulty: 'beginner',
description: '在餐廳與服務生的基本對話練習',
estimatedTime: 5, // 分鐘
thumbnail: '/assets/media/images/restaurant-scene.jpg',
characters: [
{
id: 'customer',
name: '顧客',
avatar: '/assets/media/images/customer-avatar.png'
},
{
id: 'waiter',
name: '服務生',
avatar: '/assets/media/images/waiter-avatar.png',
isAI: true
}
],
conversation: [
{
speaker: 'waiter',
text: 'Good evening! Welcome to our restaurant. How many people?',
chinese: '晚安!歡迎來到我們餐廳。請問幾位?',
audioUrl: '/assets/media/audio/dialogue_001_01.mp3'
},
{
speaker: 'customer',
text: 'Table for two, please.',
chinese: '請給我們兩人桌。',
audioUrl: '/assets/media/audio/dialogue_001_02.mp3',
isUserResponse: true,
alternatives: [
'Two people, please.',
'A table for two.',
'Party of two.'
]
},
{
speaker: 'waiter',
text: 'Perfect! Right this way, please. Here are your menus.',
chinese: '很好!請這邊走。這是菜單。',
audioUrl: '/assets/media/audio/dialogue_001_03.mp3'
}
],
completedBy: 1250, // 完成人數
rating: 4.8,
tags: ['restaurant', 'basic', 'ordering']
},
{
id: 'dialogue_002',
title: '機場報到',
category: 'travel',
difficulty: 'intermediate',
description: '在機場辦理登機手續的對話',
estimatedTime: 8,
thumbnail: '/assets/media/images/airport-scene.jpg',
characters: [
{
id: 'passenger',
name: '乘客',
avatar: '/assets/media/images/passenger-avatar.png'
},
{
id: 'checkin_agent',
name: '報到人員',
avatar: '/assets/media/images/agent-avatar.png',
isAI: true
}
],
conversation: [
{
speaker: 'checkin_agent',
text: 'Good morning! May I have your passport and ticket, please?',
chinese: '早安!請出示您的護照和機票。',
audioUrl: '/assets/media/audio/dialogue_002_01.mp3'
},
{
speaker: 'passenger',
text: 'Here you go.',
chinese: '給您。',
audioUrl: '/assets/media/audio/dialogue_002_02.mp3',
isUserResponse: true,
alternatives: [
'Here they are.',
'Sure, here you are.',
'Of course.'
]
}
],
completedBy: 890,
rating: 4.6,
tags: ['travel', 'airport', 'procedures']
}
];
/**
* 模擬學習進度數據
*/
export const mockLearningProgress = {
dailyStats: [
{ date: '2024-09-03', wordsLearned: 15, timeSpent: 25, accuracy: 82 },
{ date: '2024-09-04', wordsLearned: 12, timeSpent: 30, accuracy: 88 },
{ date: '2024-09-05', wordsLearned: 18, timeSpent: 35, accuracy: 75 },
{ date: '2024-09-06', wordsLearned: 20, timeSpent: 40, accuracy: 90 },
{ date: '2024-09-07', wordsLearned: 16, timeSpent: 28, accuracy: 85 },
{ date: '2024-09-08', wordsLearned: 14, timeSpent: 32, accuracy: 87 },
{ date: '2024-09-09', wordsLearned: 22, timeSpent: 45, accuracy: 92 }
],
weeklyGoals: {
wordsTarget: 100,
timeTarget: 5 * 60, // 5小時以分鐘為單位
currentWords: 117,
currentTime: 235 // 分鐘
},
categoryProgress: {
business: { total: 150, mastered: 120, learning: 25, difficult: 5 },
daily: { total: 200, mastered: 180, learning: 15, difficult: 5 },
travel: { total: 80, mastered: 60, learning: 15, difficult: 5 },
technology: { total: 100, mastered: 45, learning: 30, difficult: 25 }
},
achievements: [
{
id: 'first_week',
title: '初次體驗',
description: '完成第一週學習',
icon: '🎯',
unlockedDate: '2024-01-22',
rarity: 'common'
},
{
id: 'streak_7',
title: '七日連勝',
description: '連續學習7天',
icon: '🔥',
unlockedDate: '2024-02-01',
rarity: 'rare'
},
{
id: 'words_1000',
title: '詞彙大師',
description: '學習1000個詞彙',
icon: '📚',
unlockedDate: '2024-08-15',
rarity: 'epic'
}
]
};
/**
* 模擬系統設定數據
*/
export const mockSystemSettings = {
themes: [
{ id: 'auto', name: '自動', description: '跟隨系統設定' },
{ id: 'light', name: '淺色', description: '淺色主題' },
{ id: 'dark', name: '深色', description: '深色主題' }
],
languages: [
{ id: 'zh-TW', name: '繁體中文', flag: '🇹🇼' },
{ id: 'zh-CN', name: '简体中文', flag: '🇨🇳' },
{ id: 'en-US', name: 'English', flag: '🇺🇸' },
{ id: 'ja-JP', name: '日本語', flag: '🇯🇵' }
],
notificationTypes: [
{ id: 'daily_reminder', name: '每日提醒', description: '提醒您每天學習' },
{ id: 'streak_warning', name: '連勝警告', description: '連勝即將中斷時提醒' },
{ id: 'achievement', name: '成就通知', description: '獲得新成就時通知' },
{ id: 'weekly_report', name: '週報', description: '每週學習報告' }
]
};
/**
* 模擬 API 響應數據
*/
export const mockApiResponses = {
login: {
success: {
token: 'mock_jwt_token_12345',
user: mockUsers[0],
expiresIn: 86400 // 24小時
},
error: {
message: '帳號或密碼錯誤',
code: 'INVALID_CREDENTIALS'
}
},
getUserStats: {
success: mockUserStats,
error: {
message: '無法載入用戶統計',
code: 'STATS_LOAD_ERROR'
}
},
getVocabulary: {
success: {
data: mockVocabulary,
total: mockVocabulary.length,
page: 1,
limit: 20
},
error: {
message: '無法載入詞彙數據',
code: 'VOCABULARY_LOAD_ERROR'
}
},
getDialogues: {
success: {
data: mockDialogues,
total: mockDialogues.length,
page: 1,
limit: 10
},
error: {
message: '無法載入對話數據',
code: 'DIALOGUE_LOAD_ERROR'
}
}
};
/**
* 模擬 API 客戶端
* 用於開發環境的 API 模擬
*/
export class MockApiClient {
constructor() {
this.delay = 300; // 模擬網路延遲
this.failureRate = 0.1; // 10% 機率失敗
}
/**
* 模擬 API 延遲
*/
async simulateDelay() {
return new Promise(resolve => {
setTimeout(resolve, this.delay);
});
}
/**
* 模擬隨機失敗
*/
simulateRandomFailure() {
return Math.random() < this.failureRate;
}
/**
* 用戶登入
*/
async login(email, password) {
await this.simulateDelay();
if (this.simulateRandomFailure()) {
throw new Error(mockApiResponses.login.error.message);
}
// 簡單的驗證邏輯
if (email === 'demo@dramaling.com' && password === 'password') {
return mockApiResponses.login.success;
} else {
throw new Error(mockApiResponses.login.error.message);
}
}
/**
* 獲取用戶統計
*/
async getUserStats() {
await this.simulateDelay();
if (this.simulateRandomFailure()) {
throw new Error(mockApiResponses.getUserStats.error.message);
}
return mockApiResponses.getUserStats.success;
}
/**
* 獲取詞彙列表
*/
async getVocabulary(params = {}) {
await this.simulateDelay();
if (this.simulateRandomFailure()) {
throw new Error(mockApiResponses.getVocabulary.error.message);
}
let filteredVocabulary = [...mockVocabulary];
// 模擬過濾和排序
if (params.category) {
filteredVocabulary = filteredVocabulary.filter(
vocab => vocab.category === params.category
);
}
if (params.difficulty) {
filteredVocabulary = filteredVocabulary.filter(
vocab => vocab.difficulty === params.difficulty
);
}
return {
data: filteredVocabulary,
total: filteredVocabulary.length,
page: params.page || 1,
limit: params.limit || 20
};
}
/**
* 獲取對話場景
*/
async getDialogues(params = {}) {
await this.simulateDelay();
if (this.simulateRandomFailure()) {
throw new Error(mockApiResponses.getDialogues.error.message);
}
let filteredDialogues = [...mockDialogues];
if (params.category) {
filteredDialogues = filteredDialogues.filter(
dialogue => dialogue.category === params.category
);
}
if (params.difficulty) {
filteredDialogues = filteredDialogues.filter(
dialogue => dialogue.difficulty === params.difficulty
);
}
return {
data: filteredDialogues,
total: filteredDialogues.length,
page: params.page || 1,
limit: params.limit || 10
};
}
/**
* 獲取學習進度
*/
async getLearningProgress() {
await this.simulateDelay();
if (this.simulateRandomFailure()) {
throw new Error('無法載入學習進度');
}
return mockLearningProgress;
}
/**
* 獲取當前用戶
*/
async getCurrentUser() {
await this.simulateDelay();
if (this.simulateRandomFailure()) {
throw new Error('無法載入用戶資料');
}
return mockUsers[0];
}
}
// 導出模擬 API 客戶端實例
export const mockApi = new MockApiClient();