getQueryParams(); $courseId = !empty($queryParams['course_id']) ? (int)$queryParams['course_id'] : null; $lessonId = !empty($queryParams['lesson_id']) ? (int)$queryParams['lesson_id'] : null; $scope = $queryParams['scope'] ?? null; $sql = "SELECT e.*, COUNT(q.id) as questions_count FROM exams e LEFT JOIN questions q ON q.exam_id = e.id WHERE e.is_published = 1"; $params = []; if ($courseId) { $sql .= " AND e.course_id = ?"; $params[] = $courseId; } if ($lessonId) { $sql .= " AND e.lesson_id = ?"; $params[] = $lessonId; } if ($scope) { $sql .= " AND e.scope = ?"; $params[] = $scope; } $sql .= " GROUP BY e.id ORDER BY e.timestamp_seconds ASC, e.id ASC"; $exams = Database::select($sql, $params); $response->json([ 'status' => 'success', 'data' => $exams ]); } /** * Get single exam with questions and sanitized options * GET /api/exams/{id} */ public function getExamDetails(Request $request, Response $response): void { self::ensureSchema(); $examId = (int)$request->getParam('id'); $isTeacher = ($request->role === 'teacher' || $request->role === 'super_admin'); $exam = Database::selectOne("SELECT * FROM exams WHERE id = ? LIMIT 1", [$examId]); if (!$exam || $examId === 1 || (str_contains($exam['title'] ?? '', 'الوحدة الأولى') && count(Database::select("SELECT id FROM questions WHERE exam_id = ?", [$examId])) < 15)) { $examId = self::seedUnit1ComprehensiveExam(); $exam = Database::selectOne("SELECT * FROM exams WHERE id = ? LIMIT 1", [$examId]); } if (!$exam) { $response->status(404)->json(['status' => 'error', 'message' => 'الامتحان غير موجود']); return; } $questions = Database::select("SELECT * FROM questions WHERE exam_id = ? ORDER BY id ASC", [$examId]); foreach ($questions as &$q) { $options = Database::select("SELECT id, option_text, feedback_text" . ($isTeacher ? ", is_correct" : "") . " FROM question_options WHERE question_id = ? ORDER BY id ASC", [$q['id']]); $q['options'] = $options; } $exam['questions'] = $questions; $response->json([ 'status' => 'success', 'data' => $exam ]); } /** * Submit Exam Attempt & Calculate Instant AI Diagnostic Evaluation * POST /api/exams/{id}/submit */ public function submitExam(Request $request, Response $response): void { self::ensureAttemptSchema(); $studentId = $request->user_id; $examId = (int)$request->getParam('id'); $body = $request->getBody(); $answers = $body['answers'] ?? []; // Array of ['question_id' => X, 'selected_option_id' => Y] $timeSpent = (int)($body['time_spent_seconds'] ?? 0); $exam = Database::selectOne("SELECT * FROM exams WHERE id = ? LIMIT 1", [$examId]); if (!$exam) { $response->status(404)->json(['status' => 'error', 'message' => 'الامتحان غير موجود']); return; } // Fetch all questions and correct options $questions = Database::select("SELECT id, points, topic_tag, explanation_text, ai_hint FROM questions WHERE exam_id = ?", [$examId]); $questionMap = []; $totalPoints = 0; foreach ($questions as $q) { $questionMap[$q['id']] = $q; $totalPoints += (int)$q['points']; } $options = Database::select("SELECT id, question_id, is_correct, feedback_text FROM question_options WHERE question_id IN (" . implode(',', array_keys($questionMap)) . ")"); $correctOptions = []; foreach ($options as $opt) { if ($opt['is_correct']) { $correctOptions[$opt['question_id']] = (int)$opt['id']; } } // Score evaluation $earnedScore = 0; $weakTopics = []; $detailedAnswers = []; foreach ($answers as $ans) { $qId = (int)($ans['question_id'] ?? 0); $selectedOptId = (int)($ans['selected_option_id'] ?? 0); if (!isset($questionMap[$qId])) continue; $isCorrect = (isset($correctOptions[$qId]) && $correctOptions[$qId] === $selectedOptId); $qPoints = (int)$questionMap[$qId]['points']; $awarded = $isCorrect ? $qPoints : 0; $earnedScore += $awarded; if (!$isCorrect) { $topic = $questionMap[$qId]['topic_tag'] ?: 'المفاهيم العامة'; $weakTopics[$topic] = ($weakTopics[$topic] ?? 0) + 1; } $detailedAnswers[] = [ 'question_id' => $qId, 'selected_option_id' => $selectedOptId, 'is_correct' => $isCorrect ? 1 : 0, 'points_awarded' => $awarded, 'explanation' => $questionMap[$qId]['explanation_text'] ?? null, 'ai_hint' => $questionMap[$qId]['ai_hint'] ?? null ]; } $percentage = $totalPoints > 0 ? round(($earnedScore / $totalPoints) * 100, 2) : 0; $passed = ($percentage >= (float)$exam['passing_percentage']); $status = $passed ? 'passed' : 'needs_remediation'; // AI Diagnostic Report $aiReport = $passed ? "أداء ممتاز! استيعاب قوي للمفاهيم بنسبة {$percentage}%. أنت جاهز تماماً للانتقال للدرس التالي." : "تحتاج لمراجعة المفاهيم المتعلقة بـ: " . implode('، ', array_keys($weakTopics)) . ". يُنصح بمشاهدة مقطع الشرح الموصى به."; // Insert Attempt Record self::ensureSchema(); $uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) ); $attemptId = Database::insert( "INSERT INTO exam_attempts (uuid, student_id, exam_id, score, total_score, percentage, status, time_spent_seconds, weak_topics_json, ai_diagnostic_report, completed_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())", [$uuid, $studentId, $examId, $earnedScore, $totalPoints, $percentage, $status, $timeSpent, json_encode(array_keys($weakTopics), JSON_UNESCAPED_UNICODE), $aiReport] ); // Save detailed question answers safely foreach ($detailedAnswers as $dAns) { try { Database::insert( "INSERT INTO student_question_answers (attempt_id, student_id, question_id, selected_option_id, is_correct, points_awarded, time_spent_seconds) VALUES (?, ?, ?, ?, ?, ?, ?)", [$attemptId, $studentId, $dAns['question_id'], $dAns['selected_option_id'], $dAns['is_correct'], $dAns['points_awarded'], 0] ); } catch (\Throwable $e) { error_log("student_question_answers insert notice: " . $e->getMessage()); } } // Update Student Cumulative Mastery & Tawjihi Readiness Score $courseId = (int)$exam['course_id']; $subjectId = (int)Database::selectOne("SELECT subject_id FROM courses WHERE id = ? LIMIT 1", [$courseId])['subject_id']; $allAttempts = Database::select( "SELECT ea.percentage, ea.status FROM exam_attempts ea JOIN exams e ON e.id = ea.exam_id WHERE ea.student_id = ? AND e.course_id = ?", [$studentId, $courseId] ); $totalExams = count($allAttempts); $passedExams = 0; $sumPct = 0; foreach ($allAttempts as $att) { $sumPct += (float)$att['percentage']; if ($att['status'] === 'passed') $passedExams++; } $avgMastery = $totalExams > 0 ? round($sumPct / $totalExams, 2) : 0; $tawjihiIndex = round(($avgMastery * 0.7) + (($passedExams / max(1, $totalExams)) * 30), 1); Database::query(" INSERT INTO student_mastery_analytics (student_id, course_id, subject_id, mastery_percentage, tawjihi_readiness_score, exams_passed_count, exams_total_count, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, NOW()) ON DUPLICATE KEY UPDATE mastery_percentage = VALUES(mastery_percentage), tawjihi_readiness_score = VALUES(tawjihi_readiness_score), exams_passed_count = VALUES(exams_passed_count), exams_total_count = VALUES(exams_total_count), updated_at = NOW() ", [$studentId, $courseId, $subjectId, $avgMastery, $tawjihiIndex, $passedExams, $totalExams]); // Trigger Guardian Alert via Nabeh WhatsApp if remediation needed if (!$passed && !empty($weakTopics)) { try { $studentInfo = Database::selectOne( "SELECT s.full_name, sub.name AS subject_name FROM students s LEFT JOIN courses c ON c.id = ? LEFT JOIN subjects sub ON sub.id = c.subject_id WHERE s.id = ? LIMIT 1", [$courseId, $studentId] ); $guardian = Database::selectOne( "SELECT ai.phone_number FROM guardian_students gs JOIN guardians g ON g.id = gs.guardian_id JOIN auth_identities ai ON ai.id = g.auth_identity_id WHERE gs.student_id = ? LIMIT 1", [$studentId] ); if ($guardian && !empty($guardian['phone_number'])) { $nabeh = new \App\Services\NabehService(); $weakTopicStr = implode('، ', array_keys($weakTopics)); $nabeh->sendGuardianRemedialAlert( (string)$guardian['phone_number'], $studentInfo['full_name'] ?? 'الطالب', $studentInfo['subject_name'] ?? 'المبحث المقرر', $weakTopicStr ); } } catch (\Throwable $e) { error_log("Guardian remedial alert notice: " . $e->getMessage()); } } $response->json([ 'status' => 'success', 'data' => [ 'attempt_id' => $attemptId, 'score' => $earnedScore, 'total_score' => $totalPoints, 'percentage' => $percentage, 'passed' => $passed, 'rewind_seconds' => $passed ? 0 : (int)$exam['rewind_on_fail_seconds'], 'ai_diagnostic_report' => $aiReport, 'weak_topics' => array_keys($weakTopics), 'tawjihi_readiness_score'=> $tawjihiIndex, 'detailed_answers' => $detailedAnswers ] ]); } /** Additive production migration for installations created before completed_at. */ private static function ensureAttemptSchema(): void { try { $column = Database::selectOne( "SELECT COUNT(*) AS cnt FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'exam_attempts' AND COLUMN_NAME = 'completed_at' LIMIT 1" ); if (empty($column['cnt'])) { Database::query("ALTER TABLE exam_attempts ADD COLUMN completed_at TIMESTAMP NULL DEFAULT NULL AFTER ai_diagnostic_report"); } } catch (\Throwable $e) { error_log('Exam schema migration note: ' . $e->getMessage()); } } /** * Get Student Mastery & Tawjihi Readiness Analytics * GET /api/student/progress/mastery?course_id=1 */ public function getMastery(Request $request, Response $response): void { $studentId = $request->user_id; $courseId = (int)$request->getParam('course_id'); $analytics = Database::selectOne( "SELECT * FROM student_mastery_analytics WHERE student_id = ? AND course_id = ? LIMIT 1", [$studentId, $courseId] ); $recentAttempts = Database::select( "SELECT ea.id, ea.score, ea.total_score, ea.percentage, ea.status, ea.ai_diagnostic_report, ea.completed_at, e.title as exam_title, e.scope FROM exam_attempts ea JOIN exams e ON e.id = ea.exam_id WHERE ea.student_id = ? AND e.course_id = ? ORDER BY ea.id DESC LIMIT 10", [$studentId, $courseId] ); $response->json([ 'status' => 'success', 'data' => [ 'analytics' => $analytics ?: [ 'mastery_percentage' => 0, 'tawjihi_readiness_score'=> 0, 'exams_passed_count' => 0, 'exams_total_count' => 0 ], 'recent_attempts' => $recentAttempts ] ]); } public static function ensureSchema(): void { try { Database::query( "CREATE TABLE IF NOT EXISTS `student_question_answers` ( `id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `attempt_id` BIGINT UNSIGNED NOT NULL, `student_id` BIGINT UNSIGNED NOT NULL, `question_id` BIGINT UNSIGNED NOT NULL, `selected_option_id` BIGINT UNSIGNED NULL, `is_correct` TINYINT(1) NOT NULL DEFAULT 0, `points_awarded` DECIMAL(5, 2) NOT NULL DEFAULT 0.00, `time_spent_seconds` INT UNSIGNED NOT NULL DEFAULT 0, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, KEY `idx_sqa_attempt` (`attempt_id`), KEY `idx_sqa_student` (`student_id`), KEY `idx_sqa_question` (`question_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci" ); // Ensure completed_at in exam_attempts $colCheck = Database::selectOne( "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'exam_attempts' AND COLUMN_NAME = 'completed_at' LIMIT 1" ); if (!$colCheck) { Database::query("ALTER TABLE exam_attempts ADD COLUMN completed_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP AFTER ai_diagnostic_report"); } } catch (\Throwable $e) { error_log("ExamController ensureSchema notice: " . $e->getMessage()); } } public static function seedUnit1ComprehensiveExam(): int { self::ensureSchema(); $exam = Database::selectOne( "SELECT id FROM exams WHERE (scope = 'unit_comprehensive' OR scope = 'unit_exam' OR id = 1) AND (title LIKE '%الوحدة الأولى%' OR id = 1) LIMIT 1" ); $examId = $exam ? (int)$exam['id'] : 0; if (!$examId) { $examId = (int)Database::insert( "INSERT INTO exams (uuid, course_id, lesson_id, creator_type, scope, title, passing_percentage, total_points, duration_minutes, is_mandatory, is_published) VALUES (UUID(), 1, 0, 'ai_adaptive', 'unit_comprehensive', 'اختبار الفهم الشامل: الوحدة الأولى — أنظمة المعادلات', 70.00, 100, 45, 1, 1)" ); } else { Database::query( "UPDATE exams SET title = 'اختبار الفهم الشامل: الوحدة الأولى — أنظمة المعادلات', duration_minutes = 45, total_points = 100, passing_percentage = 70.00, is_published = 1 WHERE id = ?", [$examId] ); } $existingQuestions = Database::select("SELECT id, question_text FROM questions WHERE exam_id = ?", [$examId]); $hasCalculus = false; foreach ($existingQuestions as $eq) { if (str_contains($eq['question_text'], 'مشتق') || str_contains($eq['question_text'], "f'(x)")) { $hasCalculus = true; break; } } if (count($existingQuestions) < 15 || $hasCalculus) { // Wipe legacy corrupt questions foreach ($existingQuestions as $oq) { Database::query("DELETE FROM question_options WHERE question_id = ?", [$oq['id']]); } Database::query("DELETE FROM questions WHERE exam_id = ?", [$examId]); $bank = self::getUnit1QuestionBank(); foreach ($bank as $qData) { $qId = (int)Database::insert( "INSERT INTO questions (uuid, exam_id, question_text, question_type, bloom_taxonomy, topic_tag, explanation_text, points) VALUES (UUID(), ?, ?, 'multiple_choice', ?, ?, ?, ?)", [$examId, $qData['question_text'], $qData['bloom'], $qData['topic'], $qData['explanation'], $qData['points']] ); foreach ($qData['options'] as $idx => $optText) { Database::insert( "INSERT INTO question_options (question_id, option_text, is_correct) VALUES (?, ?, ?)", [$qId, $optText, ($idx === $qData['correct_index']) ? 1 : 0] ); } } } return $examId; } public static function getUnit1QuestionBank(): array { return [ [ 'question_text' => 'ما هي مجموعة حل المعادلة الحقيقية: x³ - 4x = 0؟', 'bloom' => 'recall', 'topic' => 'حل المعادلات بإخراج العامل المشترك الأكبر', 'explanation' => 'بإخراج x كعامل مشترك: x(x² - 4) = 0 ومنها x(x - 2)(x + 2) = 0، فيكون الحل x = 0, 2, -2.', 'points' => 6, 'options' => ['{ -2, 0, 2 }', '{ 0, 4 }', '{ -2, 2 }', '{ 0, 2 }'], 'correct_index' => 0 ], [ 'question_text' => 'حل المعادلة x⁴ - 5x² + 4 = 0 في مجموعة الأعداد الحقيقية هو:', 'bloom' => 'comprehension', 'topic' => 'المعادلات في الصورة التربيعية', 'explanation' => 'بالتحليل كمعادلة تربيعية: (x² - 4)(x² - 1) = 0، ومنها x² = 4 أو x² = 1، فالجذور هي ±2 و ±1.', 'points' => 7, 'options' => ['{ -2, -1, 1, 2 }', '{ 1, 4 }', '{ -1, 1 }', '{ -4, 4 }'], 'correct_index' => 0 ], [ 'question_text' => 'كم حلاً حقيقياً يحقق المعادلة: x³ + 8 = 0؟', 'bloom' => 'comprehension', 'topic' => 'تحليل مجموع المكعبين والحلول الحقيقية', 'explanation' => 'بتحليل مجموع مكعبين: (x + 2)(x² - 2x + 4) = 0. القوس التربيعي مميزه سالب (-12) فلا يعطي جذوراً حقيقية، والحل الحقيقي الوحيد هو x = -2.', 'points' => 6, 'options' => ['حل حقيقي واحد فقط وهو x = -2', 'ثلاثة حلول حقيقية', 'حلّان حقيقيان', 'لا يوجد أي حل حقيقي'], 'correct_index' => 0 ], [ 'question_text' => 'ما هو أقصى عدد ممكن لنقاط التقاطع بين مستقيم وقطع مكافئ في المستوى الإحداثي؟', 'bloom' => 'recall', 'topic' => 'التمثيل الهندسي لنظام خطي وتربيعي', 'explanation' => 'المستقيم يقطع القطع المكافئ في نقطتين كحد أقصى (حلان)، أو يمسه في نقطة (حل واحد)، أو لا يقطعه (لا يوجد حل حقيقي).', 'points' => 6, 'options' => ['نقطتان كحد أقصى (حلّان حقيقيان)', 'ثلاث نقاط تقاطع', 'أربع نقاط تقاطع', 'نقطة واحدة فقط دائماً'], 'correct_index' => 0 ], [ 'question_text' => 'إذا كان لدينا النظام: y = x + 1 و y = x² + 1، فما هي نقاط تقاطع المنحنيين؟', 'bloom' => 'application', 'topic' => 'حل نظام خطي وتربيعي بطريقة التعويض', 'explanation' => 'بالمساواة: x² + 1 = x + 1 ومنها x² - x = 0 أي x(x - 1) = 0، فيكون x = 0 أو x = 1. بالتعويض نجد y = 1 أو y = 2.', 'points' => 7, 'options' => ['(0, 1) و (1, 2)', '(0, 0) و (1, 1)', '(1, 2) فقط', '(-1, 0) و (1, 2)'], 'correct_index' => 0 ], [ 'question_text' => 'متى لا يوجد أي حل حقيقي لنظام مكوّن من معادلة خطية وأخرى تربيعية؟', 'bloom' => 'analysis', 'topic' => 'استخدام المميز لتحديد عدد حلول النظام', 'explanation' => 'إذا كان مميز المعادلة التربيعية الناتجة عن التعويض سالباً (Δ = b² - 4ac < 0)، فإن المستقيم لا يتقاطع مع المنحنى.', 'points' => 7, 'options' => ['عندما يكون مميز المعادلة التربيعية الناتجة سالباً (Δ < 0)', 'عندما يكون المميز مساوياً لصفر', 'عندما يكون المميز موجباً تماماً', 'إذا كان ميل المستقيم يساوي صفراً'], 'correct_index' => 0 ], [ 'question_text' => 'إذا كان لنظام مكوّن من مستقيم وقطع مكافئ حل حقيقي وحيد فقط، فإن المستقيم يعتبر:', 'bloom' => 'comprehension', 'topic' => 'المستقيم المماس لمنحنى تربيعي', 'explanation' => 'وجود حل حقيقي وحيد لنظام خطي-تربيعي يعني هندسياً أن المستقيم يمس المنحنى عند نقطة واحدة فقط.', 'points' => 6, 'options' => ['مماساً لمنحنى القطع المكافئ عند نقطة التماس', 'قاطعاً للمنحنى في نقطتين', 'خط تقارب رأسي للمنحنى', 'محور تماثل للقطع المكافئ'], 'correct_index' => 0 ], [ 'question_text' => 'في النظام: x² + y² = 25 و x² - y² = 7، ما هي قيمة x²؟', 'bloom' => 'application', 'topic' => 'حل نظام تربيعي بطريقة الحذف', 'explanation' => 'بجمع المعادلتين طرفاً لطرف: 2x² = 32 ومنها x² = 16.', 'points' => 7, 'options' => ['x² = 16', 'x² = 9', 'x² = 32', 'x² = 18'], 'correct_index' => 0 ], [ 'question_text' => 'ما هو أقصى عدد ممكن من نقاط التقاطع بين دائرة وقطع مكافئ في المستوى الإحداثي؟', 'bloom' => 'comprehension', 'topic' => 'التقاطع الهندسي بين منحنيين تربيعيين', 'explanation' => 'يمكن لدائرة وقطع مكافئ أن يتقاطعا في 0، أو 1، أو 2، أو 3، أو 4 نقاط كحد أقصى.', 'points' => 7, 'options' => ['4 نقاط تقاطع (أربعة حلول)', 'حلان فقط', '6 نقاط تقاطع', 'حل وحيد فقط دائماً'], 'correct_index' => 0 ], [ 'question_text' => 'النظام: x² + y² = 13 و y = x² + 1 يتقاطع في النقطتين:', 'bloom' => 'application', 'topic' => 'التعويض بين معادلتين تربيعيتين', 'explanation' => 'بتعويض x² = y - 1 في الأولى: y - 1 + y² = 13 أي y² + y - 14 = 0 أو نجد بالنظام y=3 و x=±2.', 'points' => 7, 'options' => ['(-2, 3) و (2, 3)', '(3, -2) و (3, 2)', '(0, 1) فقط', '(2, 5) و (-2, 5)'], 'correct_index' => 0 ], [ 'question_text' => 'إذا كانت النقطة (a, b) حلاً لنظام يتكون من دائرة مركزها نقطة الأصل ومعادلة متماثلة حول المحور الصادي، فإن:', 'bloom' => 'analysis', 'topic' => 'خصائص التناظر في أنظمة المعادلات', 'explanation' => 'التماثل حول محور الصادات يعني أن استبدال x بـ (-x) يعطي نفس النتيجة، فالنقطة (-a, b) تكون أيضاً حلاً للنظام.', 'points' => 7, 'options' => ['(-a, b) تكون أيضاً حلاً للنظام', '(a, -b) هو الحل الوحيد دائماً', 'لا يوجد أي تناظر هندسي', 'الحل سالب دائماً'], 'correct_index' => 0 ], [ 'question_text' => 'في برمجية جيوجبرا (GeoGebra)، ما هي الأداة المخصصة لإيجاد حل نظام المعادلات بيانياً؟', 'bloom' => 'recall', 'topic' => 'برمجية جيوجبرا وحل الأنظمة بيانياً', 'explanation' => 'أداة التقاطع (Intersect Tool) في جيوجبرا تُحدد إحداثيات نقاط تقاطع المنحنيات التي تمثل حلول النظام مباشرة.', 'points' => 6, 'options' => ['أداة التقاطع (Intersect Tool)', 'أداة القياس (Measure)', 'أداة الانعكاس (Reflect)', 'أداة المماس (Tangent)'], 'correct_index' => 0 ], [ 'question_text' => 'عند تمثيل معادلتين في جيوجبرا وظهور نقطة التقاطع A = (3, -2)، فهذا يعني هندسياً وجبرياً أن:', 'bloom' => 'comprehension', 'topic' => 'تفسير مخرجات برمجية جيوجبرا', 'explanation' => 'إحداثيات نقطة التقاطع (x, y) تعني أن الزوج المرتب يحقق كلتا المعادلتين معاً في آن واحد، وهو حل النظام.', 'points' => 6, 'options' => ['x = 3 و y = -2 هو حل يحقق كلتا المعادلتين معاً', 'x = -2 و y = 3 هو الحل', 'المنحنيان متباعدان ولا حل لهما', 'النظام له حلول غير منتهية'], 'correct_index' => 0 ], [ 'question_text' => 'لماذا يستخدم خبراء الأرصاد الجوية أنظمة معادلات غير خطية في التنبؤ بالطقس كما ورد في كتاب الطالب؟', 'bloom' => 'comprehension', 'topic' => 'التطبيقات الحياتية لأنظمة المعادلات', 'explanation' => 'لأن أي تغير في أحد العوامل (كالضغط ودرجة الحرارة وسرعة الرياح) يؤدي إلى تغير غير خطي في العوامل الأخرى.', 'points' => 7, 'options' => ['لأن أي تغير في أحد العوامل يؤدي إلى تغير غير خطي في العوامل الأخرى', 'لأن درجة الحرارة ثابتة دائماً على مدار السنة', 'للتخلص من قياس الضغط الجوي', 'لأن سرعة الرياح لا ترتبط بحركة الغلاف الجوي'], 'correct_index' => 0 ], [ 'question_text' => 'سياج مستطيل الشكل محيطه 20 متراً ومساحته 24 متراً مربعاً. ما هما بعدا المستطيل؟', 'bloom' => 'application', 'topic' => 'حل المسائل الهندسية الحياتية باستخدام الأنظمة', 'explanation' => 'النظام: 2(x + y) = 20 ومنها x + y = 10، والمساحة x * y = 24. العددان اللذان مجموعهما 10 وحاصل ضربهما 24 هما 6 و 4.', 'points' => 8, 'options' => ['الطول 6 m والعرض 4 m', 'الطول 8 m والعرض 2 m', 'الطول 10 m والعرض 2.4 m', 'الطول 5 m والعرض 5 m'], 'correct_index' => 0 ] ]; } }