Fix curriculum grounding for Grade 10: replace calculus fallback with authentic Systems of Equations questions and add self-healing guard
This commit is contained in:
@@ -332,10 +332,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
|
sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.19"
|
version: "0.12.18"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -348,10 +348,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349"
|
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.18.0"
|
version: "1.17.0"
|
||||||
nested:
|
nested:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -577,10 +577,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e"
|
sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.11"
|
version: "0.7.9"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -423,6 +423,29 @@ class VideoController
|
|||||||
|
|
||||||
$lessonId = (int)$lesson['id'];
|
$lessonId = (int)$lesson['id'];
|
||||||
|
|
||||||
|
// Self-Healing Curriculum Guard: Purge any obsolete/mismatched calculus questions
|
||||||
|
// for non-calculus lessons (e.g. Grade 10 Systems of Equations)
|
||||||
|
$isCalculusLesson = (str_contains($lesson['title'], 'اشتقاق') || str_contains($lesson['title'], 'تفاضل'));
|
||||||
|
if (!$isCalculusLesson) {
|
||||||
|
try {
|
||||||
|
$mismatched = Database::selectOne(
|
||||||
|
"SELECT q.id FROM questions q
|
||||||
|
JOIN exams e ON q.exam_id = e.id
|
||||||
|
WHERE e.lesson_id = ? AND (q.question_text LIKE '%مشتق%' OR q.question_text LIKE '%f\'(x)%')
|
||||||
|
LIMIT 1",
|
||||||
|
[$lessonId]
|
||||||
|
);
|
||||||
|
if ($mismatched) {
|
||||||
|
$badExams = Database::select("SELECT id FROM exams WHERE lesson_id = ? AND scope = 'in_video_checkpoint'", [$lessonId]);
|
||||||
|
foreach ($badExams as $be) {
|
||||||
|
Database::query("DELETE FROM exams WHERE id = ?", [$be['id']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
error_log("Curriculum self-healing notice: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If lesson has no checkpoints or missing questions, generate them autonomously
|
// If lesson has no checkpoints or missing questions, generate them autonomously
|
||||||
$existingCount = Database::selectOne("SELECT COUNT(*) as cnt FROM exams WHERE lesson_id = ? AND scope = 'in_video_checkpoint'", [$lessonId]);
|
$existingCount = Database::selectOne("SELECT COUNT(*) as cnt FROM exams WHERE lesson_id = ? AND scope = 'in_video_checkpoint'", [$lessonId]);
|
||||||
$existingQuestions = Database::selectOne("SELECT COUNT(*) as cnt FROM questions q JOIN exams e ON q.exam_id = e.id WHERE e.lesson_id = ?", [$lessonId]);
|
$existingQuestions = Database::selectOne("SELECT COUNT(*) as cnt FROM questions q JOIN exams e ON q.exam_id = e.id WHERE e.lesson_id = ?", [$lessonId]);
|
||||||
|
|||||||
@@ -374,8 +374,47 @@ class AiVideoAnalyzerService
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safe generic fallback: never inject unrelated advanced topics when
|
// Grade 10 Mathematics: Systems of Equations (أنظمة المعادلات)
|
||||||
// Gemini is unavailable.
|
$isEquations = (str_contains($title, 'معادلات') || str_contains($title, 'أنظمة') || str_contains($curriculum['unit'] ?? '', 'معادلات'));
|
||||||
|
if ($isEquations) {
|
||||||
|
return [
|
||||||
|
'timeline_chapters' => [
|
||||||
|
['start_seconds' => 0, 'end_seconds' => $c1, 'title' => 'مفهوم أنظمة المعادلات ونماذجها الحياتية', 'summary' => 'التعريف بنظام المعادلات واستخدام النماذج الحياتية مثل الأرصاد والفيزياء.'],
|
||||||
|
['start_seconds' => $c1, 'end_seconds' => $c2, 'title' => 'طرائق الحل الجبري والبياني وبرمجية جيوجبرا', 'summary' => 'حل أنظمة المعادلات بالتعويض والتحليل وتعيين نقاط التقاطع عبر برمجية GeoGebra.'],
|
||||||
|
['start_seconds' => $c2, 'end_seconds' => $duration, 'title' => 'تطبيقات عملية والتحقق من صحة الحل', 'summary' => 'حل مسائل المنهاج والتأكد من تحقيق قيم x و y لكافة معادلات النظام.']
|
||||||
|
],
|
||||||
|
'socratic_checkpoints' => [
|
||||||
|
[
|
||||||
|
'timestamp_seconds' => $cp1,
|
||||||
|
'question_text' => 'ماذا تمثّل نقطة تقاطع منحنيين في المستوى الإحداثي لنظام معادلات؟',
|
||||||
|
'options' => [
|
||||||
|
'حل مشترك يُحقق كِلا المعادلتين معاً في آن واحد',
|
||||||
|
'المسافة الرأسية بين المنحنيين',
|
||||||
|
'معادلة خط التقارب الأفقي فقط',
|
||||||
|
'المقطع الصادي لأحد المنحنيين دون الآخر'
|
||||||
|
],
|
||||||
|
'correct_index' => 0,
|
||||||
|
'rewind_seconds' => $rewind,
|
||||||
|
'explanation' => 'نقطة تقاطع أي منحنيين هندسياً تمثل الزوج المرتب (x, y) الذي يحقق كلتا المعادلتين في آن واحد، وهو حل النظام.'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'timestamp_seconds' => $cp2,
|
||||||
|
'question_text' => 'عند حل نظام مكوّن من معادلة خطية ومعادلة تربيعية، ما هو أقصى عدد ممكن من الحلول الحقيقية؟',
|
||||||
|
'options' => [
|
||||||
|
'حلّان حقيقيان (نقطتا تقاطع)',
|
||||||
|
'ثلاثة حلول حقيقية دائماً',
|
||||||
|
'أربعة حلول حقيقية',
|
||||||
|
'لا يمكن أن يتقاطعا أبداً'
|
||||||
|
],
|
||||||
|
'correct_index' => 0,
|
||||||
|
'rewind_seconds' => $rewind,
|
||||||
|
'explanation' => 'المستقيم يقطع القطع المكافئ في نقطتين كحد أقصى (حلان)، أو يمسه في نقطة واحدة (حل واحد)، أو لا يقطعه (لا يوجد حل حقيقي).'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safe generic fallback: never inject unrelated advanced topics when Gemini is unavailable.
|
||||||
$topics = array_values(array_filter(array_map('strval', $curriculum['core_topics'] ?? [])));
|
$topics = array_values(array_filter(array_map('strval', $curriculum['core_topics'] ?? [])));
|
||||||
$topic = $topics[0] ?? $title;
|
$topic = $topics[0] ?? $title;
|
||||||
$topicTwo = $topics[1] ?? $topic;
|
$topicTwo = $topics[1] ?? $topic;
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Saqel Platform — Self-Healing Socratic Checkpoints Migration & Cleanup Script
|
||||||
|
* Scans all lessons in the database and cleans up any legacy Tawjihi Calculus
|
||||||
|
* checkpoints attached to Grade 10 lessons (e.g. Systems of Equations).
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../app/bootstrap.php';
|
||||||
|
|
||||||
|
use App\Core\Database;
|
||||||
|
use App\Services\AiVideoAnalyzerService;
|
||||||
|
|
||||||
|
echo "======================================================================\n";
|
||||||
|
echo "🧹 SAQEL CURRICULUM CHECKPOINT AUDIT & REPAIR ENGINE\n";
|
||||||
|
echo "======================================================================\n\n";
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Find all lessons with mismatched calculus questions in non-calculus lessons
|
||||||
|
$mismatchedLessons = Database::select(
|
||||||
|
"SELECT DISTINCT l.id, l.title
|
||||||
|
FROM lessons l
|
||||||
|
JOIN exams e ON e.lesson_id = l.id
|
||||||
|
JOIN questions q ON q.exam_id = e.id
|
||||||
|
WHERE (q.question_text LIKE '%مشتق%' OR q.question_text LIKE '%f\'(x)%' OR q.question_text LIKE '%sin(3x)%')
|
||||||
|
AND l.title NOT LIKE '%اشتقاق%' AND l.title NOT LIKE '%تفاضل%'"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (empty($mismatchedLessons)) {
|
||||||
|
echo "✅ No mismatched calculus checkpoints found. All lessons are curriculum-grounded!\n";
|
||||||
|
} else {
|
||||||
|
echo "⚠️ Found " . count($mismatchedLessons) . " lesson(s) with obsolete calculus checkpoints:\n";
|
||||||
|
foreach ($mismatchedLessons as $les) {
|
||||||
|
echo " • Repairing Lesson [ID: {$les['id']}]: '{$les['title']}'...\n";
|
||||||
|
|
||||||
|
// Delete corrupt exam checkpoints
|
||||||
|
$badExams = Database::select("SELECT id FROM exams WHERE lesson_id = ? AND scope = 'in_video_checkpoint'", [$les['id']]);
|
||||||
|
foreach ($badExams as $be) {
|
||||||
|
Database::query("DELETE FROM exams WHERE id = ?", [$be['id']]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-generate fresh, pristine, Grade 10 curriculum checkpoints
|
||||||
|
AiVideoAnalyzerService::processLessonAutonomously((int)$les['id']);
|
||||||
|
echo " ✓ Successfully regenerated authentic Grade 10 curriculum questions!\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\n🎉 Curriculum audit & cleanup completed successfully!\n";
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
echo "❌ Error during cleanup: " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user