init
This commit is contained in:
@@ -0,0 +1,468 @@
|
||||
import '../models/test_models.dart';
|
||||
import '../data/test_static_data.dart';
|
||||
import '../../../core/models/api_response.dart';
|
||||
|
||||
/// 综合测试服务类
|
||||
class TestService {
|
||||
// 单例模式
|
||||
static final TestService _instance = TestService._internal();
|
||||
factory TestService() => _instance;
|
||||
TestService._internal();
|
||||
|
||||
/// 获取所有测试模板
|
||||
Future<ApiResponse<List<TestTemplate>>> getTestTemplates() async {
|
||||
try {
|
||||
// 模拟网络延迟
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
final templates = TestStaticData.getAllTemplates();
|
||||
return ApiResponse.success(
|
||||
data: templates,
|
||||
message: '获取测试模板成功',
|
||||
);
|
||||
} catch (e) {
|
||||
return ApiResponse.error(
|
||||
message: '获取测试模板失败: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 根据类型获取测试模板
|
||||
Future<ApiResponse<List<TestTemplate>>> getTestTemplatesByType(
|
||||
TestType type,
|
||||
) async {
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
|
||||
final templates = TestStaticData.getTemplatesByType(type);
|
||||
return ApiResponse.success(
|
||||
data: templates,
|
||||
message: '获取${_getTestTypeName(type)}模板成功',
|
||||
);
|
||||
} catch (e) {
|
||||
return ApiResponse.error(
|
||||
message: '获取测试模板失败: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 根据ID获取测试模板
|
||||
Future<ApiResponse<TestTemplate>> getTestTemplateById(String id) async {
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
|
||||
final template = TestStaticData.getTemplateById(id);
|
||||
if (template == null) {
|
||||
return ApiResponse.error(message: '测试模板不存在');
|
||||
}
|
||||
|
||||
return ApiResponse.success(
|
||||
data: template,
|
||||
message: '获取测试模板成功',
|
||||
);
|
||||
} catch (e) {
|
||||
return ApiResponse.error(
|
||||
message: '获取测试模板失败: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 创建测试会话
|
||||
Future<ApiResponse<TestSession>> createTestSession({
|
||||
required String templateId,
|
||||
required String userId,
|
||||
}) async {
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 800));
|
||||
|
||||
final session = TestStaticData.createTestSession(
|
||||
templateId: templateId,
|
||||
userId: userId,
|
||||
);
|
||||
|
||||
return ApiResponse.success(
|
||||
data: session,
|
||||
message: '创建测试会话成功',
|
||||
);
|
||||
} catch (e) {
|
||||
return ApiResponse.error(
|
||||
message: '创建测试会话失败: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 开始测试
|
||||
Future<ApiResponse<TestSession>> startTest(String sessionId) async {
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
|
||||
// 模拟开始测试,实际应用中会更新数据库中的会话状态
|
||||
// 这里返回一个模拟的已开始的会话
|
||||
return ApiResponse.success(
|
||||
data: TestSession(
|
||||
id: sessionId,
|
||||
templateId: 'template_quick',
|
||||
userId: 'user_001',
|
||||
status: TestStatus.inProgress,
|
||||
questions: TestStaticData.getQuestionsByIds(['vocab_001', 'grammar_001']),
|
||||
answers: [],
|
||||
currentQuestionIndex: 0,
|
||||
startTime: DateTime.now(),
|
||||
timeRemaining: 900, // 15分钟
|
||||
),
|
||||
message: '测试已开始',
|
||||
);
|
||||
} catch (e) {
|
||||
return ApiResponse.error(
|
||||
message: '开始测试失败: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 提交答案
|
||||
Future<ApiResponse<TestSession>> submitAnswer({
|
||||
required String sessionId,
|
||||
required UserAnswer answer,
|
||||
}) async {
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 400));
|
||||
|
||||
// 模拟提交答案并返回更新后的会话
|
||||
return ApiResponse.success(
|
||||
data: TestSession(
|
||||
id: sessionId,
|
||||
templateId: 'template_quick',
|
||||
userId: 'user_001',
|
||||
status: TestStatus.inProgress,
|
||||
questions: TestStaticData.getQuestionsByIds(['vocab_001', 'grammar_001']),
|
||||
answers: [answer],
|
||||
currentQuestionIndex: 1,
|
||||
startTime: DateTime.now().subtract(const Duration(minutes: 5)),
|
||||
timeRemaining: 600, // 剩余10分钟
|
||||
),
|
||||
message: '答案提交成功',
|
||||
);
|
||||
} catch (e) {
|
||||
return ApiResponse.error(
|
||||
message: '提交答案失败: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 暂停测试
|
||||
Future<ApiResponse<TestSession>> pauseTest(String sessionId) async {
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
|
||||
return ApiResponse.success(
|
||||
data: TestSession(
|
||||
id: sessionId,
|
||||
templateId: 'template_quick',
|
||||
userId: 'user_001',
|
||||
status: TestStatus.paused,
|
||||
questions: TestStaticData.getQuestionsByIds(['vocab_001', 'grammar_001']),
|
||||
answers: [],
|
||||
currentQuestionIndex: 0,
|
||||
startTime: DateTime.now().subtract(const Duration(minutes: 5)),
|
||||
timeRemaining: 600,
|
||||
),
|
||||
message: '测试已暂停',
|
||||
);
|
||||
} catch (e) {
|
||||
return ApiResponse.error(
|
||||
message: '暂停测试失败: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 恢复测试
|
||||
Future<ApiResponse<TestSession>> resumeTest(String sessionId) async {
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
|
||||
return ApiResponse.success(
|
||||
data: TestSession(
|
||||
id: sessionId,
|
||||
templateId: 'template_quick',
|
||||
userId: 'user_001',
|
||||
status: TestStatus.inProgress,
|
||||
questions: TestStaticData.getQuestionsByIds(['vocab_001', 'grammar_001']),
|
||||
answers: [],
|
||||
currentQuestionIndex: 0,
|
||||
startTime: DateTime.now().subtract(const Duration(minutes: 5)),
|
||||
timeRemaining: 600,
|
||||
),
|
||||
message: '测试已恢复',
|
||||
);
|
||||
} catch (e) {
|
||||
return ApiResponse.error(
|
||||
message: '恢复测试失败: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 完成测试
|
||||
Future<ApiResponse<TestResult>> completeTest({
|
||||
required String sessionId,
|
||||
required List<UserAnswer> answers,
|
||||
}) async {
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 1000));
|
||||
|
||||
// 模拟计算测试结果
|
||||
final result = _calculateTestResult(sessionId, answers);
|
||||
|
||||
// 保存结果到静态数据
|
||||
TestStaticData.addTestResult(result);
|
||||
|
||||
return ApiResponse.success(
|
||||
data: result,
|
||||
message: '测试完成,结果已保存',
|
||||
);
|
||||
} catch (e) {
|
||||
return ApiResponse.error(
|
||||
message: '完成测试失败: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取用户测试历史
|
||||
Future<ApiResponse<List<TestResult>>> getUserTestHistory(
|
||||
String userId, {
|
||||
int page = 1,
|
||||
int limit = 10,
|
||||
}) async {
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 600));
|
||||
|
||||
final allResults = TestStaticData.getUserResults(userId);
|
||||
final startIndex = (page - 1) * limit;
|
||||
final endIndex = startIndex + limit;
|
||||
|
||||
final results = allResults.length > startIndex
|
||||
? allResults.sublist(
|
||||
startIndex,
|
||||
endIndex > allResults.length ? allResults.length : endIndex,
|
||||
)
|
||||
: <TestResult>[];
|
||||
|
||||
return ApiResponse.success(
|
||||
data: results,
|
||||
message: '获取测试历史成功',
|
||||
);
|
||||
} catch (e) {
|
||||
return ApiResponse.error(
|
||||
message: '获取测试历史失败: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取最近的测试结果
|
||||
Future<ApiResponse<List<TestResult>>> getRecentTestResults(
|
||||
String userId, {
|
||||
int limit = 5,
|
||||
}) async {
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 400));
|
||||
|
||||
final results = TestStaticData.getRecentResults(userId, limit: limit);
|
||||
return ApiResponse.success(
|
||||
data: results,
|
||||
message: '获取最近测试结果成功',
|
||||
);
|
||||
} catch (e) {
|
||||
return ApiResponse.error(
|
||||
message: '获取最近测试结果失败: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取测试结果详情
|
||||
Future<ApiResponse<TestResult>> getTestResultById(String resultId) async {
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
|
||||
final result = TestStaticData.getResultById(resultId);
|
||||
if (result == null) {
|
||||
return ApiResponse.error(message: '测试结果不存在');
|
||||
}
|
||||
|
||||
return ApiResponse.success(
|
||||
data: result,
|
||||
message: '获取测试结果成功',
|
||||
);
|
||||
} catch (e) {
|
||||
return ApiResponse.error(
|
||||
message: '获取测试结果失败: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取用户技能统计
|
||||
Future<ApiResponse<Map<SkillType, double>>> getUserSkillStatistics(
|
||||
String userId,
|
||||
) async {
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
final statistics = TestStaticData.getSkillStatistics(userId);
|
||||
return ApiResponse.success(
|
||||
data: statistics,
|
||||
message: '获取技能统计成功',
|
||||
);
|
||||
} catch (e) {
|
||||
return ApiResponse.error(
|
||||
message: '获取技能统计失败: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取题目统计
|
||||
Future<ApiResponse<Map<String, dynamic>>> getQuestionStatistics() async {
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
|
||||
final difficultyStats = TestStaticData.getDifficultyStatistics();
|
||||
final skillStats = TestStaticData.getSkillDistributionStatistics();
|
||||
|
||||
return ApiResponse.success(
|
||||
data: {
|
||||
'difficultyDistribution': difficultyStats,
|
||||
'skillDistribution': skillStats,
|
||||
'totalQuestions': TestStaticData.getAllQuestions().length,
|
||||
},
|
||||
message: '获取题目统计成功',
|
||||
);
|
||||
} catch (e) {
|
||||
return ApiResponse.error(
|
||||
message: '获取题目统计失败: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 删除测试结果
|
||||
Future<ApiResponse<bool>> deleteTestResult(String resultId) async {
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
|
||||
final success = TestStaticData.deleteTestResult(resultId);
|
||||
if (success) {
|
||||
return ApiResponse.success(
|
||||
data: true,
|
||||
message: '删除测试结果成功',
|
||||
);
|
||||
} else {
|
||||
return ApiResponse.error(message: '测试结果不存在');
|
||||
}
|
||||
} catch (e) {
|
||||
return ApiResponse.error(
|
||||
message: '删除测试结果失败: ${e.toString()}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取测试类型名称
|
||||
String _getTestTypeName(TestType type) {
|
||||
switch (type) {
|
||||
case TestType.quick:
|
||||
return '快速测试';
|
||||
case TestType.standard:
|
||||
return '标准测试';
|
||||
case TestType.full:
|
||||
return '完整测试';
|
||||
case TestType.mock:
|
||||
return '模拟考试';
|
||||
case TestType.vocabulary:
|
||||
return '词汇专项';
|
||||
case TestType.grammar:
|
||||
return '语法专项';
|
||||
case TestType.reading:
|
||||
return '阅读专项';
|
||||
case TestType.listening:
|
||||
return '听力专项';
|
||||
case TestType.speaking:
|
||||
return '口语专项';
|
||||
case TestType.writing:
|
||||
return '写作专项';
|
||||
}
|
||||
}
|
||||
|
||||
/// 计算测试结果(模拟)
|
||||
TestResult _calculateTestResult(String sessionId, List<UserAnswer> answers) {
|
||||
// 这里是一个简化的计算逻辑,实际应用中会更复杂
|
||||
final totalQuestions = answers.length;
|
||||
final correctAnswers = (totalQuestions * 0.8).round(); // 模拟80%正确率
|
||||
final totalScore = correctAnswers;
|
||||
final maxScore = totalQuestions;
|
||||
final percentage = (totalScore / maxScore) * 100;
|
||||
|
||||
return TestResult(
|
||||
id: 'result_${DateTime.now().millisecondsSinceEpoch}',
|
||||
testId: 'template_quick',
|
||||
userId: 'user_001',
|
||||
testType: TestType.quick,
|
||||
totalScore: totalScore,
|
||||
maxScore: maxScore,
|
||||
percentage: percentage,
|
||||
overallLevel: _calculateOverallLevel(percentage),
|
||||
skillScores: _calculateSkillScores(answers),
|
||||
answers: answers,
|
||||
startTime: DateTime.now().subtract(const Duration(minutes: 15)),
|
||||
endTime: DateTime.now(),
|
||||
duration: 900,
|
||||
feedback: _generateFeedback(percentage),
|
||||
recommendations: {
|
||||
'nextLevel': 'intermediate',
|
||||
'focusAreas': ['grammar', 'vocabulary'],
|
||||
'suggestedStudyTime': 45,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 计算整体水平
|
||||
DifficultyLevel _calculateOverallLevel(double percentage) {
|
||||
if (percentage >= 90) return DifficultyLevel.advanced;
|
||||
if (percentage >= 80) return DifficultyLevel.upperIntermediate;
|
||||
if (percentage >= 70) return DifficultyLevel.intermediate;
|
||||
if (percentage >= 60) return DifficultyLevel.elementary;
|
||||
return DifficultyLevel.beginner;
|
||||
}
|
||||
|
||||
/// 计算技能得分
|
||||
List<SkillScore> _calculateSkillScores(List<UserAnswer> answers) {
|
||||
// 简化的技能得分计算
|
||||
return [
|
||||
SkillScore(
|
||||
skillType: SkillType.vocabulary,
|
||||
score: 4,
|
||||
maxScore: 5,
|
||||
percentage: 80.0,
|
||||
level: DifficultyLevel.elementary,
|
||||
feedback: '词汇掌握良好',
|
||||
),
|
||||
SkillScore(
|
||||
skillType: SkillType.grammar,
|
||||
score: 3,
|
||||
maxScore: 4,
|
||||
percentage: 75.0,
|
||||
level: DifficultyLevel.elementary,
|
||||
feedback: '语法基础扎实',
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/// 生成反馈
|
||||
String _generateFeedback(double percentage) {
|
||||
if (percentage >= 90) {
|
||||
return '优秀!您的英语水平很高,继续保持。';
|
||||
} else if (percentage >= 80) {
|
||||
return '良好!您的英语基础扎实,可以尝试更高难度的内容。';
|
||||
} else if (percentage >= 70) {
|
||||
return '不错!您的英语水平中等,建议加强薄弱环节的练习。';
|
||||
} else if (percentage >= 60) {
|
||||
return '及格!您的英语基础还需要加强,建议多练习基础知识。';
|
||||
} else {
|
||||
return '需要努力!建议从基础开始,系统性地学习英语。';
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user