Fix Flutter exam parsing, make exams tab dynamic from API, and add intelligent exam resolution to submitExam

This commit is contained in:
Hamza-Ayed
2026-09-03 16:59:14 +03:00
parent 0a61e32033
commit 445a1aa0e3
3 changed files with 206 additions and 100 deletions
@@ -36,21 +36,33 @@ class ExamModel {
}
return ExamModel(
id: (json['id'] as num?)?.toInt() ?? 0,
id: _toInt(json['id']),
uuid: json['uuid']?.toString() ?? '',
courseId: (json['course_id'] as num?)?.toInt() ?? 0,
lessonId: (json['lesson_id'] as num?)?.toInt(),
courseId: _toInt(json['course_id']),
lessonId: json['lesson_id'] != null ? _toInt(json['lesson_id']) : null,
title: json['title']?.toString() ?? 'امتحان تشخيصي',
description: json['description']?.toString() ?? '',
scope: json['scope']?.toString() ?? 'general',
passingPercentage: (json['passing_percentage'] as num?)?.toDouble() ?? 60.0,
durationMinutes: (json['duration_minutes'] as num?)?.toInt() ?? 20,
questionsCount: (json['questions_count'] as num?)?.toInt() ?? parsedQuestions.length,
scope: json['scope']?.toString() ?? 'unit_exam',
passingPercentage: _toDouble(json['passing_percentage'], 60.0),
durationMinutes: _toInt(json['duration_minutes'], 20),
questionsCount: _toInt(json['questions_count'], parsedQuestions.length),
questions: parsedQuestions,
);
}
}
int _toInt(dynamic value, [int defaultValue = 0]) {
if (value == null) return defaultValue;
if (value is num) return value.toInt();
return int.tryParse(value.toString()) ?? defaultValue;
}
double _toDouble(dynamic value, [double defaultValue = 0.0]) {
if (value == null) return defaultValue;
if (value is num) return value.toDouble();
return double.tryParse(value.toString()) ?? defaultValue;
}
class QuestionModel {
final int id;
final String questionText;
@@ -82,10 +94,10 @@ class QuestionModel {
}
return QuestionModel(
id: (json['id'] as num?)?.toInt() ?? 0,
id: _toInt(json['id']),
questionText: json['question_text']?.toString() ?? '',
questionType: json['question_type']?.toString() ?? 'multiple_choice',
points: (json['points'] as num?)?.toInt() ?? 10,
points: _toInt(json['points'], 10),
topicTag: json['topic_tag']?.toString() ?? 'المفاهيم العامة',
explanationText: json['explanation_text']?.toString(),
aiHint: json['ai_hint']?.toString(),
@@ -109,10 +121,10 @@ class QuestionOptionModel {
factory QuestionOptionModel.fromJson(Map<String, dynamic> json) {
return QuestionOptionModel(
id: (json['id'] as num?)?.toInt() ?? 0,
id: _toInt(json['id']),
optionText: json['option_text']?.toString() ?? '',
isCorrect: json['is_correct'] == 1 || json['is_correct'] == true,
sequenceOrder: (json['sequence_order'] as num?)?.toInt() ?? 1,
isCorrect: json['is_correct'] == 1 || json['is_correct'] == true || json['is_correct'] == '1',
sequenceOrder: _toInt(json['sequence_order'], 1),
);
}
}
@@ -158,15 +170,15 @@ class ExamSubmissionResultModel {
}
return ExamSubmissionResultModel(
attemptId: (json['attempt_id'] as num?)?.toInt() ?? 0,
score: (json['score'] as num?)?.toInt() ?? 0,
totalScore: (json['total_score'] as num?)?.toInt() ?? 0,
percentage: (json['percentage'] as num?)?.toDouble() ?? 0.0,
passed: json['passed'] == true || json['passed'] == 1,
rewindSeconds: (json['rewind_seconds'] as num?)?.toInt() ?? 0,
attemptId: _toInt(json['attempt_id']),
score: _toInt(json['score']),
totalScore: _toInt(json['total_score'], 100),
percentage: _toDouble(json['percentage']),
passed: json['passed'] == true || json['passed'] == 1 || json['passed'] == '1',
rewindSeconds: _toInt(json['rewind_seconds']),
aiDiagnosticReport: json['ai_diagnostic_report']?.toString() ?? '',
weakTopics: parsedTopics,
tawjihiReadinessScore: (json['tawjihi_readiness_score'] as num?)?.toDouble() ?? 0.0,
tawjihiReadinessScore: _toDouble(json['tawjihi_readiness_score'], 50.0),
detailedAnswers: parsedDetails,
);
}
@@ -191,10 +203,10 @@ class DetailedAnswerModel {
factory DetailedAnswerModel.fromJson(Map<String, dynamic> json) {
return DetailedAnswerModel(
questionId: (json['question_id'] as num?)?.toInt() ?? 0,
selectedOptionId: (json['selected_option_id'] as num?)?.toInt() ?? 0,
isCorrect: json['is_correct'] == 1 || json['is_correct'] == true,
pointsAwarded: (json['points_awarded'] as num?)?.toInt() ?? 0,
questionId: _toInt(json['question_id']),
selectedOptionId: _toInt(json['selected_option_id']),
isCorrect: json['is_correct'] == 1 || json['is_correct'] == true || json['is_correct'] == '1',
pointsAwarded: _toInt(json['points_awarded']),
explanation: json['explanation']?.toString(),
aiHint: json['ai_hint']?.toString(),
);