155 lines
5.3 KiB
PHP
155 lines
5.3 KiB
PHP
<?php
|
|
|
|
require_once __DIR__ . '/../app/bootstrap.php';
|
|
|
|
use App\Services\CurriculumService;
|
|
|
|
/**
|
|
* Intelligent & Semantic Markdown Curriculum Parser
|
|
* Maps sections with 100% precision:
|
|
* - Lesson 1 -> lesson_01.md
|
|
* - Lesson 2 -> lesson_02.md
|
|
* - Intro & Project -> intro_and_project.md
|
|
* - GeoGebra Lab -> geogebra_lab.md
|
|
* - Unit Exam -> unit_exam.md
|
|
*/
|
|
function parseAndIngestTextbookMarkdown(string $rawMarkdown, array $metadata = []): array
|
|
{
|
|
$lines = explode("\n", $rawMarkdown);
|
|
|
|
$gradeName = $metadata['grade_name'] ?? 'الصف العاشر';
|
|
$gradeKey = $metadata['grade_key'] ?? 'grade_10';
|
|
$subName = $metadata['subject_name'] ?? 'الرياضيات';
|
|
$subKey = $metadata['subject_key'] ?? 'math_10';
|
|
$semName = $metadata['semester_name'] ?? 'الفصل الدراسي الأول';
|
|
$semKey = $metadata['semester_key'] ?? 'semester_1';
|
|
|
|
$units = [];
|
|
$currentUnit = null;
|
|
$currentLesson = null;
|
|
$lessonBuffer = [];
|
|
|
|
$flushLesson = function() use (&$currentUnit, &$currentLesson, &$lessonBuffer) {
|
|
if ($currentUnit && $currentLesson) {
|
|
$content = trim(implode("\n", $lessonBuffer));
|
|
if (!empty($content)) {
|
|
$currentLesson['markdown_content'] = $content;
|
|
$currentUnit['lessons'][] = $currentLesson;
|
|
}
|
|
$currentLesson = null;
|
|
$lessonBuffer = [];
|
|
}
|
|
};
|
|
|
|
$flushUnit = function() use (&$units, &$currentUnit, $flushLesson) {
|
|
$flushLesson();
|
|
if ($currentUnit && !empty($currentUnit['lessons'])) {
|
|
$units[] = $currentUnit;
|
|
$currentUnit = null;
|
|
}
|
|
};
|
|
|
|
$unitCounter = 0;
|
|
|
|
$arabicOrdinalMap = [
|
|
'الأولى' => 1, 'الاولى' => 1, '1' => 1,
|
|
'الثانية' => 2, 'الثانيه' => 2, '2' => 2,
|
|
'الثالثة' => 3, 'الثالثه' => 3, '3' => 3,
|
|
'الرابعة' => 4, 'الرابعه' => 4, '4' => 4,
|
|
'الخامسة' => 5, 'الخامسه' => 5, '5' => 5,
|
|
'السادسة' => 6, 'السادسه' => 6, '6' => 6,
|
|
];
|
|
|
|
foreach ($lines as $line) {
|
|
$trimmed = trim($line);
|
|
|
|
// Detect Unit (# UNIT or # الوحدة)
|
|
if (preg_match('/^#\s+(UNIT|الوحدة)\s*([0-9\-\:A-Za-z\s\p{Arabic}]+)(.*)$/ui', $trimmed, $m) || preg_match('/^#\s+([A-Za-z0-9\s]+(?:SPOT|SKILLS|REFERENCE|LIST))/ui', $trimmed, $m2)) {
|
|
$flushUnit();
|
|
$unitTitle = trim(preg_replace('/^#\s+/u', '', $trimmed));
|
|
|
|
$detectedNum = null;
|
|
foreach ($arabicOrdinalMap as $word => $num) {
|
|
if (mb_stripos($unitTitle, $word) !== false) {
|
|
$detectedNum = $num;
|
|
break;
|
|
}
|
|
}
|
|
if ($detectedNum !== null) {
|
|
$unitCounter = $detectedNum;
|
|
} else {
|
|
$unitCounter++;
|
|
}
|
|
|
|
$unitKey = sprintf('unit_%02d', $unitCounter);
|
|
|
|
$currentUnit = [
|
|
'unit_key' => $unitKey,
|
|
'unit_name' => $unitTitle,
|
|
'lessons' => []
|
|
];
|
|
continue;
|
|
}
|
|
|
|
// Detect Section (## ...)
|
|
if (preg_match('/^##\s+(.+)$/u', $trimmed, $mAlt) && $currentUnit) {
|
|
$flushLesson();
|
|
$lessonTitle = trim($mAlt[1]);
|
|
|
|
// Semantic Identification of Lesson ID and File
|
|
if (preg_match('/(?:الدرس|Lesson)\s*([0-9]+)/ui', $lessonTitle, $mLes)) {
|
|
$lesNum = (int)$mLes[1];
|
|
$lesId = sprintf('lesson_%02d', $lesNum);
|
|
} elseif (preg_match('/(?:مقدمة|مشروع)/ui', $lessonTitle)) {
|
|
$lesId = 'intro_and_project';
|
|
} elseif (preg_match('/(?:معمل|جيوجبرا|نشاط)/ui', $lessonTitle)) {
|
|
$lesId = 'geogebra_lab';
|
|
} elseif (preg_match('/(?:اختبار|تدريب)/ui', $lessonTitle)) {
|
|
$lesId = 'unit_exam';
|
|
} else {
|
|
$lesId = 'section_' . count($currentUnit['lessons'] ?? []);
|
|
}
|
|
|
|
$currentLesson = [
|
|
'lesson_id' => $lesId,
|
|
'title' => $lessonTitle,
|
|
'outcomes' => [$lessonTitle]
|
|
];
|
|
$lessonBuffer = [$trimmed];
|
|
continue;
|
|
}
|
|
|
|
if ($currentLesson) {
|
|
$lessonBuffer[] = $line;
|
|
}
|
|
}
|
|
|
|
$flushUnit();
|
|
|
|
// Clean old files in target directories to eliminate stubs
|
|
$baseUnitDir = __DIR__ . "/../storage/curriculum/{$gradeKey}/{$subKey}/{$semKey}/";
|
|
foreach ($units as $u) {
|
|
$uDir = $baseUnitDir . $u['unit_key'];
|
|
if (is_dir($uDir)) {
|
|
$existingFiles = glob($uDir . '/*.md');
|
|
foreach ($existingFiles as $f) {
|
|
if (basename($f) === 'lesson_1.md' || basename($f) === 'lesson_2.md') {
|
|
@unlink($f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$extracted = [
|
|
'grade_name' => $gradeName,
|
|
'grade_key' => $gradeKey,
|
|
'subject_name' => $subName,
|
|
'subject_key' => $subKey,
|
|
'semester_name' => $semName,
|
|
'semester_key' => $semKey,
|
|
'units' => $units
|
|
];
|
|
|
|
return CurriculumService::mergeExtractedCurriculum($extracted);
|
|
}
|