338 lines
11 KiB
Dart
338 lines
11 KiB
Dart
|
|
import '../models/speaking_scenario.dart';
|
||
|
|
|
||
|
|
/// 口语练习静态数据
|
||
|
|
class SpeakingStaticData {
|
||
|
|
static final List<SpeakingTask> _tasks = [
|
||
|
|
// 日常对话场景
|
||
|
|
SpeakingTask(
|
||
|
|
id: 'daily_001',
|
||
|
|
title: '自我介绍',
|
||
|
|
description: '学习如何进行基本的自我介绍',
|
||
|
|
scenario: SpeakingScenario.dailyConversation,
|
||
|
|
difficulty: SpeakingDifficulty.beginner,
|
||
|
|
objectives: [
|
||
|
|
'能够清晰地介绍自己的姓名、年龄和职业',
|
||
|
|
'掌握基本的问候语和礼貌用语',
|
||
|
|
'学会询问他人的基本信息',
|
||
|
|
],
|
||
|
|
keyPhrases: [
|
||
|
|
'My name is...',
|
||
|
|
'I am from...',
|
||
|
|
'I work as...',
|
||
|
|
'Nice to meet you',
|
||
|
|
'How about you?',
|
||
|
|
],
|
||
|
|
backgroundInfo: '在日常生活中,自我介绍是最基本的社交技能。无论是在工作场合还是社交聚会,都需要用到这项技能。',
|
||
|
|
estimatedDuration: 10,
|
||
|
|
isRecommended: true,
|
||
|
|
createdAt: DateTime.now().subtract(const Duration(days: 30)),
|
||
|
|
updatedAt: DateTime.now().subtract(const Duration(days: 30)),
|
||
|
|
),
|
||
|
|
|
||
|
|
SpeakingTask(
|
||
|
|
id: 'daily_002',
|
||
|
|
title: '询问方向',
|
||
|
|
description: '学习如何询问和指示方向',
|
||
|
|
scenario: SpeakingScenario.dailyConversation,
|
||
|
|
difficulty: SpeakingDifficulty.elementary,
|
||
|
|
objectives: [
|
||
|
|
'能够礼貌地询问方向',
|
||
|
|
'理解和给出简单的方向指示',
|
||
|
|
'掌握常用的地点和方向词汇',
|
||
|
|
],
|
||
|
|
keyPhrases: [
|
||
|
|
'Excuse me, where is...?',
|
||
|
|
'How can I get to...?',
|
||
|
|
'Go straight',
|
||
|
|
'Turn left/right',
|
||
|
|
'It\'s on your left/right',
|
||
|
|
],
|
||
|
|
estimatedDuration: 15,
|
||
|
|
createdAt: DateTime.now().subtract(const Duration(days: 25)),
|
||
|
|
updatedAt: DateTime.now().subtract(const Duration(days: 25)),
|
||
|
|
),
|
||
|
|
|
||
|
|
// 商务会议场景
|
||
|
|
SpeakingTask(
|
||
|
|
id: 'business_001',
|
||
|
|
title: '会议开场',
|
||
|
|
description: '学习如何主持和参与会议开场',
|
||
|
|
scenario: SpeakingScenario.businessMeeting,
|
||
|
|
difficulty: SpeakingDifficulty.intermediate,
|
||
|
|
objectives: [
|
||
|
|
'能够正式地开始会议',
|
||
|
|
'介绍会议议程和参与者',
|
||
|
|
'掌握商务会议的基本礼仪',
|
||
|
|
],
|
||
|
|
keyPhrases: [
|
||
|
|
'Let\'s get started',
|
||
|
|
'Today\'s agenda includes...',
|
||
|
|
'I\'d like to introduce...',
|
||
|
|
'The purpose of this meeting is...',
|
||
|
|
'Any questions before we begin?',
|
||
|
|
],
|
||
|
|
backgroundInfo: '商务会议是职场中重要的沟通方式,掌握会议开场技巧能够提升专业形象。',
|
||
|
|
estimatedDuration: 20,
|
||
|
|
isRecommended: true,
|
||
|
|
createdAt: DateTime.now().subtract(const Duration(days: 20)),
|
||
|
|
updatedAt: DateTime.now().subtract(const Duration(days: 20)),
|
||
|
|
),
|
||
|
|
|
||
|
|
SpeakingTask(
|
||
|
|
id: 'business_002',
|
||
|
|
title: '产品介绍',
|
||
|
|
description: '学习如何向客户介绍产品',
|
||
|
|
scenario: SpeakingScenario.businessMeeting,
|
||
|
|
difficulty: SpeakingDifficulty.upperIntermediate,
|
||
|
|
objectives: [
|
||
|
|
'能够清晰地描述产品特点',
|
||
|
|
'强调产品的优势和价值',
|
||
|
|
'回答客户的疑问',
|
||
|
|
],
|
||
|
|
keyPhrases: [
|
||
|
|
'Our product features...',
|
||
|
|
'The main benefit is...',
|
||
|
|
'This will help you...',
|
||
|
|
'Compared to competitors...',
|
||
|
|
'Would you like to know more about...?',
|
||
|
|
],
|
||
|
|
estimatedDuration: 25,
|
||
|
|
createdAt: DateTime.now().subtract(const Duration(days: 18)),
|
||
|
|
updatedAt: DateTime.now().subtract(const Duration(days: 18)),
|
||
|
|
),
|
||
|
|
|
||
|
|
// 求职面试场景
|
||
|
|
SpeakingTask(
|
||
|
|
id: 'interview_001',
|
||
|
|
title: '面试自我介绍',
|
||
|
|
description: '学习面试中的专业自我介绍',
|
||
|
|
scenario: SpeakingScenario.jobInterview,
|
||
|
|
difficulty: SpeakingDifficulty.intermediate,
|
||
|
|
objectives: [
|
||
|
|
'能够简洁有力地介绍自己',
|
||
|
|
'突出相关工作经验和技能',
|
||
|
|
'展现对职位的兴趣和热情',
|
||
|
|
],
|
||
|
|
keyPhrases: [
|
||
|
|
'I have X years of experience in...',
|
||
|
|
'My background includes...',
|
||
|
|
'I\'m particularly skilled at...',
|
||
|
|
'I\'m excited about this opportunity because...',
|
||
|
|
'I believe I would be a good fit because...',
|
||
|
|
],
|
||
|
|
backgroundInfo: '面试自我介绍是求职过程中的关键环节,需要在短时间内给面试官留下深刻印象。',
|
||
|
|
estimatedDuration: 15,
|
||
|
|
isRecommended: true,
|
||
|
|
createdAt: DateTime.now().subtract(const Duration(days: 15)),
|
||
|
|
updatedAt: DateTime.now().subtract(const Duration(days: 15)),
|
||
|
|
),
|
||
|
|
|
||
|
|
// 购物场景
|
||
|
|
SpeakingTask(
|
||
|
|
id: 'shopping_001',
|
||
|
|
title: '服装购买',
|
||
|
|
description: '学习在服装店购物的对话',
|
||
|
|
scenario: SpeakingScenario.shopping,
|
||
|
|
difficulty: SpeakingDifficulty.elementary,
|
||
|
|
objectives: [
|
||
|
|
'能够询问商品信息',
|
||
|
|
'表达对尺寸和颜色的需求',
|
||
|
|
'进行价格谈判和付款',
|
||
|
|
],
|
||
|
|
keyPhrases: [
|
||
|
|
'Do you have this in size...?',
|
||
|
|
'Can I try this on?',
|
||
|
|
'How much does this cost?',
|
||
|
|
'Do you accept credit cards?',
|
||
|
|
'I\'ll take it',
|
||
|
|
],
|
||
|
|
estimatedDuration: 12,
|
||
|
|
createdAt: DateTime.now().subtract(const Duration(days: 12)),
|
||
|
|
updatedAt: DateTime.now().subtract(const Duration(days: 12)),
|
||
|
|
),
|
||
|
|
|
||
|
|
// 餐厅场景
|
||
|
|
SpeakingTask(
|
||
|
|
id: 'restaurant_001',
|
||
|
|
title: '餐厅点餐',
|
||
|
|
description: '学习在餐厅点餐的完整流程',
|
||
|
|
scenario: SpeakingScenario.restaurant,
|
||
|
|
difficulty: SpeakingDifficulty.elementary,
|
||
|
|
objectives: [
|
||
|
|
'能够预订餐桌',
|
||
|
|
'阅读菜单并点餐',
|
||
|
|
'处理特殊饮食要求',
|
||
|
|
],
|
||
|
|
keyPhrases: [
|
||
|
|
'I\'d like to make a reservation',
|
||
|
|
'Can I see the menu?',
|
||
|
|
'I\'ll have the...',
|
||
|
|
'I\'m allergic to...',
|
||
|
|
'Could I get the check, please?',
|
||
|
|
],
|
||
|
|
estimatedDuration: 18,
|
||
|
|
createdAt: DateTime.now().subtract(const Duration(days: 10)),
|
||
|
|
updatedAt: DateTime.now().subtract(const Duration(days: 10)),
|
||
|
|
),
|
||
|
|
|
||
|
|
// 旅行场景
|
||
|
|
SpeakingTask(
|
||
|
|
id: 'travel_001',
|
||
|
|
title: '机场办理登机',
|
||
|
|
description: '学习在机场办理登机手续',
|
||
|
|
scenario: SpeakingScenario.travel,
|
||
|
|
difficulty: SpeakingDifficulty.intermediate,
|
||
|
|
objectives: [
|
||
|
|
'能够办理登机手续',
|
||
|
|
'处理行李托运',
|
||
|
|
'询问航班信息',
|
||
|
|
],
|
||
|
|
keyPhrases: [
|
||
|
|
'I\'d like to check in',
|
||
|
|
'Here\'s my passport',
|
||
|
|
'I have one bag to check',
|
||
|
|
'What gate is my flight?',
|
||
|
|
'What time is boarding?',
|
||
|
|
],
|
||
|
|
backgroundInfo: '机场是国际旅行的重要场所,掌握相关英语对话能够让旅行更加顺利。',
|
||
|
|
estimatedDuration: 20,
|
||
|
|
createdAt: DateTime.now().subtract(const Duration(days: 8)),
|
||
|
|
updatedAt: DateTime.now().subtract(const Duration(days: 8)),
|
||
|
|
),
|
||
|
|
|
||
|
|
// 学术讨论场景
|
||
|
|
SpeakingTask(
|
||
|
|
id: 'academic_001',
|
||
|
|
title: '课堂讨论',
|
||
|
|
description: '学习参与学术课堂讨论',
|
||
|
|
scenario: SpeakingScenario.academic,
|
||
|
|
difficulty: SpeakingDifficulty.advanced,
|
||
|
|
objectives: [
|
||
|
|
'能够表达学术观点',
|
||
|
|
'进行逻辑性论证',
|
||
|
|
'礼貌地反驳不同观点',
|
||
|
|
],
|
||
|
|
keyPhrases: [
|
||
|
|
'In my opinion...',
|
||
|
|
'The evidence suggests...',
|
||
|
|
'I disagree because...',
|
||
|
|
'That\'s an interesting point, however...',
|
||
|
|
'Could you elaborate on...?',
|
||
|
|
],
|
||
|
|
estimatedDuration: 30,
|
||
|
|
createdAt: DateTime.now().subtract(const Duration(days: 5)),
|
||
|
|
updatedAt: DateTime.now().subtract(const Duration(days: 5)),
|
||
|
|
),
|
||
|
|
|
||
|
|
// 社交聚会场景
|
||
|
|
SpeakingTask(
|
||
|
|
id: 'social_001',
|
||
|
|
title: '聚会闲聊',
|
||
|
|
description: '学习在社交聚会中的轻松对话',
|
||
|
|
scenario: SpeakingScenario.socializing,
|
||
|
|
difficulty: SpeakingDifficulty.intermediate,
|
||
|
|
objectives: [
|
||
|
|
'能够进行轻松的闲聊',
|
||
|
|
'分享个人兴趣和经历',
|
||
|
|
'保持对话的自然流畅',
|
||
|
|
],
|
||
|
|
keyPhrases: [
|
||
|
|
'How do you know the host?',
|
||
|
|
'What do you do for fun?',
|
||
|
|
'Have you been here before?',
|
||
|
|
'That sounds interesting!',
|
||
|
|
'I should probably get going',
|
||
|
|
],
|
||
|
|
estimatedDuration: 15,
|
||
|
|
createdAt: DateTime.now().subtract(const Duration(days: 3)),
|
||
|
|
updatedAt: DateTime.now().subtract(const Duration(days: 3)),
|
||
|
|
),
|
||
|
|
|
||
|
|
// 演讲展示场景
|
||
|
|
SpeakingTask(
|
||
|
|
id: 'presentation_001',
|
||
|
|
title: '产品演示',
|
||
|
|
description: '学习进行产品演示和展示',
|
||
|
|
scenario: SpeakingScenario.presentation,
|
||
|
|
difficulty: SpeakingDifficulty.advanced,
|
||
|
|
objectives: [
|
||
|
|
'能够结构化地组织演示内容',
|
||
|
|
'使用视觉辅助工具',
|
||
|
|
'处理观众的问题和反馈',
|
||
|
|
],
|
||
|
|
keyPhrases: [
|
||
|
|
'Today I\'ll be presenting...',
|
||
|
|
'As you can see in this slide...',
|
||
|
|
'Let me demonstrate...',
|
||
|
|
'Are there any questions?',
|
||
|
|
'Thank you for your attention',
|
||
|
|
],
|
||
|
|
backgroundInfo: '产品演示是商务环境中的重要技能,需要结合专业知识和演讲技巧。',
|
||
|
|
estimatedDuration: 35,
|
||
|
|
isRecommended: true,
|
||
|
|
createdAt: DateTime.now().subtract(const Duration(days: 1)),
|
||
|
|
updatedAt: DateTime.now().subtract(const Duration(days: 1)),
|
||
|
|
),
|
||
|
|
];
|
||
|
|
|
||
|
|
/// 获取所有任务
|
||
|
|
static List<SpeakingTask> getAllTasks() {
|
||
|
|
return List.from(_tasks);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// 根据场景获取任务
|
||
|
|
static List<SpeakingTask> getTasksByScenario(SpeakingScenario scenario) {
|
||
|
|
return _tasks.where((task) => task.scenario == scenario).toList();
|
||
|
|
}
|
||
|
|
|
||
|
|
/// 根据难度获取任务
|
||
|
|
static List<SpeakingTask> getTasksByDifficulty(SpeakingDifficulty difficulty) {
|
||
|
|
return _tasks.where((task) => task.difficulty == difficulty).toList();
|
||
|
|
}
|
||
|
|
|
||
|
|
/// 获取推荐任务
|
||
|
|
static List<SpeakingTask> getRecommendedTasks() {
|
||
|
|
return _tasks.where((task) => task.isRecommended).toList();
|
||
|
|
}
|
||
|
|
|
||
|
|
/// 获取最近任务
|
||
|
|
static List<SpeakingTask> getRecentTasks() {
|
||
|
|
final sortedTasks = List<SpeakingTask>.from(_tasks);
|
||
|
|
sortedTasks.sort((a, b) => b.updatedAt.compareTo(a.updatedAt));
|
||
|
|
return sortedTasks.take(5).toList();
|
||
|
|
}
|
||
|
|
|
||
|
|
/// 获取热门任务(按完成次数排序)
|
||
|
|
static List<SpeakingTask> getPopularTasks() {
|
||
|
|
final sortedTasks = List<SpeakingTask>.from(_tasks);
|
||
|
|
sortedTasks.sort((a, b) => b.completionCount.compareTo(a.completionCount));
|
||
|
|
return sortedTasks.take(5).toList();
|
||
|
|
}
|
||
|
|
|
||
|
|
/// 根据ID获取任务
|
||
|
|
static SpeakingTask? getTaskById(String id) {
|
||
|
|
try {
|
||
|
|
return _tasks.firstWhere((task) => task.id == id);
|
||
|
|
} catch (e) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// 获取场景统计
|
||
|
|
static Map<SpeakingScenario, int> getScenarioStats() {
|
||
|
|
final stats = <SpeakingScenario, int>{};
|
||
|
|
for (final scenario in SpeakingScenario.values) {
|
||
|
|
stats[scenario] = _tasks.where((task) => task.scenario == scenario).length;
|
||
|
|
}
|
||
|
|
return stats;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// 获取难度统计
|
||
|
|
static Map<SpeakingDifficulty, int> getDifficultyStats() {
|
||
|
|
final stats = <SpeakingDifficulty, int>{};
|
||
|
|
for (final difficulty in SpeakingDifficulty.values) {
|
||
|
|
stats[difficulty] = _tasks.where((task) => task.difficulty == difficulty).length;
|
||
|
|
}
|
||
|
|
return stats;
|
||
|
|
}
|
||
|
|
}
|