/// Exam, Question, and Socratic Diagnostic Models for Saqel Student App class ExamModel { final int id; final String uuid; final int courseId; final int? lessonId; final String title; final String description; final String scope; final double passingPercentage; final int durationMinutes; final int questionsCount; final List questions; const ExamModel({ required this.id, required this.uuid, required this.courseId, this.lessonId, required this.title, required this.description, required this.scope, required this.passingPercentage, required this.durationMinutes, this.questionsCount = 0, this.questions = const [], }); factory ExamModel.fromJson(Map json) { var rawQuestions = json['questions']; List parsedQuestions = []; if (rawQuestions is List) { parsedQuestions = rawQuestions .map((q) => QuestionModel.fromJson(Map.from(q))) .toList(); } return ExamModel( id: (json['id'] as num?)?.toInt() ?? 0, uuid: json['uuid']?.toString() ?? '', courseId: (json['course_id'] as num?)?.toInt() ?? 0, lessonId: (json['lesson_id'] as num?)?.toInt(), 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, questions: parsedQuestions, ); } } class QuestionModel { final int id; final String questionText; final String questionType; final int points; final String topicTag; final String? explanationText; final String? aiHint; final List options; const QuestionModel({ required this.id, required this.questionText, required this.questionType, required this.points, required this.topicTag, this.explanationText, this.aiHint, this.options = const [], }); factory QuestionModel.fromJson(Map json) { var rawOptions = json['options']; List parsedOptions = []; if (rawOptions is List) { parsedOptions = rawOptions .map((opt) => QuestionOptionModel.fromJson(Map.from(opt))) .toList(); } return QuestionModel( id: (json['id'] as num?)?.toInt() ?? 0, questionText: json['question_text']?.toString() ?? '', questionType: json['question_type']?.toString() ?? 'multiple_choice', points: (json['points'] as num?)?.toInt() ?? 10, topicTag: json['topic_tag']?.toString() ?? 'المفاهيم العامة', explanationText: json['explanation_text']?.toString(), aiHint: json['ai_hint']?.toString(), options: parsedOptions, ); } } class QuestionOptionModel { final int id; final String optionText; final bool isCorrect; final int sequenceOrder; const QuestionOptionModel({ required this.id, required this.optionText, this.isCorrect = false, this.sequenceOrder = 1, }); factory QuestionOptionModel.fromJson(Map json) { return QuestionOptionModel( id: (json['id'] as num?)?.toInt() ?? 0, optionText: json['option_text']?.toString() ?? '', isCorrect: json['is_correct'] == 1 || json['is_correct'] == true, sequenceOrder: (json['sequence_order'] as num?)?.toInt() ?? 1, ); } } class ExamSubmissionResultModel { final int attemptId; final int score; final int totalScore; final double percentage; final bool passed; final int rewindSeconds; final String aiDiagnosticReport; final List weakTopics; final double tawjihiReadinessScore; final List detailedAnswers; const ExamSubmissionResultModel({ required this.attemptId, required this.score, required this.totalScore, required this.percentage, required this.passed, required this.rewindSeconds, required this.aiDiagnosticReport, required this.weakTopics, required this.tawjihiReadinessScore, this.detailedAnswers = const [], }); factory ExamSubmissionResultModel.fromJson(Map json) { var rawTopics = json['weak_topics']; List parsedTopics = []; if (rawTopics is List) { parsedTopics = rawTopics.map((e) => e.toString()).toList(); } var rawDetails = json['detailed_answers']; List parsedDetails = []; if (rawDetails is List) { parsedDetails = rawDetails .map((d) => DetailedAnswerModel.fromJson(Map.from(d))) .toList(); } 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, aiDiagnosticReport: json['ai_diagnostic_report']?.toString() ?? '', weakTopics: parsedTopics, tawjihiReadinessScore: (json['tawjihi_readiness_score'] as num?)?.toDouble() ?? 0.0, detailedAnswers: parsedDetails, ); } } class DetailedAnswerModel { final int questionId; final int selectedOptionId; final bool isCorrect; final int pointsAwarded; final String? explanation; final String? aiHint; const DetailedAnswerModel({ required this.questionId, required this.selectedOptionId, required this.isCorrect, required this.pointsAwarded, this.explanation, this.aiHint, }); factory DetailedAnswerModel.fromJson(Map 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, explanation: json['explanation']?.toString(), aiHint: json['ai_hint']?.toString(), ); } }