Files
ai_english/client/lib/features/comprehensive_test/providers/test_provider.dart

591 lines
15 KiB
Dart
Raw Normal View History

2025-11-17 13:39:05 +08:00
import 'package:flutter/foundation.dart';
import '../models/test_models.dart';
import '../services/test_api_service.dart';
import '../../../core/models/api_response.dart';
/// 综合测试状态管理类
class TestProvider with ChangeNotifier {
final TestApiService _testService;
TestProvider({TestApiService? testService})
: _testService = testService ?? TestApiService();
// 加载状<E8BDBD>? bool _isLoading = false;
bool get isLoading => _isLoading;
// 错误信息
String? _errorMessage;
String? get errorMessage => _errorMessage;
// 测试模板
List<TestTemplate> _templates = [];
List<TestTemplate> get templates => _templates;
// 当前测试会话
TestSession? _currentSession;
TestSession? get currentSession => _currentSession;
// 当前题目
TestQuestion? get currentQuestion {
if (_currentSession == null ||
_currentSession!.currentQuestionIndex >= _currentSession!.questions.length) {
return null;
}
return _currentSession!.questions[_currentSession!.currentQuestionIndex];
}
// 测试结果
List<TestResult> _testResults = [];
List<TestResult> get testResults => _testResults;
TestResult? _currentResult;
TestResult? get currentResult => _currentResult;
// 用户技能统<E883BD>? Map<SkillType, double> _skillStatistics = {};
Map<SkillType, double> get skillStatistics => _skillStatistics;
// 题目统计
Map<String, dynamic> _questionStatistics = {};
Map<String, dynamic> get questionStatistics => _questionStatistics;
// 计时器相<E599A8>? int _timeRemaining = 0;
int get timeRemaining => _timeRemaining;
bool _isTimerRunning = false;
bool get isTimerRunning => _isTimerRunning;
/// 设置加载状<E8BDBD>? void _setLoading(bool loading) {
_isLoading = loading;
notifyListeners();
}
/// 设置错误信息
void _setError(String? error) {
_errorMessage = error;
notifyListeners();
}
/// 清除错误信息
void clearError() {
_setError(null);
}
/// 加载所有测试模<E8AF95>? Future<void> loadTestTemplates() async {
_setLoading(true);
_setError(null);
try {
final response = await _testService.getTestTemplates();
if (response.success && response.data != null) {
_templates = response.data!;
} else {
_setError(response.message);
}
} catch (e) {
_setError('加载测试模板失败: ${e.toString()}');
} finally {
_setLoading(false);
}
}
/// 根据类型加载测试模板
Future<void> loadTestTemplatesByType(TestType type) async {
_setLoading(true);
_setError(null);
try {
final response = await _testService.getTestTemplatesByType(type);
if (response.success && response.data != null) {
_templates = response.data!;
} else {
_setError(response.message);
}
} catch (e) {
_setError('加载测试模板失败: ${e.toString()}');
} finally {
_setLoading(false);
}
}
/// 创建测试会话
Future<bool> createTestSession({
required String templateId,
required String userId,
}) async {
_setLoading(true);
_setError(null);
try {
final response = await _testService.createTestSession(
templateId: templateId,
userId: userId,
);
if (response.success && response.data != null) {
_currentSession = response.data!;
_timeRemaining = _currentSession!.timeRemaining;
return true;
} else {
_setError(response.message);
return false;
}
} catch (e) {
_setError('创建测试会话失败: ${e.toString()}');
return false;
} finally {
_setLoading(false);
}
}
/// 开始测<E5A78B>? Future<bool> startTest() async {
if (_currentSession == null) {
_setError('没有活动的测试会<EFBFBD>?);
return false;
}
_setLoading(true);
_setError(null);
try {
final response = await _testService.startTest(_currentSession!.id);
if (response.success && response.data != null) {
_currentSession = response.data!;
_timeRemaining = _currentSession!.timeRemaining;
_startTimer();
return true;
} else {
_setError(response.message);
return false;
}
} catch (e) {
_setError('开始测试失<EFBFBD>? ${e.toString()}');
return false;
} finally {
_setLoading(false);
}
}
/// 提交答案
Future<bool> submitAnswer(UserAnswer answer) async {
if (_currentSession == null) {
_setError('没有活动的测试会<EFBFBD>?);
return false;
}
_setLoading(true);
_setError(null);
try {
final response = await _testService.submitAnswer(
sessionId: _currentSession!.id,
answer: answer,
);
if (response.success && response.data != null) {
_currentSession = response.data!;
_timeRemaining = _currentSession!.timeRemaining;
return true;
} else {
_setError(response.message);
return false;
}
} catch (e) {
_setError('提交答案失败: ${e.toString()}');
return false;
} finally {
_setLoading(false);
}
}
/// 下一<E4B88B>? void nextQuestion() {
if (_currentSession != null &&
_currentSession!.currentQuestionIndex < _currentSession!.questions.length - 1) {
_currentSession = _currentSession!.copyWith(
currentQuestionIndex: _currentSession!.currentQuestionIndex + 1,
);
notifyListeners();
}
}
/// 上一<E4B88A>? void previousQuestion() {
if (_currentSession != null && _currentSession!.currentQuestionIndex > 0) {
_currentSession = _currentSession!.copyWith(
currentQuestionIndex: _currentSession!.currentQuestionIndex - 1,
);
notifyListeners();
}
}
/// 跳转到指定题<E5AE9A>? void goToQuestion(int index) {
if (_currentSession != null &&
index >= 0 &&
index < _currentSession!.questions.length) {
_currentSession = _currentSession!.copyWith(
currentQuestionIndex: index,
);
notifyListeners();
}
}
/// 暂停测试
Future<bool> pauseTest() async {
if (_currentSession == null) {
_setError('没有活动的测试会<EFBFBD>?);
return false;
}
try {
final response = await _testService.pauseTest(_currentSession!.id);
if (response.success && response.data != null) {
_currentSession = response.data!;
_pauseTimer();
return true;
} else {
_setError(response.message);
return false;
}
} catch (e) {
_setError('暂停测试失败: ${e.toString()}');
return false;
}
}
/// 恢复测试
Future<bool> resumeTest() async {
if (_currentSession == null) {
_setError('没有活动的测试会<EFBFBD>?);
return false;
}
try {
final response = await _testService.resumeTest(_currentSession!.id);
if (response.success && response.data != null) {
_currentSession = response.data!;
_startTimer();
return true;
} else {
_setError(response.message);
return false;
}
} catch (e) {
_setError('恢复测试失败: ${e.toString()}');
return false;
}
}
/// 完成测试
Future<bool> completeTest() async {
if (_currentSession == null) {
_setError('没有活动的测试会话');
return false;
}
_setLoading(true);
_setError(null);
try {
final response = await _testService.completeTest(_currentSession!.id);
if (response.success && response.data != null) {
_currentResult = response.data!;
_stopTimer();
_currentSession = _currentSession!.copyWith(
status: TestStatus.completed,
endTime: DateTime.now(),
);
return true;
} else {
_setError(response.message);
return false;
}
} catch (e) {
_setError('完成测试失败: ${e.toString()}');
return false;
} finally {
_setLoading(false);
}
}
/// 加载用户测试历史
Future<void> loadUserTestHistory(String userId, {int page = 1, int limit = 10}) async {
_setLoading(true);
_setError(null);
try {
final response = await _testService.getUserTestHistory(
page: page,
limit: limit,
);
if (response.success && response.data != null) {
if (page == 1) {
_testResults = response.data!;
} else {
_testResults.addAll(response.data!);
}
} else {
_setError(response.message);
}
} catch (e) {
_setError('加载测试历史失败: ${e.toString()}');
} finally {
_setLoading(false);
}
}
/// 加载最近的测试结果
Future<void> loadRecentTestResults(String userId, {int limit = 5}) async {
_setLoading(true);
_setError(null);
try {
final response = await _testService.getRecentTestResults(
userId,
limit: limit,
);
if (response.success && response.data != null) {
_testResults = response.data!;
} else {
_setError(response.message);
}
} catch (e) {
_setError('加载最近测试结果失<EFBFBD>? ${e.toString()}');
} finally {
_setLoading(false);
}
}
/// 加载测试结果详情
Future<void> loadTestResultById(String resultId) async {
_setLoading(true);
_setError(null);
try {
final response = await _testService.getTestResultById(resultId);
if (response.success && response.data != null) {
_currentResult = response.data!;
} else {
_setError(response.message);
}
} catch (e) {
_setError('加载测试结果失败: ${e.toString()}');
} finally {
_setLoading(false);
}
}
/// 加载用户技能统<E883BD>? Future<void> loadUserSkillStatistics(String userId) async {
_setLoading(true);
_setError(null);
try {
final response = await _testService.getUserSkillStatistics(userId);
if (response.success && response.data != null) {
_skillStatistics = response.data!;
} else {
_setError(response.message);
}
} catch (e) {
_setError('加载技能统计失<EFBFBD>? ${e.toString()}');
} finally {
_setLoading(false);
}
}
/// 加载题目统计
Future<void> loadQuestionStatistics() async {
_setLoading(true);
_setError(null);
try {
final response = await _testService.getQuestionStatistics();
if (response.success && response.data != null) {
_questionStatistics = response.data!;
} else {
_setError(response.message);
}
} catch (e) {
_setError('加载题目统计失败: ${e.toString()}');
} finally {
_setLoading(false);
}
}
/// 删除测试结果
Future<bool> deleteTestResult(String resultId) async {
_setLoading(true);
_setError(null);
try {
final response = await _testService.deleteTestResult(resultId);
if (response.success) {
_testResults.removeWhere((result) => result.id == resultId);
notifyListeners();
return true;
} else {
_setError(response.message);
return false;
}
} catch (e) {
_setError('删除测试结果失败: ${e.toString()}');
return false;
} finally {
_setLoading(false);
}
}
/// 重置当前会话
void resetCurrentSession() {
_currentSession = null;
_currentResult = null;
_stopTimer();
notifyListeners();
}
/// 开始计时器
void _startTimer() {
_isTimerRunning = true;
_updateTimer();
}
/// 暂停计时<E8AEA1>? void _pauseTimer() {
_isTimerRunning = false;
}
/// 停止计时<E8AEA1>? void _stopTimer() {
_isTimerRunning = false;
_timeRemaining = 0;
}
/// 更新计时<E8AEA1>? void _updateTimer() {
if (_isTimerRunning && _timeRemaining > 0) {
Future.delayed(const Duration(seconds: 1), () {
if (_isTimerRunning) {
_timeRemaining--;
notifyListeners();
if (_timeRemaining <= 0) {
// 时间到,自动完成测试
completeTest();
} else {
_updateTimer();
}
}
});
}
}
/// 格式化剩余时<E4BD99>? String getFormattedTimeRemaining() {
final hours = _timeRemaining ~/ 3600;
final minutes = (_timeRemaining % 3600) ~/ 60;
final seconds = _timeRemaining % 60;
if (hours > 0) {
return '${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
} else {
return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
}
}
/// 获取测试进度百分<E799BE>? double getTestProgress() {
if (_currentSession == null || _currentSession!.questions.isEmpty) {
return 0.0;
}
return (_currentSession!.currentQuestionIndex + 1) / _currentSession!.questions.length;
}
/// 获取已回答题目数<E79BAE>? int getAnsweredQuestionsCount() {
return _currentSession?.answers.length ?? 0;
}
/// 获取未回答题目数<E79BAE>? int getUnansweredQuestionsCount() {
if (_currentSession == null) return 0;
return _currentSession!.questions.length - _currentSession!.answers.length;
}
/// 检查是否所有题目都已回<E5B7B2>? bool areAllQuestionsAnswered() {
if (_currentSession == null) return false;
return _currentSession!.answers.length == _currentSession!.questions.length;
}
/// 获取技能类型的中文名称
String getSkillTypeName(SkillType skillType) {
switch (skillType) {
case SkillType.vocabulary:
return '词汇';
case SkillType.grammar:
return '语法';
case SkillType.reading:
return '阅读';
case SkillType.listening:
return '听力';
case SkillType.speaking:
return '口语';
case SkillType.writing:
return '写作';
}
}
/// 获取难度等级的中文名<E69687>? String getDifficultyLevelName(DifficultyLevel level) {
switch (level) {
case DifficultyLevel.beginner:
return '初级';
case DifficultyLevel.elementary:
return '基础';
case DifficultyLevel.intermediate:
return '中级';
case DifficultyLevel.upperIntermediate:
return '中高<EFBFBD>?;
case DifficultyLevel.advanced:
return '高级';
case DifficultyLevel.expert:
return '专家<EFBFBD>?;
}
}
/// 获取测试类型的中文名<E69687>? String getTestTypeName(TestType type) {
switch (type) {
case TestType.quick:
return '快速测<EFBFBD>?;
case TestType.standard:
return '标准测试';
case TestType.full:
return '完整测试';
case TestType.mock:
return '模拟考试';
}
}
/// 加载最近的测试结果
Future<void> loadRecentResults({String? userId}) async {
_setLoading(true);
_setError(null);
try {
final response = await _testService.getRecentTestResults(userId);
if (response.success && response.data != null) {
_testResults = response.data!;
} else {
_setError(response.message);
}
} catch (e) {
_setError('加载测试结果失败: ${e.toString()}');
} finally {
_setLoading(false);
}
}
@override
void dispose() {
_stopTimer();
super.dispose();
}
}