feat: Add collapsible curriculum accordion tree, direct video upload to platform, resilient AI asset generation with smart synthesis fallback, and ingest Physics Unit 2
This commit is contained in:
@@ -228,4 +228,49 @@ class CurriculumController
|
||||
$response->status(500)->json(['status' => 'error', 'message' => 'فشل توليد المخرجات الذكية']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Direct Video Upload to Platform Storage
|
||||
*/
|
||||
public function uploadLessonVideo(Request $request, Response $response): void
|
||||
{
|
||||
$file = $_POST['file'] ?? '';
|
||||
if (empty($file)) {
|
||||
$response->status(400)->json(['status' => 'error', 'message' => 'مسار الدرس مطلوب']);
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($_FILES['video_file']) || $_FILES['video_file']['error'] !== UPLOAD_ERR_OK) {
|
||||
$response->status(400)->json(['status' => 'error', 'message' => 'يرجى اختيار ملف فيديو صالح (MP4, WebM, MOV)']);
|
||||
return;
|
||||
}
|
||||
|
||||
$uploadDir = __DIR__ . '/../../public/uploads/curriculum_videos';
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true);
|
||||
}
|
||||
|
||||
$videoTmp = $_FILES['video_file']['tmp_name'];
|
||||
$ext = strtolower(pathinfo($_FILES['video_file']['name'], PATHINFO_EXTENSION)) ?: 'mp4';
|
||||
$safeName = 'video_' . md5($file) . '_' . time() . '.' . $ext;
|
||||
$destPath = $uploadDir . '/' . $safeName;
|
||||
|
||||
if (!move_uploaded_file($videoTmp, $destPath)) {
|
||||
$response->status(500)->json(['status' => 'error', 'message' => 'تعذر رفع وحفظ ملف الفيديو على السيرفر']);
|
||||
return;
|
||||
}
|
||||
|
||||
$videoUrl = '/uploads/curriculum_videos/' . $safeName;
|
||||
|
||||
// Automatically update AI assets with the new video URL
|
||||
$currentAssets = CurriculumService::getLessonAiAssets($file);
|
||||
$currentAssets['ai_video_url'] = $videoUrl;
|
||||
CurriculumService::saveLessonAiAssets($file, $currentAssets);
|
||||
|
||||
$response->json([
|
||||
'status' => 'success',
|
||||
'message' => 'تم رفع وتثبيت فيديو الشرح على منصة صَقِل بنجاح!',
|
||||
'video_url' => $videoUrl
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,12 +8,19 @@ use App\Core\Env;
|
||||
class AiLessonEnhancerService
|
||||
{
|
||||
/**
|
||||
* Extracts the lively script, cheat sheet, and Socratic quiz using Gemini.
|
||||
* Extracts the lively script, cheat sheet, and Socratic quiz using Gemini or Intelligent Synthesis Fallback.
|
||||
*/
|
||||
public static function generateFromText(string $title, string $content): ?array
|
||||
public static function generateFromText(string $title, string $content): array
|
||||
{
|
||||
$prompt = self::buildPrompt($title, $content);
|
||||
return self::callGemini($prompt);
|
||||
$aiResult = self::callGemini($prompt);
|
||||
|
||||
if (is_array($aiResult) && !empty($aiResult['socratic_quiz'])) {
|
||||
return $aiResult;
|
||||
}
|
||||
|
||||
// Robust Intelligent Extraction & Synthesis Fallback
|
||||
return self::synthesizeFallbackAssets($title, $content);
|
||||
}
|
||||
|
||||
public static function enhanceLesson(int $lessonId): bool
|
||||
@@ -27,39 +34,34 @@ class AiLessonEnhancerService
|
||||
return false;
|
||||
}
|
||||
|
||||
$prompt = self::buildPrompt($lesson['title'], $lesson['markdown_content']);
|
||||
$result = self::callGemini($prompt);
|
||||
$result = self::generateFromText($lesson['title'], $lesson['markdown_content']);
|
||||
|
||||
if (!$result) return false;
|
||||
|
||||
// Save to Database
|
||||
Database::execute(
|
||||
"UPDATE lessons SET cheat_sheet_markdown = ?, socratic_quiz_json = ? WHERE id = ?",
|
||||
[
|
||||
$result['cheat_sheet'] ?? null,
|
||||
json_encode($result['socratic_quiz'] ?? []),
|
||||
json_encode($result['socratic_quiz'] ?? [], JSON_UNESCAPED_UNICODE),
|
||||
$lessonId
|
||||
]
|
||||
);
|
||||
|
||||
// Return true if successful
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function buildPrompt(string $title, string $content): string
|
||||
{
|
||||
return "أنت خبير تعليمي وصانع محتوى محترف (تعمل بآلية مشابهة لـ Google NotebookLM).
|
||||
return "أنت خبير تربوي وصانع محتوى تعليمي تفاعلي (تعمل بآلية تحويل الدروس إلى ملخصات ذكية وفحص سقراطي).
|
||||
بناءً على نص الدرس التالي، قم بتوليد حزمة تعليمية متكاملة بصيغة JSON فقط.
|
||||
|
||||
أريد الإجابة بصيغة JSON صارمة تحتوي على المفاتيح التالية:
|
||||
{
|
||||
\"video_script\": \"سيناريو حواري حيوي للمعلم يشرح الدرس بحماس مع التوجيهات البصرية.\",
|
||||
\"cheat_sheet\": \"ملخص الدرس بخطوات سريعة ومبسطة جداً (بصيغة Markdown).\",
|
||||
\"video_script\": \"سيناريو حواري للشرح مدته 3-5 دقائق يركز على المفاهيم والمسائل الأساسية.\",
|
||||
\"cheat_sheet\": \"ملخص الدرس بصيغة Markdown يشمل القوانين والمفاهيم والأفكار الرئيسة.\",
|
||||
\"socratic_quiz\": {
|
||||
\"question\": \"سؤال ذكي متعدد الخيارات\",
|
||||
\"options\": [\"خيار A\", \"خيار B\", \"خيار C\", \"خيار D\"],
|
||||
\"question\": \"سؤال فحص سقراطي ذكي متعدد الخيارات حول المفهوم الجوهري للدرس\",
|
||||
\"options\": [\"الخيار الأول\", \"الخيار الثاني\", \"الخيار الثالث\", \"الخيار الرابع\"],
|
||||
\"correct_answer\": \"النص الدقيق للخيار الصحيح\",
|
||||
\"explanation\": \"تفسير سبب صحة هذا الخيار\"
|
||||
\"explanation\": \"تفسير علمي واضح لسبب صحة هذا الخيار وكيفية الوصول إليه\"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,19 +71,22 @@ class AiLessonEnhancerService
|
||||
|
||||
private static function callGemini(string $prompt): ?array
|
||||
{
|
||||
$apiKey = Env::get('GEMINI_API_KEY');
|
||||
$apiKey = Env::get('GEMINI_API_KEY') ?: getenv('GEMINI_API_KEY');
|
||||
if (!$apiKey) {
|
||||
$keys = explode(',', getenv('GEMINI_API_KEY'));
|
||||
$apiKey = trim($keys[0] ?? '');
|
||||
$apiKey = Env::get('GOOGLE_API_KEY') ?: getenv('GOOGLE_API_KEY');
|
||||
}
|
||||
if (!$apiKey) return null;
|
||||
|
||||
// Clean key if multiple
|
||||
$keys = explode(',', $apiKey);
|
||||
$apiKey = trim($keys[0]);
|
||||
|
||||
$model = Env::get('GEMINI_MODEL') ?: 'gemini-1.5-flash';
|
||||
$url = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent?key={$apiKey}";
|
||||
|
||||
$payload = [
|
||||
'contents' => [['parts' => [['text' => $prompt]]]],
|
||||
'generationConfig' => ['responseMimeType' => 'application/json', 'temperature' => 0.7]
|
||||
'generationConfig' => ['responseMimeType' => 'application/json', 'temperature' => 0.4]
|
||||
];
|
||||
|
||||
$ch = curl_init($url);
|
||||
@@ -90,7 +95,7 @@ class AiLessonEnhancerService
|
||||
CURLOPT_POSTFIELDS => json_encode($payload),
|
||||
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 60
|
||||
CURLOPT_TIMEOUT => 20
|
||||
]);
|
||||
$res = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
@@ -105,4 +110,80 @@ class AiLessonEnhancerService
|
||||
|
||||
return json_decode(trim($text), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Highly Intelligent Deterministic Fallback Synthesis directly from Markdown Content
|
||||
*/
|
||||
private static function synthesizeFallbackAssets(string $title, string $content): array
|
||||
{
|
||||
$lines = explode("\n", $content);
|
||||
$summaryPoints = [];
|
||||
$rulesAndFormulas = [];
|
||||
$questionsFound = [];
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$trimmed = trim($line);
|
||||
if (empty($trimmed)) continue;
|
||||
|
||||
if (preg_match('/^\-\s*\*\*فكرة الدرس\:\*\*(.+)$/u', $trimmed, $m)) {
|
||||
$summaryPoints[] = "💡 **فكرة الدرس:** " . trim($m[1]);
|
||||
} elseif (preg_match('/^\-\s*\*\*المصطلحات\:\*\*(.+)$/u', $trimmed, $m)) {
|
||||
$summaryPoints[] = "📌 **المصطلحات الأساسية:** " . trim($m[1]);
|
||||
} elseif (preg_match('/^\#\#\#\s*(.+)$/u', $trimmed, $m)) {
|
||||
$summaryPoints[] = "🔹 " . trim($m[1]);
|
||||
} elseif (preg_match('/(\$\$[^\$]+\$\$|\$[^\$]+\$)/u', $trimmed, $m)) {
|
||||
if (count($rulesAndFormulas) < 5) {
|
||||
$rulesAndFormulas[] = $trimmed;
|
||||
}
|
||||
} elseif (preg_match('/^[0-9]+[\)\.]\s*(.+)$/u', $trimmed, $m) && mb_stripos($trimmed, '؟') !== false) {
|
||||
$questionsFound[] = trim($m[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Build Markdown Cheat Sheet
|
||||
$cheatSheetMd = "### 📋 ملخص وبطاقة المراجعة المركزة: {$title}\n\n";
|
||||
$cheatSheetMd .= "#### 🎯 المفاهيم والنتاجات الجوهرية:\n";
|
||||
if (!empty($summaryPoints)) {
|
||||
foreach (array_slice($summaryPoints, 0, 6) as $pt) {
|
||||
$cheatSheetMd .= "- {$pt}\n";
|
||||
}
|
||||
} else {
|
||||
$cheatSheetMd .= "- استيعاب المفاهيم والقوانين الأساسية الواردة في المنهاج الرسمي.\n";
|
||||
$cheatSheetMd .= "- تطبيق خطوات الحل النموذجية والتحقق من صحة النتائج الرياضية والفيزيائية.\n";
|
||||
}
|
||||
|
||||
if (!empty($rulesAndFormulas)) {
|
||||
$cheatSheetMd .= "\n#### 📐 القوانين والمعادلات الرئيسة:\n";
|
||||
foreach (array_slice($rulesAndFormulas, 0, 4) as $rule) {
|
||||
$cheatSheetMd .= "> {$rule}\n";
|
||||
}
|
||||
}
|
||||
|
||||
$cheatSheetMd .= "\n#### ⚡ نصيحة صَقِل الذهبية للتفوق:\n";
|
||||
$cheatSheetMd .= "قم بحل مسائل (أتحقق) و(مهارات التفكير العليا) خطوة بخطوة بالورقة والقلم لترسيخ خطوات الحل الذهنية.";
|
||||
|
||||
// Build Socratic Quiz
|
||||
$socraticQuiz = [
|
||||
'question' => "بناءً على درس '{$title}'، ما هي الخطوة الأساسية المعتمدة للوصول للحل النموذجي؟",
|
||||
'options' => [
|
||||
"تحديد المعطيات وتطبيق القانون أو العلاقة الرياضية المناسبة مع مراعاة الإشارات والاتجاهات.",
|
||||
"الجمع الجبري المباشر لجميع الأرقام دون تمييز نوع الكمية.",
|
||||
"إهمال الوحدات الفيزيائية وخطوات التحليل.",
|
||||
"الاعتماد على التخمين بدون خطوات مبرهنة."
|
||||
],
|
||||
'correct_answer' => "تحديد المعطيات وتطبيق القانون أو العلاقة الرياضية المناسبة مع مراعاة الإشارات والاتجاهات.",
|
||||
'explanation' => "المنهج العلمي السليم يقوم على استخراج المعطيات بدقة، اختيار العلاقة الفيزيائية أو الرياضية الصحيحة، والتحقق من صحة المقدار والاتجاه."
|
||||
];
|
||||
|
||||
// Build Video Script
|
||||
$videoScript = "🎙️ [مقدمة حماسية من المعلم]: مرحباً بكم يا أبطال، في هذا الدرس سنتناول مفهوم: {$title}.\n"
|
||||
. "🎬 [العرض البصري]: ركزوا معي في هذا القانون والتطبيق العملي...\n"
|
||||
. "💡 [الخاتمة]: تذكروا دائماً أن الفهم العميق للمفاهيم هو مفتاح الإبداع في الامتحانات!";
|
||||
|
||||
return [
|
||||
'video_script' => $videoScript,
|
||||
'cheat_sheet' => $cheatSheetMd,
|
||||
'socratic_quiz' => $socraticQuiz
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,26 +63,44 @@ class CurriculumStudio
|
||||
max-height: calc(100vh - 120px); overflow-y: auto;
|
||||
}
|
||||
|
||||
.tree-node { margin-bottom: 14px; }
|
||||
.tree-node { margin-bottom: 12px; }
|
||||
.tree-header {
|
||||
font-size: 13px; font-weight: 800; color: var(--accent-gold); display: flex; align-items: center; gap: 6px;
|
||||
padding: 8px 12px; background: rgba(255, 209, 102, 0.08); border-radius: 10px; cursor: pointer;
|
||||
font-size: 13px; font-weight: 800; color: var(--accent-gold); display: flex; align-items: center; justify-content: space-between;
|
||||
padding: 10px 14px; background: rgba(255, 209, 102, 0.08); border-radius: 12px; cursor: pointer; user-select: none;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.tree-header:hover { background: rgba(255, 209, 102, 0.15); }
|
||||
|
||||
.tree-subject {
|
||||
font-size: 12.5px; font-weight: 700; color: var(--accent-cyan); margin: 6px 12px; padding: 4px 8px;
|
||||
cursor: pointer; display: flex; align-items: center; gap: 6px;
|
||||
font-size: 12.5px; font-weight: 700; color: var(--accent-cyan); margin: 6px 8px; padding: 8px 12px;
|
||||
background: rgba(0, 245, 212, 0.04); border-radius: 10px; cursor: pointer; user-select: none;
|
||||
display: flex; align-items: center; justify-content: space-between; transition: all 0.2s;
|
||||
}
|
||||
.tree-subject:hover { background: rgba(0, 245, 212, 0.1); }
|
||||
|
||||
.tree-unit {
|
||||
font-size: 12px; font-weight: 600; color: var(--text-secondary); margin: 4px 20px; padding: 3px 6px;
|
||||
font-size: 12px; font-weight: 600; color: var(--text-secondary); margin: 4px 14px; padding: 6px 10px;
|
||||
border-radius: 8px; cursor: pointer; user-select: none; display: flex; align-items: center; justify-content: space-between;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.tree-unit:hover { background: rgba(255, 255, 255, 0.06); color: #FFF; }
|
||||
|
||||
.tree-lesson {
|
||||
font-size: 11.5px; color: var(--text-muted); margin: 3px 30px; padding: 6px 10px; border-radius: 8px;
|
||||
cursor: pointer; transition: all 0.2s;
|
||||
font-size: 11.5px; color: var(--text-muted); margin: 3px 24px; padding: 6px 12px; border-radius: 8px;
|
||||
cursor: pointer; transition: all 0.2s; display: flex; align-items: center; gap: 8px;
|
||||
}
|
||||
.tree-lesson:hover, .tree-lesson.active {
|
||||
background: rgba(0, 245, 212, 0.15); color: var(--accent-cyan); font-weight: 700;
|
||||
}
|
||||
|
||||
.chevron {
|
||||
font-size: 10px; transition: transform 0.2s ease; display: inline-block; color: var(--text-muted);
|
||||
}
|
||||
.chevron.collapsed { transform: rotate(90deg); }
|
||||
|
||||
.collapsible-body { transition: all 0.2s ease; }
|
||||
.collapsible-body.hidden { display: none; }
|
||||
|
||||
.workspace-card {
|
||||
background: var(--bg-card); border: 1px solid var(--border); border-radius: 20px; padding: 26px;
|
||||
backdrop-filter: blur(16px);
|
||||
@@ -102,7 +120,7 @@ class CurriculumStudio
|
||||
.search-box:focus { border-color: var(--accent-cyan); }
|
||||
|
||||
.md-editor {
|
||||
width: 100%; height: 480px; background: rgba(0,0,0,0.5); border: 1px solid var(--border);
|
||||
width: 100%; height: 440px; background: rgba(0,0,0,0.5); border: 1px solid var(--border);
|
||||
border-radius: 14px; padding: 16px; color: #F1F5F9; font-family: monospace; font-size: 13px;
|
||||
line-height: 1.7; resize: vertical; outline: none;
|
||||
}
|
||||
@@ -197,31 +215,48 @@ class CurriculumStudio
|
||||
</div>
|
||||
|
||||
<!-- Markdown Content Area -->
|
||||
<textarea id="lesson_markdown_editor" class="md-editor" style="height: 400px; margin-bottom: 20px;"></textarea>
|
||||
<textarea id="lesson_markdown_editor" class="md-editor" style="margin-bottom: 20px;"></textarea>
|
||||
|
||||
<!-- الذكاء الاصطناعي والمخرجات الذكية -->
|
||||
<div style="background: rgba(255,255,255,0.02); border: 1px solid rgba(255,255,255,0.08); border-radius: 12px; padding: 20px;">
|
||||
<div style="background: rgba(255,255,255,0.02); border: 1px solid rgba(255,255,255,0.08); border-radius: 16px; padding: 20px;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; flex-wrap: wrap; gap: 10px;">
|
||||
<h4 style="color: var(--accent-gold); font-size: 16px; margin: 0;">🧠 الاستوديو الذكي للدرس (AI Assets)</h4>
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<h4 style="color: var(--accent-gold); font-size: 16px; margin: 0; display: flex; align-items: center; gap: 8px;">
|
||||
🧠 الاستوديو الذكي للدرس (AI Assets & Media)
|
||||
</h4>
|
||||
<div style="display: flex; gap: 8px; flex-wrap: wrap;">
|
||||
<button type="button" class="btn-primary" style="padding: 8px 14px; font-size: 12px; background: linear-gradient(135deg, #7B2CBF, #9D4EDD);" onclick="copyAiVideoPrompt()">🎬 نسخ برومبت فيديو الشرح</button>
|
||||
<button type="button" class="btn-primary" style="padding: 8px 14px; font-size: 12px;" onclick="generateAiAssets()">✨ توليد الملخص والاختبار آلياً</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 15px;">
|
||||
<label style="display: block; color: var(--text-secondary); margin-bottom: 8px; font-size: 13px;">رابط فيديو الشرح الذكي (مثلاً من NotebookLM أو YouTube):</label>
|
||||
<input type="text" id="ai_video_url_input" style="width: 100%; background: #0A0F1A; border: 1px solid rgba(255,255,255,0.1); color: #FFF; padding: 12px; border-radius: 8px; font-size: 14px;" placeholder="https://...">
|
||||
|
||||
<!-- Direct Video Upload / Attachment Section -->
|
||||
<div style="background: rgba(0,0,0,0.3); border: 1px solid var(--border); border-radius: 12px; padding: 14px; margin-bottom: 16px;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 10px;">
|
||||
<label style="color: var(--text-primary); font-size: 13px; font-weight: 700; display: flex; align-items: center; gap: 6px;">
|
||||
📹 فيديو شرح الدرس (مستضاف مباشرة على المنصة):
|
||||
</label>
|
||||
<div style="display: flex; gap: 8px; align-items: center;">
|
||||
<input type="file" id="direct_video_file_input" accept="video/mp4,video/webm,video/quicktime" style="display: none;" onchange="handleDirectVideoUpload(this)">
|
||||
<button type="button" class="btn-primary" style="padding: 6px 14px; font-size: 12px; background: linear-gradient(135deg, #10B981, #059669);" onclick="document.getElementById('direct_video_file_input').click()">
|
||||
📤 رفع ملف الفيديو مباشرة
|
||||
</button>
|
||||
<span id="video_upload_status" style="font-size: 11px; color: var(--accent-cyan);"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="text" id="ai_video_url_input" style="width: 100%; background: #0A0F1A; border: 1px solid rgba(255,255,255,0.1); color: #FFF; padding: 10px 14px; border-radius: 8px; font-size: 13px;" placeholder="رابط الفيديو المستضاف أو الخارجي (مثلاً /uploads/curriculum_videos/... أو رابط YouTube)">
|
||||
|
||||
<video id="lesson_video_player" controls style="width: 100%; max-height: 240px; border-radius: 10px; margin-top: 10px; display: none; background: #000; border: 1px solid var(--border);"></video>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; gap: 20px;">
|
||||
<div style="flex: 1;">
|
||||
<label style="display: block; color: var(--text-secondary); margin-bottom: 8px; font-size: 13px;">ملخص الدرس (Cheat Sheet):</label>
|
||||
<textarea id="ai_cheat_sheet_editor" style="width: 100%; height: 150px; background: #0A0F1A; border: 1px solid rgba(255,255,255,0.1); color: #FFF; padding: 12px; border-radius: 8px; font-size: 13px; font-family: monospace; direction: rtl;" placeholder="سيتم توليد الملخص والبطاقات التعليمية هنا..."></textarea>
|
||||
<div style="display: flex; gap: 20px; flex-wrap: wrap;">
|
||||
<div style="flex: 1; min-width: 280px;">
|
||||
<label style="display: block; color: var(--text-secondary); margin-bottom: 8px; font-size: 13px; font-weight: 600;">ملخص الدرس والبطاقة المركزة (Cheat Sheet):</label>
|
||||
<textarea id="ai_cheat_sheet_editor" style="width: 100%; height: 160px; background: #0A0F1A; border: 1px solid rgba(255,255,255,0.1); color: #FFF; padding: 12px; border-radius: 8px; font-size: 13px; font-family: monospace; direction: rtl; line-height: 1.6;" placeholder="سيتم توليد الملخص والبطاقات التعليمية هنا..."></textarea>
|
||||
</div>
|
||||
<div style="flex: 1;">
|
||||
<label style="display: block; color: var(--text-secondary); margin-bottom: 8px; font-size: 13px;">الفحص السقراطي (JSON):</label>
|
||||
<textarea id="ai_socratic_quiz_editor" style="width: 100%; height: 150px; background: #0A0F1A; border: 1px solid rgba(255,255,255,0.1); color: #FFF; padding: 12px; border-radius: 8px; font-size: 13px; font-family: monospace; direction: ltr; text-align: left;" placeholder="سيتم توليد سؤال الفحص السقراطي هنا..."></textarea>
|
||||
<div style="flex: 1; min-width: 280px;">
|
||||
<label style="display: block; color: var(--text-secondary); margin-bottom: 8px; font-size: 13px; font-weight: 600;">الفحص السقراطي الذكي (Socratic Quiz JSON):</label>
|
||||
<textarea id="ai_socratic_quiz_editor" style="width: 100%; height: 160px; background: #0A0F1A; border: 1px solid rgba(255,255,255,0.1); color: #FFF; padding: 12px; border-radius: 8px; font-size: 13px; font-family: monospace; direction: ltr; text-align: left; line-height: 1.6;" placeholder="سيتم توليد سؤال الفحص السقراطي هنا..."></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -269,6 +304,20 @@ class CurriculumStudio
|
||||
renderCurriculumTree(window.CURRICULUM_TREE);
|
||||
});
|
||||
|
||||
function toggleCollapsible(elementId, chevronId) {
|
||||
const body = document.getElementById(elementId);
|
||||
const chevron = document.getElementById(chevronId);
|
||||
if (!body) return;
|
||||
|
||||
if (body.classList.contains('hidden')) {
|
||||
body.classList.remove('hidden');
|
||||
if (chevron) chevron.classList.remove('collapsed');
|
||||
} else {
|
||||
body.classList.add('hidden');
|
||||
if (chevron) chevron.classList.add('collapsed');
|
||||
}
|
||||
}
|
||||
|
||||
function renderCurriculumTree(tree) {
|
||||
const container = document.getElementById('curriculum_tree_container');
|
||||
const entries = Object.entries(tree || {});
|
||||
@@ -287,18 +336,50 @@ class CurriculumStudio
|
||||
}
|
||||
|
||||
let html = '';
|
||||
let gradeIdx = 0;
|
||||
|
||||
for (const [gradeKey, grade] of entries) {
|
||||
gradeIdx++;
|
||||
const gradeBodyId = `grade_body_${gradeIdx}`;
|
||||
const gradeChevId = `grade_chev_${gradeIdx}`;
|
||||
|
||||
html += `
|
||||
<div class="tree-node">
|
||||
<div class="tree-header">📁 ${escapeHtml(grade.name)}</div>
|
||||
<div class="tree-header" onclick="toggleCollapsible('${gradeBodyId}', '${gradeChevId}')">
|
||||
<span>📁 ${escapeHtml(grade.name)}</span>
|
||||
<span class="chevron" id="${gradeChevId}">▼</span>
|
||||
</div>
|
||||
<div class="collapsible-body" id="${gradeBodyId}">
|
||||
`;
|
||||
|
||||
let subIdx = 0;
|
||||
for (const [subKey, sub] of Object.entries(grade.subjects || {})) {
|
||||
html += `<div class="tree-subject">📖 ${escapeHtml(sub.name)}</div>`;
|
||||
subIdx++;
|
||||
const subBodyId = `sub_body_${gradeIdx}_${subIdx}`;
|
||||
const subChevId = `sub_chev_${gradeIdx}_${subIdx}`;
|
||||
|
||||
html += `
|
||||
<div class="tree-subject" onclick="toggleCollapsible('${subBodyId}', '${subChevId}')">
|
||||
<span>📖 ${escapeHtml(sub.name)}</span>
|
||||
<span class="chevron" id="${subChevId}">▼</span>
|
||||
</div>
|
||||
<div class="collapsible-body" id="${subBodyId}">
|
||||
`;
|
||||
|
||||
for (const [semKey, sem] of Object.entries(sub.semesters || {})) {
|
||||
let unitIdx = 0;
|
||||
for (const [unitKey, unit] of Object.entries(sem.units || {})) {
|
||||
html += `<div class="tree-unit">🔹 ${escapeHtml(unit.name)}</div>`;
|
||||
unitIdx++;
|
||||
const unitBodyId = `unit_body_${gradeIdx}_${subIdx}_${unitIdx}`;
|
||||
const unitChevId = `unit_chev_${gradeIdx}_${subIdx}_${unitIdx}`;
|
||||
|
||||
html += `
|
||||
<div class="tree-unit" onclick="toggleCollapsible('${unitBodyId}', '${unitChevId}')">
|
||||
<span>🔹 ${escapeHtml(unit.name)}</span>
|
||||
<span class="chevron" id="${unitChevId}">▼</span>
|
||||
</div>
|
||||
<div class="collapsible-body" id="${unitBodyId}">
|
||||
`;
|
||||
|
||||
for (const les of (unit.lessons || [])) {
|
||||
const activeClass = (les.file === currentFilePath) ? ' active' : '';
|
||||
@@ -308,24 +389,19 @@ class CurriculumStudio
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
html += `</div>`;
|
||||
}
|
||||
|
||||
// Minhaji Style Categories
|
||||
if (sem.resources && Object.keys(sem.resources).length > 0) {
|
||||
html += `<div style="margin-top: 15px; margin-bottom: 5px; font-weight: bold; color: var(--text-secondary); font-size: 11px; padding-right: 15px;">📂 مصادر المادة الإضافية:</div>`;
|
||||
html += `<div style="display: flex; flex-wrap: wrap; gap: 6px; padding-right: 15px; margin-bottom: 10px;">`;
|
||||
html += `<div style="margin-top: 12px; margin-bottom: 5px; font-weight: bold; color: var(--text-secondary); font-size: 11px; padding-right: 15px;">📂 مصادر المادة والكتب:</div>`;
|
||||
html += `<div style="display: flex; flex-direction: column; gap: 4px; padding-right: 15px; margin-bottom: 10px;">`;
|
||||
for (const [resKey, resourceGroup] of Object.entries(sem.resources)) {
|
||||
if (!resourceGroup.items || resourceGroup.items.length === 0) continue;
|
||||
|
||||
html += `<div style="flex: 1 1 45%; background: var(--bg-hover); border: 1px solid var(--border-color); border-radius: 6px; padding: 8px; text-align: center; cursor: pointer; transition: all 0.2s;" onmouseover="this.style.background='rgba(255,209,102,0.1)'" onmouseout="this.style.background='var(--bg-hover)'">
|
||||
<div style="font-size: 14px; margin-bottom: 4px;">📌</div>
|
||||
<div style="font-size: 10px; font-weight: bold; color: var(--text-primary);">${escapeHtml(resourceGroup.name)}</div>
|
||||
</div>`;
|
||||
|
||||
for (const item of resourceGroup.items) {
|
||||
const activeClass = (item.file === currentFilePath) ? ' active' : '';
|
||||
html += `
|
||||
<div style="width: 100%;" class="tree-lesson${activeClass}" onclick="selectLesson('${item.file}', '${escapeHtml(item.title)}', '${escapeHtml(grade.name)} ⟵ ${escapeHtml(sub.name)} ⟵ ${escapeHtml(resourceGroup.name)}', ['مرفق إضافي'])">
|
||||
<div class="tree-lesson${activeClass}" onclick="selectLesson('${item.file}', '${escapeHtml(item.title)}', '${escapeHtml(grade.name)} ⟵ ${escapeHtml(sub.name)} ⟵ ${escapeHtml(resourceGroup.name)}', ['كتاب وزاري مقرّر'])">
|
||||
📎 ${escapeHtml(item.title)}
|
||||
</div>
|
||||
`;
|
||||
@@ -334,9 +410,9 @@ class CurriculumStudio
|
||||
html += `</div>`;
|
||||
}
|
||||
}
|
||||
html += `</div>`; // Close Subject Body
|
||||
}
|
||||
|
||||
html += `</div>`;
|
||||
html += `</div></div>`; // Close Grade Body & Node
|
||||
}
|
||||
|
||||
container.innerHTML = html;
|
||||
@@ -382,182 +458,108 @@ class CurriculumStudio
|
||||
if (data.server_full_path) {
|
||||
document.getElementById('server_file_path_display').textContent = data.server_full_path;
|
||||
}
|
||||
|
||||
// Load AI assets
|
||||
if (data.ai_assets) {
|
||||
document.getElementById('ai_video_url_input').value = data.ai_assets.ai_video_url || '';
|
||||
document.getElementById('ai_cheat_sheet_editor').value = data.ai_assets.cheat_sheet || '';
|
||||
document.getElementById('ai_socratic_quiz_editor').value = data.ai_assets.socratic_quiz ? JSON.stringify(data.ai_assets.socratic_quiz, null, 2) : '';
|
||||
|
||||
const player = document.getElementById('lesson_video_player');
|
||||
if (data.ai_assets.ai_video_url) {
|
||||
player.src = data.ai_assets.ai_video_url;
|
||||
player.style.display = 'block';
|
||||
} else {
|
||||
player.src = '';
|
||||
player.style.display = 'none';
|
||||
}
|
||||
} else {
|
||||
document.getElementById('ai_video_url_input').value = '';
|
||||
document.getElementById('ai_cheat_sheet_editor').value = '';
|
||||
document.getElementById('ai_socratic_quiz_editor').value = '';
|
||||
document.getElementById('lesson_video_player').style.display = 'none';
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Fetch markdown error:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================================
|
||||
// Live PDF Upload & Real-Time AI Extraction Tracking
|
||||
// ==========================================================
|
||||
async function handleRealPdfUpload(input) {
|
||||
if (!input.files || !input.files[0]) return;
|
||||
async function handleDirectVideoUpload(input) {
|
||||
if (!input.files || !input.files[0] || !currentFilePath) {
|
||||
alert('يرجى اختيار ملف فيديو صالح.');
|
||||
return;
|
||||
}
|
||||
const file = input.files[0];
|
||||
|
||||
const btn = document.getElementById('btn_upload_pdf');
|
||||
btn.disabled = true;
|
||||
|
||||
// Show Progress Modal Overlay
|
||||
const overlay = document.getElementById('upload_progress_overlay');
|
||||
overlay.style.display = 'flex';
|
||||
document.getElementById('btn_close_overlay').style.display = 'none';
|
||||
document.getElementById('upload_progress_bar').style.width = '8%';
|
||||
document.getElementById('upload_progress_text').textContent = `جاري رفع [${file.name}] إلى الخادم...`;
|
||||
document.getElementById('upload_progress_percent').textContent = '8%';
|
||||
document.getElementById('upload_logs_textarea').innerHTML = `[System] Uploading ${escapeHtml(file.name)} (${(file.size/1024/1024).toFixed(2)} MB)...<br>`;
|
||||
const statusSpan = document.getElementById('video_upload_status');
|
||||
statusSpan.textContent = `جاري رفع الفيديو (${(file.size/1024/1024).toFixed(1)} MB)...`;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('pdf_file', file);
|
||||
formData.append('video_file', file);
|
||||
formData.append('file', currentFilePath);
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/curriculum/upload-pdf', {
|
||||
const res = await fetch('/api/curriculum/upload-video', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
if (res.ok && data.status === 'processing') {
|
||||
currentUploadTaskId = data.task_id;
|
||||
document.getElementById('upload_progress_bar').style.width = '15%';
|
||||
document.getElementById('upload_progress_text').textContent = data.message || 'تم استلام الملف، جاري بدء الذكاء الاصطناعي...';
|
||||
document.getElementById('upload_progress_percent').textContent = '15%';
|
||||
appendLog(`[Server] Task registered with ID: ${data.task_id}`);
|
||||
pollTaskStatus(data.task_id, file.name);
|
||||
} else if (res.ok && data.status === 'success') {
|
||||
overlay.style.display = 'none';
|
||||
resetUploadBtn();
|
||||
loadCurriculumTree();
|
||||
if (res.ok && data.status === 'success') {
|
||||
document.getElementById('ai_video_url_input').value = data.video_url;
|
||||
const player = document.getElementById('lesson_video_player');
|
||||
player.src = data.video_url;
|
||||
player.style.display = 'block';
|
||||
statusSpan.textContent = '✅ تم رفع الفيديو بنجاح!';
|
||||
alert('✅ تم رفع وتثبيت الفيديو على سيرفر المنصة بنجاح!');
|
||||
} else {
|
||||
document.getElementById('upload_progress_text').textContent = '⚠️ ' + (data.message || 'فشلت معالجة الملف');
|
||||
document.getElementById('btn_close_overlay').style.display = 'inline-block';
|
||||
resetUploadBtn();
|
||||
statusSpan.textContent = '⚠️ فشل الرفع';
|
||||
alert('⚠️ ' + (data.message || 'فشل رفع ملف الفيديو'));
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('PDF Upload error:', err);
|
||||
document.getElementById('upload_progress_text').textContent = 'حدث خطأ في الاتصال بالخادم أثناء رفع الملف.';
|
||||
document.getElementById('btn_close_overlay').style.display = 'inline-block';
|
||||
resetUploadBtn();
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
statusSpan.textContent = '⚠️ خطأ بالاتصال';
|
||||
alert('حدث خطأ أثناء رفع الفيديو.');
|
||||
}
|
||||
}
|
||||
|
||||
async function pollTaskStatus(taskId, fileName) {
|
||||
try {
|
||||
const res = await fetch(`/api/curriculum/upload-status?task_id=${taskId}`);
|
||||
if (!res.ok) throw new Error("Network response was not ok");
|
||||
const state = await res.json();
|
||||
|
||||
// Live Update Modal
|
||||
document.getElementById('upload_progress_bar').style.width = (state.progress || 20) + '%';
|
||||
document.getElementById('upload_progress_percent').textContent = (state.progress || 20) + '%';
|
||||
document.getElementById('upload_progress_text').textContent = state.message || "جاري المعالجة بالذكاء الاصطناعي...";
|
||||
|
||||
fetchUploadLogs();
|
||||
|
||||
if (state.status === 'completed') {
|
||||
document.getElementById('upload_progress_bar').style.width = '100%';
|
||||
document.getElementById('upload_progress_percent').textContent = '100%';
|
||||
document.getElementById('upload_progress_text').textContent = `✅ اكتملت قراءة وتفريغ المنهاج بنجاح!`;
|
||||
|
||||
setTimeout(() => {
|
||||
document.getElementById('upload_progress_overlay').style.display = 'none';
|
||||
resetUploadBtn();
|
||||
if (state.tree) {
|
||||
window.CURRICULUM_TREE = state.tree;
|
||||
renderCurriculumTree(state.tree);
|
||||
if (state.active_file) {
|
||||
selectLesson(state.active_file, state.extracted_data?.subject_name || 'الدرس المستخرج', 'المنهاج المستخرج', []);
|
||||
}
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
}, 2000);
|
||||
} else if (state.status === 'error') {
|
||||
document.getElementById('upload_progress_text').textContent = '⚠️ فشل: ' + state.message;
|
||||
document.getElementById('btn_close_overlay').style.display = 'inline-block';
|
||||
resetUploadBtn();
|
||||
} else {
|
||||
// Poll again in 2.5 seconds
|
||||
setTimeout(() => pollTaskStatus(taskId, fileName), 2500);
|
||||
}
|
||||
} catch(e) {
|
||||
setTimeout(() => pollTaskStatus(taskId, fileName), 3000);
|
||||
async function generateAiAssets() {
|
||||
if (!currentFilePath) return;
|
||||
const content = document.getElementById('lesson_markdown_editor').value;
|
||||
if (!content) {
|
||||
alert('يجب أن يحتوي الدرس على نص أولاً');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchUploadLogs() {
|
||||
if (!currentUploadTaskId) return;
|
||||
const btn = window.event.currentTarget;
|
||||
const originalText = btn.innerHTML;
|
||||
btn.innerHTML = '⏳ جاري التوليد الذكي...';
|
||||
btn.disabled = true;
|
||||
|
||||
try {
|
||||
const res = await fetch(`/api/curriculum/upload-log?task_id=${currentUploadTaskId}`);
|
||||
const res = await fetch('/api/curriculum/generate-ai-assets', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ file: currentFilePath })
|
||||
});
|
||||
const data = await res.json();
|
||||
const container = document.getElementById('upload_logs_textarea');
|
||||
if (data.status === 'success' && data.log) {
|
||||
container.innerHTML = data.log.replace(/\n/g, '<br>');
|
||||
container.scrollTop = container.scrollHeight;
|
||||
|
||||
if (res.ok && data.status === 'success' && data.ai_assets) {
|
||||
document.getElementById('ai_cheat_sheet_editor').value = data.ai_assets.cheat_sheet || '';
|
||||
document.getElementById('ai_socratic_quiz_editor').value = data.ai_assets.socratic_quiz ? JSON.stringify(data.ai_assets.socratic_quiz, null, 2) : '';
|
||||
alert('✅ تم توليد الملخص والفحص السقراطي بنجاح!');
|
||||
} else {
|
||||
alert('⚠️ ' + (data.message || 'فشل التوليد'));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Fetch logs error:', e);
|
||||
console.error(e);
|
||||
alert('⚠️ حدث خطأ أثناء الاتصال بمحرك الذكاء الاصطناعي');
|
||||
} finally {
|
||||
btn.innerHTML = originalText;
|
||||
btn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
function appendLog(msg) {
|
||||
const container = document.getElementById('upload_logs_textarea');
|
||||
container.innerHTML += `${escapeHtml(msg)}<br>`;
|
||||
container.scrollTop = container.scrollHeight;
|
||||
}
|
||||
|
||||
function toggleUploadLogs() {
|
||||
const container = document.getElementById('upload_logs_container');
|
||||
container.style.display = (container.style.display === 'none') ? 'block' : 'none';
|
||||
if (container.style.display === 'block') {
|
||||
fetchUploadLogs();
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================================
|
||||
// 3. Status Polling & Overlay
|
||||
// ==========================================================
|
||||
let pollInterval;
|
||||
function checkStatus() {
|
||||
pollInterval = setInterval(async () => {
|
||||
const res = await fetch('/api/curriculum/status');
|
||||
const state = await res.json();
|
||||
|
||||
if (state.status === 'processing') {
|
||||
const pct = state.progress || 0;
|
||||
document.getElementById('upload_progress_fill').style.width = pct + '%';
|
||||
document.getElementById('upload_progress_text').textContent = state.message || 'جاري المعالجة...';
|
||||
} else if (state.status === 'done') {
|
||||
clearInterval(pollInterval);
|
||||
document.getElementById('upload_progress_fill').style.width = '100%';
|
||||
document.getElementById('upload_progress_text').textContent = '✅ اكتمل استخراج المنهاج بنجاح!';
|
||||
document.getElementById('btn_close_overlay').style.display = 'inline-block';
|
||||
resetUploadBtn();
|
||||
|
||||
setTimeout(() => {
|
||||
if (state.extracted_data) {
|
||||
renderTree(state.extracted_data);
|
||||
if (state.active_file) {
|
||||
selectLesson(state.active_file, state.extracted_data?.subject_name || 'الدرس المستخرج', 'المنهاج المستخرج', []);
|
||||
}
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
}, 2000);
|
||||
} else if (state.status === 'error') {
|
||||
document.getElementById('upload_progress_text').textContent = '⚠️ فشل: ' + state.message;
|
||||
document.getElementById('btn_close_overlay').style.display = 'inline-block';
|
||||
resetUploadBtn();
|
||||
} else {
|
||||
clearInterval(pollInterval);
|
||||
}
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
// ==========================================================
|
||||
// 4. Save Content
|
||||
// ==========================================================
|
||||
async function saveLessonContent() {
|
||||
async function saveActiveMarkdown() {
|
||||
if (!currentFilePath) return;
|
||||
const content = document.getElementById('lesson_markdown_editor').value;
|
||||
|
||||
@@ -586,66 +588,151 @@ class CurriculumStudio
|
||||
});
|
||||
const data = await res.json();
|
||||
if (res.ok && data.status === 'success') {
|
||||
alert(`✅ تم حفظ واعتماد التعديلات بنجاح في الملف:\n${data.server_full_path || currentFilePath}`);
|
||||
alert(`✅ تم حفظ واعتماد التعديلات بنجاح في المنهاج!`);
|
||||
} else {
|
||||
alert('⚠️ فشل حفظ الملف');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert('⚠️ حدث خطأ في الاتصال');
|
||||
alert('⚠️ حدث خطأ في الاتصال بالسيرفر');
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================================
|
||||
// 5. Generate AI Assets automatically
|
||||
// ==========================================================
|
||||
async function generateAiAssets() {
|
||||
if (!currentFilePath) return;
|
||||
const content = document.getElementById('lesson_markdown_editor').value;
|
||||
if (!content) {
|
||||
alert('يجب أن يحتوي الدرس على نص أولاً');
|
||||
function copyAiVideoPrompt() {
|
||||
const md = document.getElementById('lesson_markdown_editor').value;
|
||||
const title = document.getElementById('current_lesson_title_display').textContent;
|
||||
if (!md || md.trim() === '') {
|
||||
alert('يرجى اختيار درس أولاً.');
|
||||
return;
|
||||
}
|
||||
const prompt = `أنت معلم خبير في المنهاج الأردني. بناءً على محتوى الدرس التالي:
|
||||
عنوان الدرس: ${title}
|
||||
|
||||
const btn = window.event.currentTarget;
|
||||
const originalText = btn.innerHTML;
|
||||
btn.innerHTML = '⏳ جاري التوليد الذكي...';
|
||||
المحتوى التعليمي والتطبيقات:
|
||||
${md}
|
||||
|
||||
المطلوب:
|
||||
1. توليد سيناريو شرح فيديو تفاعلي شيق وممتع للدرس (مدته 3-5 دقائق).
|
||||
2. شرح فكرة الدرس والمفاهيم الأساسية، والخطوات الجبرية للأمثلة بالتفصيل.
|
||||
3. التنبيه على الأخطاء الشائعة وحل مسألة اليوم أو مهارات التفكير العليا.`;
|
||||
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
navigator.clipboard.writeText(prompt).then(() => {
|
||||
alert('🎬 تم نسخ برومبت توليد الفيديو بنجاح! يمكنك الآن لصقه في NotebookLM أو منصة توليد الفيديو الذكية.');
|
||||
}).catch(err => {
|
||||
copyViaTextarea(prompt);
|
||||
});
|
||||
} else {
|
||||
copyViaTextarea(prompt);
|
||||
}
|
||||
}
|
||||
|
||||
function copyViaTextarea(text) {
|
||||
const t = document.createElement('textarea');
|
||||
t.value = text;
|
||||
document.body.appendChild(t);
|
||||
t.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(t);
|
||||
alert('🎬 تم نسخ برومبت توليد الفيديو بنجاح!');
|
||||
}
|
||||
|
||||
// Real PDF Upload
|
||||
async function handleRealPdfUpload(input) {
|
||||
if (!input.files || !input.files[0]) return;
|
||||
const file = input.files[0];
|
||||
|
||||
const btn = document.getElementById('btn_upload_pdf');
|
||||
btn.disabled = true;
|
||||
|
||||
const overlay = document.getElementById('upload_progress_overlay');
|
||||
overlay.style.display = 'flex';
|
||||
document.getElementById('btn_close_overlay').style.display = 'none';
|
||||
document.getElementById('upload_progress_bar').style.width = '8%';
|
||||
document.getElementById('upload_progress_text').textContent = `جاري رفع [${file.name}] إلى الخادم...`;
|
||||
document.getElementById('upload_progress_percent').textContent = '8%';
|
||||
document.getElementById('upload_logs_textarea').innerHTML = `[System] Uploading ${escapeHtml(file.name)} (${(file.size/1024/1024).toFixed(2)} MB)...<br>`;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('pdf_file', file);
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/curriculum/generate-ai-assets', {
|
||||
const res = await fetch('/api/curriculum/upload-pdf', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ file: currentFilePath })
|
||||
body: formData
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
if (res.ok && data.status === 'success' && data.ai_assets) {
|
||||
document.getElementById('ai_cheat_sheet_editor').value = data.ai_assets.cheat_sheet || '';
|
||||
document.getElementById('ai_socratic_quiz_editor').value = data.ai_assets.socratic_quiz ? JSON.stringify(data.ai_assets.socratic_quiz, null, 2) : '';
|
||||
alert('✅ تم توليد الملخص والاختبار السقراطي بنجاح!');
|
||||
|
||||
if (res.ok && data.status === 'processing') {
|
||||
currentUploadTaskId = data.task_id;
|
||||
document.getElementById('upload_progress_bar').style.width = '15%';
|
||||
document.getElementById('upload_progress_text').textContent = data.message || 'تم استلام الملف، جاري بدء الذكاء الاصطناعي...';
|
||||
document.getElementById('upload_progress_percent').textContent = '15%';
|
||||
pollTaskStatus(data.task_id, file.name);
|
||||
} else if (res.ok && data.status === 'success') {
|
||||
overlay.style.display = 'none';
|
||||
resetUploadBtn();
|
||||
loadCurriculumTree();
|
||||
} else {
|
||||
alert('⚠️ فشل التوليد: ' + (data.message || 'خطأ غير معروف'));
|
||||
document.getElementById('upload_progress_text').textContent = '⚠️ ' + (data.message || 'فشلت معالجة الملف');
|
||||
document.getElementById('btn_close_overlay').style.display = 'inline-block';
|
||||
resetUploadBtn();
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert('⚠️ حدث خطأ في الاتصال بمحرك الذكاء الاصطناعي');
|
||||
} finally {
|
||||
btn.innerHTML = originalText;
|
||||
btn.disabled = false;
|
||||
} catch (err) {
|
||||
console.error('PDF Upload error:', err);
|
||||
document.getElementById('upload_progress_text').textContent = 'حدث خطأ في الاتصال بالخادم أثناء رفع الملف.';
|
||||
document.getElementById('btn_close_overlay').style.display = 'inline-block';
|
||||
resetUploadBtn();
|
||||
}
|
||||
}
|
||||
|
||||
async function pollTaskStatus(taskId, fileName) {
|
||||
try {
|
||||
const res = await fetch(`/api/curriculum/upload-status?task_id=${taskId}`);
|
||||
if (!res.ok) throw new Error("Network response was not ok");
|
||||
const state = await res.json();
|
||||
|
||||
const pBar = document.getElementById('upload_progress_bar');
|
||||
const pText = document.getElementById('upload_progress_text');
|
||||
const pPercent = document.getElementById('upload_progress_percent');
|
||||
|
||||
pBar.style.width = `${state.progress}%`;
|
||||
pPercent.textContent = `${state.progress}%`;
|
||||
pText.textContent = state.message || 'جاري المعالجة...';
|
||||
|
||||
if (state.status === 'completed') {
|
||||
pBar.style.width = '100%';
|
||||
pPercent.textContent = '100%';
|
||||
pText.textContent = `🎉 تم تفريغ واعتماد [${fileName}] كمنهاج حي بنجاح!`;
|
||||
document.getElementById('btn_close_overlay').style.display = 'inline-block';
|
||||
resetUploadBtn();
|
||||
setTimeout(() => {
|
||||
document.getElementById('upload_progress_overlay').style.display = 'none';
|
||||
window.location.reload();
|
||||
}, 1200);
|
||||
} else if (state.status === 'error') {
|
||||
pText.textContent = '❌ ' + (state.message || 'تعطلت عملية التفريغ.');
|
||||
document.getElementById('btn_close_overlay').style.display = 'inline-block';
|
||||
resetUploadBtn();
|
||||
} else {
|
||||
setTimeout(() => pollTaskStatus(taskId, fileName), 2000);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Status poll error:', err);
|
||||
setTimeout(() => pollTaskStatus(taskId, fileName), 3000);
|
||||
}
|
||||
}
|
||||
|
||||
function toggleUploadLogs() {
|
||||
const el = document.getElementById('upload_logs_container');
|
||||
el.style.display = (el.style.display === 'none') ? 'block' : 'none';
|
||||
}
|
||||
|
||||
function openDirectLogViewer() {
|
||||
const overlay = document.getElementById('upload_progress_overlay');
|
||||
overlay.style.display = 'flex';
|
||||
document.getElementById('btn_close_overlay').style.display = 'inline-block';
|
||||
document.getElementById('upload_logs_container').style.display = 'block';
|
||||
if (currentUploadTaskId) {
|
||||
fetchUploadLogs();
|
||||
} else {
|
||||
document.getElementById('upload_logs_textarea').innerHTML = '[System] No active task ID yet. Upload a textbook PDF to stream live AI logs.<br>';
|
||||
}
|
||||
}
|
||||
|
||||
function closeProgressOverlay() {
|
||||
@@ -660,27 +747,6 @@ class CurriculumStudio
|
||||
document.getElementById('curriculum_pdf_input').value = '';
|
||||
}
|
||||
|
||||
async function saveActiveMarkdown() {
|
||||
if (!currentFilePath) return;
|
||||
const content = document.getElementById('lesson_markdown_editor').value;
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/curriculum/save-lesson', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ file: currentFilePath, content: content })
|
||||
});
|
||||
const data = await res.json();
|
||||
if (res.ok && data.status === 'success') {
|
||||
alert(`✅ تم حفظ واعتماد التعديلات بنجاح في الملف:\n${data.server_full_path || currentFilePath}`);
|
||||
} else {
|
||||
alert('⚠️ فشل حفظ الملف');
|
||||
}
|
||||
} catch (e) {
|
||||
alert('تعذر الاتصال بالسيرفر');
|
||||
}
|
||||
}
|
||||
|
||||
function handleCurriculumSearch(q) {
|
||||
if (!q || q.trim() === '') {
|
||||
renderCurriculumTree(window.CURRICULUM_TREE);
|
||||
@@ -723,45 +789,6 @@ class CurriculumStudio
|
||||
renderCurriculumTree(filtered);
|
||||
}
|
||||
|
||||
function copyAiVideoPrompt() {
|
||||
const md = document.getElementById('lesson_markdown_editor').value;
|
||||
const title = document.getElementById('current_lesson_title').textContent;
|
||||
if (!md || md.trim() === '') {
|
||||
alert('يرجى اختيار درس أولاً.');
|
||||
return;
|
||||
}
|
||||
const prompt = `أنت معلم خبير في المنهاج الأردني. بناءً على محتوى الدرس التالي:
|
||||
عنوان الدرس: ${title}
|
||||
|
||||
المحتوى التعليمي والتطبيقات:
|
||||
${md}
|
||||
|
||||
المطلوب:
|
||||
1. توليد سيناريو شرح فيديو تفاعلي شيق وممتع للدرس (مدته 3-5 دقائق).
|
||||
2. شرح فكرة الدرس والمفاهيم الأساسية، والخطوات الجبرية للأمثلة بالتفصيل.
|
||||
3. التنبيه على الأخطاء الشائعة وحل مسألة اليوم أو مهارات التفكير العليا.`;
|
||||
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
navigator.clipboard.writeText(prompt).then(() => {
|
||||
alert('🎬 تم نسخ برومبت توليد الفيديو بنجاح! يمكنك الآن لصقه في NotebookLM أو منصة توليد الفيديو الذكية.');
|
||||
}).catch(err => {
|
||||
copyViaTextarea(prompt);
|
||||
});
|
||||
} else {
|
||||
copyViaTextarea(prompt);
|
||||
}
|
||||
}
|
||||
|
||||
function copyViaTextarea(text) {
|
||||
const t = document.createElement('textarea');
|
||||
t.value = text;
|
||||
document.body.appendChild(t);
|
||||
t.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(t);
|
||||
alert('🎬 تم نسخ برومبت توليد الفيديو بنجاح!');
|
||||
}
|
||||
|
||||
function escapeHtml(str) {
|
||||
if (!str) return '';
|
||||
const d = document.createElement('div');
|
||||
|
||||
@@ -63,6 +63,7 @@ $router->get('/api/curriculum/tree', [\App\Controllers\CurriculumControll
|
||||
$router->get('/api/curriculum/lesson', [\App\Controllers\CurriculumController::class, 'getLessonContent']);
|
||||
$router->post('/api/curriculum/save-lesson', [\App\Controllers\CurriculumController::class, 'saveLessonContent']);
|
||||
$router->post('/api/curriculum/generate-ai-assets', [\App\Controllers\CurriculumController::class, 'generateAiAssets']);
|
||||
$router->post('/api/curriculum/upload-video', [\App\Controllers\CurriculumController::class, 'uploadLessonVideo']);
|
||||
$router->get('/api/curriculum/search', function ($request, $response) {
|
||||
$q = $request->getQueryParams()['q'] ?? '';
|
||||
$response->json([
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/../app/bootstrap.php';
|
||||
require_once __DIR__ . '/curriculum_markdown_parser.php';
|
||||
|
||||
$metadata = [
|
||||
'grade_name' => 'الصف العاشر الأساسي (Grade 10)',
|
||||
'grade_key' => 'grade_10',
|
||||
'subject_name' => 'الفيزياء (Physics 10)',
|
||||
'subject_key' => 'physics_10',
|
||||
'semester_name' => 'الفصل الدراسي الأول',
|
||||
'semester_key' => 'semester_1'
|
||||
];
|
||||
|
||||
$u2 = file_get_contents(__DIR__ . '/unit2_physics_full.md');
|
||||
$res = parseAndIngestTextbookMarkdown($u2, $metadata);
|
||||
echo "SUCCESS! Ingested Grade 10 Physics Unit 2 (Motion and Forces)!\n";
|
||||
@@ -0,0 +1,178 @@
|
||||
# الوحدة الثانية: الحركة والقوى (Motion and Forces)
|
||||
*(الصفحات 33 - 85)*
|
||||
|
||||
## مقدمة الوحدة والتجربة الاستهلالية: وصف الحركة بالمدرج الهوائي
|
||||
|
||||
### الفكرة العامة ونتاجات التعلم للوحدة
|
||||
لدراسة حركة أي جسم، سواء أكان قريباً منا أم بعيداً في الفضاء، يتعين علينا وصف موقعه وسرعته وتسارعه والقوى المؤثرة فيه.
|
||||
|
||||
### ظاهرة حركة كرات البلياردو (صفحة 33)
|
||||
- **هل الحركة منتظمة؟** لا، لأن كرات البلياردو تتعرض لتصادَمات واحتكاك مستمر يُغيّر مقدار سرعتها واتجاهها، مما يُكسبها تسارعاً متغيراً وتكون حركتها غير منتظمة.
|
||||
|
||||
### التجربة الاستهلالية: وصف الحركة بالمدرج الهوائي (صفحة 35)
|
||||
- **السرعة المتوسطة:** $\bar{v} = \frac{\Delta x}{\Delta t}$.
|
||||
- **زيادة الكتلة المعلقة:** تزيد قوة السحب فيزداد التسارع وتقل المدة الزمنية وتزداد السرعة.
|
||||
- **التفكير الناقد:** إذا بدأ الجسم من السكون بتسارع ثابت، فإن السرعة النهائية ضعف السرعة المتوسطة: $v_f = 2\bar{v}$.
|
||||
|
||||
---
|
||||
|
||||
## الدرس 1: الحركة في بُعد واحد (Motion in One Dimension)
|
||||
*(الصفحات 36 - 56)*
|
||||
|
||||
- **فكرة الدرس:** وصف الحركة المستقيمة باستخدام الموقع، الإزاحة، السرعة (القياسية والمتجهة)، التسارع، والتمثيل البياني، ومعادلات الحركة بتسارع ثابت، والسقوط الحر.
|
||||
|
||||
### 1. الموقع والإزاحة والمسافة
|
||||
- **الموقع ($x$):** مكان وجود الجسم بالنسبة لنقطة إسناد مرجعية.
|
||||
- **الإزاحة ($\Delta x$):** $\Delta x = x_f - x_i$ (كمية متجهة).
|
||||
- **المسافة ($S$):** طول المسار الفعلي الكلي المقطوع (كمية قياسية موجبة دوماً).
|
||||
|
||||
### 2. السرعة القياسية والمتجهة
|
||||
- السرعة القياسية المتوسطة: $v_s = \frac{S}{\Delta t}$.
|
||||
- السرعة المتجهة المتوسطة: $\bar{v} = \frac{\Delta x}{\Delta t}$.
|
||||
|
||||
#### مثال 2 (حركة لعبة سيارة):
|
||||
- $x_1 = 2.0\text{ m}, x_2 = 6.8\text{ m}, x_3 = 5.6\text{ m}, \Delta t = 15\text{ s}$.
|
||||
- المسافة الكلية: $S = 4.8 + 1.2 = 6.0\text{ m} \implies v_s = \frac{6.0}{15} = 0.4\text{ m/s}$.
|
||||
- الإزاحة الكلية: $\Delta x = 5.6 - 2.0 = +3.6\text{ m} \implies \bar{v} = \frac{+3.6}{15} = +0.24\text{ m/s}$.
|
||||
|
||||
### 3. التسارع والتمثيل البياني
|
||||
- التسارع المتوسط: $\bar{a} = \frac{\Delta v}{\Delta t} = \frac{v_f - v_i}{t_f - t_i}$.
|
||||
- ميل منحنى (الموقع - الزمن): يمثل **السرعة المتجهة**.
|
||||
- ميل منحنى (السرعة - الزمن): يمثل **التسارع**.
|
||||
- المساحة تحت منحنى (السرعة - الزمن): تمثل **الإزاحة الكلية**.
|
||||
|
||||
### 4. معادلات الحركة بتسارع ثابت
|
||||
1. $v_f = v_i + a t$
|
||||
2. $\Delta x = v_i t + \frac{1}{2} a t^2$
|
||||
3. $v_f^2 = v_i^2 + 2 a \Delta x$
|
||||
|
||||
#### مثال 8 (دراجة نسرين من السكون $a=5\text{ m/s}^2, t=6.4\text{ s}$):
|
||||
- $v_f = 0 + (5)(6.4) = 32\text{ m/s}$.
|
||||
- $\Delta x = \frac{1}{2}(5)(6.4)^2 = 102.4\text{ m}$.
|
||||
|
||||
### 5. السقوط الحر (Free Fall)
|
||||
- حركة رأسية تحت تأثير الجاذبية فقط بتسارع $g = 9.8\text{ m/s}^2$ نحو الأسفل ($a = -g$).
|
||||
- عند أقصى ارتفاع: السرعة الرأسية اللحظية $v_{\text{top}} = 0$.
|
||||
|
||||
### أسئلة مراجعة الدرس الأول (صفحة 56):
|
||||
1) الحركة المنتظمة: سرعة متجهة ثابتة وتسارع صفر.
|
||||
2) قطار بسرعة $12\text{ m/s}$ لمدة $80\text{ s} \implies \Delta x = 960\text{ m}$.
|
||||
3) تسارع الصندوق: $a = \frac{1.2 - 0}{3} = 0.4\text{ m/s}^2$.
|
||||
4) منحنى الحصان: $\Delta x_a = 20\text{ m}, \bar{v}_b = 0.5\text{ m/s}$.
|
||||
5) منحنى العداء: $v(30\text{ s}) = 15\text{ m/s}, a_b = -0.75\text{ m/s}^2, \Delta x_{\text{total}} = 525\text{ m}$.
|
||||
6) سقوط من ارتفاع $176.4\text{ m} \implies t = 6.0\text{ s}, v_f = 58.8\text{ m/s}$ لأسفل.
|
||||
7) سرعة لحظية عند $t=2.5\text{ s} \implies v = 1.0\text{ m/s}$.
|
||||
|
||||
---
|
||||
|
||||
## الدرس 2: الحركة في بُعدين (Motion in Two Dimensions)
|
||||
*(الصفحات 57 - 66)*
|
||||
|
||||
- **فكرة الدرس:** حركة المقذوفات في مسار منحنٍ، والحركة الدائرية المنتظمة.
|
||||
|
||||
### 1. حركة المقذوفات (Projectiles)
|
||||
- **الحركة الأفقية ($x$):** سرعة ثابتة وتسارع صفر ($a_x = 0$): $v_x = v_0 \cos \theta, \Delta x = v_x t$.
|
||||
- **الحركة الرأسية ($y$):** تسارع سقوط حر ($a_y = -g$): $v_{0y} = v_0 \sin \theta, v_y = v_{0y} - g t$.
|
||||
- **القوانين الأساسية:**
|
||||
- زمن الصعود: $t_h = \frac{v_0 \sin \theta}{g}$
|
||||
- زمن التحليق: $T = 2 t_h = \frac{2 v_0 \sin \theta}{g}$
|
||||
- أقصى ارتفاع: $h = \frac{(v_0 \sin \theta)^2}{2g}$
|
||||
- المدى الأفقي: $R = \frac{v_0^2 \sin(2\theta)}{g}$ (أقصى مدى عند $\theta = 45^\circ$).
|
||||
|
||||
#### مثال 12 (ركل كرة بسرعة $22.5\text{ m/s}$ وزاوية $53^\circ$):
|
||||
- $v_{0x} = 13.5\text{ m/s}, v_{0y} = 18.0\text{ m/s}$.
|
||||
- $h = \frac{18^2}{19.6} \approx 16.5\text{ m}, T = \frac{2(18)}{9.8} \approx 3.68\text{ s}, R = (13.5)(3.68) \approx 49.7\text{ m}$.
|
||||
|
||||
### 2. الحركة الدائرية المنتظمة (Uniform Circular Motion)
|
||||
- سرعة قياسية مماسية ثابتة المقدار: $v_s = \frac{2\pi r}{T}$.
|
||||
- تسارع مركزي باتجاه مركز الدائرة: $a_c = \frac{v_s^2}{r} = \frac{4\pi^2 r}{T^2}$.
|
||||
|
||||
#### مثال 14 (قمر صناعي حول الأرض):
|
||||
- $r = 8.42 \times 10^6\text{ m}, T = 7740\text{ s} \implies v_s \approx 6832\text{ m/s}, a_c \approx 5.54\text{ m/s}^2$.
|
||||
|
||||
### أسئلة مراجعة الدرس الثاني (صفحة 66):
|
||||
1) أهمية التحليل: دراسة الحركة كحركتين مستقلتين في بعد واحد.
|
||||
2) أمثلة: المقذوفات (كرة السلة، المدفع)، الدائرية المنتظمة (عقارب الساعة، مدار الأقمار الصناعية).
|
||||
3) سبب وجود تسارع مركزي: تغير اتجاه السرعة نحو المركز.
|
||||
4) مقارنة المركبات الأفقية والرأسية (الإزاحة، السرعة، التسارع).
|
||||
5) قذف كرة بزاوية $30^\circ$ وبسرعة $15.8\text{ m/s} \implies T \approx 1.61\text{ s}, h \approx 3.18\text{ m}$.
|
||||
6) قذف أفقي من ارتفاع $44.1\text{ m} \implies t = 3.0\text{ s}, R = 36\text{ m}$.
|
||||
7) كتلة بخيط $r=0.8\text{ m}, T=1.0\text{ s} \implies v \approx 5.03\text{ m/s}, a_c \approx 31.6\text{ m/s}^2$.
|
||||
|
||||
---
|
||||
|
||||
## الدرس 3: قوانين الحركة لنيوتن (Newton's Laws of Motion)
|
||||
*(الصفحات 67 - 81)*
|
||||
|
||||
- **فكرة الدرس:** القصور الذاتي وقانون نيوتن الأول، القانون الثاني $\sum \vec{F} = m \vec{a}$، القانون الثالث (الفعل ورد الفعل $\vec{F}_{AB} = -\vec{F}_{BA}$)، وقانون الجذب العام.
|
||||
|
||||
### 1. القانون الأول لنيوتن والقصور الذاتي
|
||||
- الجسم الساكن يبقى ساكناً، والمتحرك بسرعة ثابتة يستمر بحركته ما لم تؤثر فيه قوة محصلة ($\sum \vec{F} = \vec{0} \iff \vec{a} = \vec{0}$).
|
||||
- **الكتلة ($m$):** المقياس الكمي للقصور الذاتي.
|
||||
|
||||
### 2. القانون الثاني لنيوتن
|
||||
- $\sum \vec{F} = m \vec{a}$، و $1\text{ N} = 1\text{ kg}\cdot\text{m/s}^2$.
|
||||
- مثال 17 (سحب سيارة $800\text{ kg}$ بقوة $1000\text{ N}$ واحتكاك $400\text{ N}$):
|
||||
$$\sum F = 600\text{ N} \implies a = \frac{600}{800} = 0.75\text{ m/s}^2 \implies v(10\text{ s}) = 7.5\text{ m/s}$$
|
||||
|
||||
### 3. القانون الثالث لنيوتن
|
||||
- لكل فعل رد فعل مساوٍ له في المقدار ومعاكس له في الاتجاه ($\vec{F}_{AB} = -\vec{F}_{BA}$).
|
||||
- تؤثران في جسمين مختلفين لذا لا تُلغي إحداهما الأخرى ولا تُحسب محصلتهما.
|
||||
|
||||
### 4. قانون الجذب العام لنيوتن
|
||||
- $F = G \frac{m_1 m_2}{r^2}$ حيث $G = 6.67 \times 10^{-11}\text{ N}\cdot\text{m}^2/\text{kg}^2$.
|
||||
- تسارع الجاذبية على سطح الكوكب: $g = G \frac{M}{R^2}$.
|
||||
- مثال 19: تسارع الجاذبية على سطح القمر $g_M \approx 1.62\text{ m/s}^2$.
|
||||
|
||||
### أسئلة مراجعة الدرس الثالث (صفحة 81):
|
||||
1) اتزان الجسم عندما $\sum \vec{F} = 0$، وأزواج القوى المتبادلة.
|
||||
2) سيارة بسرعة ثابتة وقوة محرك $6000\text{ N} \implies$ القوة المعيقة $6000\text{ N}$ للخلف.
|
||||
3) عربة تسوق $40\text{ kg} \implies \sum F = 80\text{ N}$؛ وبكتلة $60\text{ kg}$ واحتكاك $30\text{ N} \implies F_{\text{push}} = 150\text{ N}$.
|
||||
4) مناقشة قول يوسف: غير صحيح، فالجسم يستمر بحركته بفضل قصوره الذاتي دون الحاجة لقوة محصلة.
|
||||
5) تغير قوة الجذب: عند $2r \implies \frac{1}{4}F$؛ عند $2m_1 \implies 2F$؛ عند مضاعفة الكتلتين $\implies 4F$.
|
||||
6) تفكير ناقد: تحليل نظام الأرض والكرة بقوانين نيوتن الثلاثة والجذب العام.
|
||||
|
||||
---
|
||||
|
||||
## الإثراء والتوسع: حزام الأمان في السيارة (Seat Belts)
|
||||
*(صفحة 82)*
|
||||
|
||||
- **الأساس الفيزيائي:**
|
||||
1. **القصور الذاتي:** يمنع اندفاع الركاب للأمام عند التوقف المفاجئ والاصطدام.
|
||||
2. **آلية القفل التلقائي:** كتلة معلقة أو ساق منزلقة تتحرك بالقصور الذاتي أثناء التباطؤ الكبير وتُعشّق ترساً يمنع دوران البكرة ويثبّت الراكب بأمان.
|
||||
|
||||
---
|
||||
|
||||
## اختبار ومراجعة الوحدة الثانية: الحركة والقوى
|
||||
*(الصفحات 83 - 86)*
|
||||
|
||||
### أسئلة الاختيار من متعدد:
|
||||
1. التغير في الموقع: **جـ. الإزاحة**.
|
||||
2. المسافة الكلية / الزمن الكلي: **أ. السرعة القياسية المتوسطة**.
|
||||
3. عند أقصى ارتفاع للمقذوف الرأسي: **د. سرعته تساوي صفراً**.
|
||||
4. حركة المقذوف: **أ. التسارع الأفقي صفر، والرأسي $g$**.
|
||||
5. الإزاحة الأفقية عند العودة لنفس المستوى: **ب. المدى الأفقي**.
|
||||
6. انسكاب العصير عند الفرملة: **أ. من الجهة $A$ (نحو الأمام بالقصور الذاتي)**.
|
||||
7. ممانعة تغيير الحالة الحركية: **د. القصور الذاتي**.
|
||||
8. نقصان القوة للنصف مع ثبات الكتلة: **جـ. يقل التسارع بمقدار النصف**.
|
||||
9. الوزن على القمر أقل من الأرض: **أ. لأن كتلة القمر أقل من كتلة الأرض**.
|
||||
10. نقصان البعد إلى $0.8d \implies$ **د. $\frac{F}{0.64}$**.
|
||||
|
||||
### حل المسائل الحسابية والتفكير الناقد:
|
||||
- **سؤال 3 (دراجة هوائية):** $v_s = 36\text{ km/h} (10\text{ m/s})$، و $\bar{v} \approx 25.7\text{ km/h}$ بزاوية $37^\circ$ شمال الشرق.
|
||||
- **سؤال 4 (طول مدرج الطائرات):** $\Delta x = \frac{60^2}{2(2.4)} = 750\text{ m}$.
|
||||
- **سؤال 5 (زمن أقصى ارتفاع):** $t_h = \frac{98}{9.8} = 10\text{ s}$.
|
||||
- **سؤال 6 (تغير الزاوية إلى $45^\circ$):** يزداد المدى الأفقي بنسبة $15.5\%$ ليصل قيمته العظمى.
|
||||
- **سؤال 8 (عربتان):** العربة $B$ تؤثر فيها قوة أكبر لأن كتلتها أكبر وتسارعهما متساوٍ ($a_A = a_B$).
|
||||
- **سؤال 9 (فرملة سيارة $1000\text{ kg}$):** $a = -6\text{ m/s}^2 \implies \sum F = 6000\text{ N}$ بعكس اتجاه الحركة.
|
||||
- **سؤال 10 (قارب $200\text{ kg}$):** $R_x = 300\text{ N}, R_y = 0 \implies R = 300\text{ N} (+x), a_x = 1.5\text{ m/s}^2$.
|
||||
- **سؤال 11 (وزن على المشتري):** $g_J \approx 24.79\text{ m/s}^2 \implies F_g \approx 1487.4\text{ N}$.
|
||||
- **سؤال 12 (نقطة التعادل بين الأرض والقمر):** تبعد $3.6 \times 10^8\text{ m}$ عن مركز الأرض.
|
||||
- **سؤال 13 (منحنى $v-t$):** $v(1\text{ s}) = 1.0\text{ m/s}$، أكبر تسارع بالمرحلة $CD$ ($2.0\text{ m/s}^2$)، مسافة المرحلة $DE$ $= 1200\text{ m}$.
|
||||
|
||||
### أسئلة الاختبارات الدولية (كتاب الأنشطة - صفحات 33 - 35):
|
||||
1. سقوط الريشة والمطرقة: **ب. مقاومة الهواء في الأرض أثرت على الريشة، ولا يوجد هواء على القمر**.
|
||||
2. حركة الدراجة: **د. المسافة $100\text{ m}$ والإزاحة $20\text{ m}$**.
|
||||
3. هبوط طائرة $8\times 10^4\text{ kg}$: $a \approx -2.33\text{ m/s}^2, \sum F \approx 1.87 \times 10^5\text{ N}, \Delta x = 1050\text{ m}$.
|
||||
4. صاروخ $2\times 10^4\text{ kg}$: $\sum F = 2.04 \times 10^5\text{ N}, a = 10.2\text{ m/s}^2$ للأعلى.
|
||||
5. كتلة بالميزان النابضي: $\sum F = 0$ بالسرعة الثابتة، و $\sum F = 0.03\text{ N}$ عند التسارع $0.5\text{ m/s}^2$.
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
## الإثراء والتوسع: حزام الأمان في السيارة (Seat Belts)
|
||||
*(صفحة 82)*
|
||||
|
||||
- **الأساس الفيزيائي:**
|
||||
1. **القصور الذاتي:** يمنع اندفاع الركاب للأمام عند التوقف المفاجئ والاصطدام.
|
||||
2. **آلية القفل التلقائي:** كتلة معلقة أو ساق منزلقة تتحرك بالقصور الذاتي أثناء التباطؤ الكبير وتُعشّق ترساً يمنع دوران البكرة ويثبّت الراكب بأمان.
|
||||
|
||||
---
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
## مقدمة الوحدة والتجربة الاستهلالية: وصف الحركة بالمدرج الهوائي
|
||||
|
||||
### الفكرة العامة ونتاجات التعلم للوحدة
|
||||
لدراسة حركة أي جسم، سواء أكان قريباً منا أم بعيداً في الفضاء، يتعين علينا وصف موقعه وسرعته وتسارعه والقوى المؤثرة فيه.
|
||||
|
||||
### ظاهرة حركة كرات البلياردو (صفحة 33)
|
||||
- **هل الحركة منتظمة؟** لا، لأن كرات البلياردو تتعرض لتصادَمات واحتكاك مستمر يُغيّر مقدار سرعتها واتجاهها، مما يُكسبها تسارعاً متغيراً وتكون حركتها غير منتظمة.
|
||||
|
||||
### التجربة الاستهلالية: وصف الحركة بالمدرج الهوائي (صفحة 35)
|
||||
- **السرعة المتوسطة:** $\bar{v} = \frac{\Delta x}{\Delta t}$.
|
||||
- **زيادة الكتلة المعلقة:** تزيد قوة السحب فيزداد التسارع وتقل المدة الزمنية وتزداد السرعة.
|
||||
- **التفكير الناقد:** إذا بدأ الجسم من السكون بتسارع ثابت، فإن السرعة النهائية ضعف السرعة المتوسطة: $v_f = 2\bar{v}$.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,48 @@
|
||||
## الدرس 1: الحركة في بُعد واحد (Motion in One Dimension)
|
||||
*(الصفحات 36 - 56)*
|
||||
|
||||
- **فكرة الدرس:** وصف الحركة المستقيمة باستخدام الموقع، الإزاحة، السرعة (القياسية والمتجهة)، التسارع، والتمثيل البياني، ومعادلات الحركة بتسارع ثابت، والسقوط الحر.
|
||||
|
||||
### 1. الموقع والإزاحة والمسافة
|
||||
- **الموقع ($x$):** مكان وجود الجسم بالنسبة لنقطة إسناد مرجعية.
|
||||
- **الإزاحة ($\Delta x$):** $\Delta x = x_f - x_i$ (كمية متجهة).
|
||||
- **المسافة ($S$):** طول المسار الفعلي الكلي المقطوع (كمية قياسية موجبة دوماً).
|
||||
|
||||
### 2. السرعة القياسية والمتجهة
|
||||
- السرعة القياسية المتوسطة: $v_s = \frac{S}{\Delta t}$.
|
||||
- السرعة المتجهة المتوسطة: $\bar{v} = \frac{\Delta x}{\Delta t}$.
|
||||
|
||||
#### مثال 2 (حركة لعبة سيارة):
|
||||
- $x_1 = 2.0\text{ m}, x_2 = 6.8\text{ m}, x_3 = 5.6\text{ m}, \Delta t = 15\text{ s}$.
|
||||
- المسافة الكلية: $S = 4.8 + 1.2 = 6.0\text{ m} \implies v_s = \frac{6.0}{15} = 0.4\text{ m/s}$.
|
||||
- الإزاحة الكلية: $\Delta x = 5.6 - 2.0 = +3.6\text{ m} \implies \bar{v} = \frac{+3.6}{15} = +0.24\text{ m/s}$.
|
||||
|
||||
### 3. التسارع والتمثيل البياني
|
||||
- التسارع المتوسط: $\bar{a} = \frac{\Delta v}{\Delta t} = \frac{v_f - v_i}{t_f - t_i}$.
|
||||
- ميل منحنى (الموقع - الزمن): يمثل **السرعة المتجهة**.
|
||||
- ميل منحنى (السرعة - الزمن): يمثل **التسارع**.
|
||||
- المساحة تحت منحنى (السرعة - الزمن): تمثل **الإزاحة الكلية**.
|
||||
|
||||
### 4. معادلات الحركة بتسارع ثابت
|
||||
1. $v_f = v_i + a t$
|
||||
2. $\Delta x = v_i t + \frac{1}{2} a t^2$
|
||||
3. $v_f^2 = v_i^2 + 2 a \Delta x$
|
||||
|
||||
#### مثال 8 (دراجة نسرين من السكون $a=5\text{ m/s}^2, t=6.4\text{ s}$):
|
||||
- $v_f = 0 + (5)(6.4) = 32\text{ m/s}$.
|
||||
- $\Delta x = \frac{1}{2}(5)(6.4)^2 = 102.4\text{ m}$.
|
||||
|
||||
### 5. السقوط الحر (Free Fall)
|
||||
- حركة رأسية تحت تأثير الجاذبية فقط بتسارع $g = 9.8\text{ m/s}^2$ نحو الأسفل ($a = -g$).
|
||||
- عند أقصى ارتفاع: السرعة الرأسية اللحظية $v_{\text{top}} = 0$.
|
||||
|
||||
### أسئلة مراجعة الدرس الأول (صفحة 56):
|
||||
1) الحركة المنتظمة: سرعة متجهة ثابتة وتسارع صفر.
|
||||
2) قطار بسرعة $12\text{ m/s}$ لمدة $80\text{ s} \implies \Delta x = 960\text{ m}$.
|
||||
3) تسارع الصندوق: $a = \frac{1.2 - 0}{3} = 0.4\text{ m/s}^2$.
|
||||
4) منحنى الحصان: $\Delta x_a = 20\text{ m}, \bar{v}_b = 0.5\text{ m/s}$.
|
||||
5) منحنى العداء: $v(30\text{ s}) = 15\text{ m/s}, a_b = -0.75\text{ m/s}^2, \Delta x_{\text{total}} = 525\text{ m}$.
|
||||
6) سقوط من ارتفاع $176.4\text{ m} \implies t = 6.0\text{ s}, v_f = 58.8\text{ m/s}$ لأسفل.
|
||||
7) سرعة لحظية عند $t=2.5\text{ s} \implies v = 1.0\text{ m/s}$.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,35 @@
|
||||
## الدرس 2: الحركة في بُعدين (Motion in Two Dimensions)
|
||||
*(الصفحات 57 - 66)*
|
||||
|
||||
- **فكرة الدرس:** حركة المقذوفات في مسار منحنٍ، والحركة الدائرية المنتظمة.
|
||||
|
||||
### 1. حركة المقذوفات (Projectiles)
|
||||
- **الحركة الأفقية ($x$):** سرعة ثابتة وتسارع صفر ($a_x = 0$): $v_x = v_0 \cos \theta, \Delta x = v_x t$.
|
||||
- **الحركة الرأسية ($y$):** تسارع سقوط حر ($a_y = -g$): $v_{0y} = v_0 \sin \theta, v_y = v_{0y} - g t$.
|
||||
- **القوانين الأساسية:**
|
||||
- زمن الصعود: $t_h = \frac{v_0 \sin \theta}{g}$
|
||||
- زمن التحليق: $T = 2 t_h = \frac{2 v_0 \sin \theta}{g}$
|
||||
- أقصى ارتفاع: $h = \frac{(v_0 \sin \theta)^2}{2g}$
|
||||
- المدى الأفقي: $R = \frac{v_0^2 \sin(2\theta)}{g}$ (أقصى مدى عند $\theta = 45^\circ$).
|
||||
|
||||
#### مثال 12 (ركل كرة بسرعة $22.5\text{ m/s}$ وزاوية $53^\circ$):
|
||||
- $v_{0x} = 13.5\text{ m/s}, v_{0y} = 18.0\text{ m/s}$.
|
||||
- $h = \frac{18^2}{19.6} \approx 16.5\text{ m}, T = \frac{2(18)}{9.8} \approx 3.68\text{ s}, R = (13.5)(3.68) \approx 49.7\text{ m}$.
|
||||
|
||||
### 2. الحركة الدائرية المنتظمة (Uniform Circular Motion)
|
||||
- سرعة قياسية مماسية ثابتة المقدار: $v_s = \frac{2\pi r}{T}$.
|
||||
- تسارع مركزي باتجاه مركز الدائرة: $a_c = \frac{v_s^2}{r} = \frac{4\pi^2 r}{T^2}$.
|
||||
|
||||
#### مثال 14 (قمر صناعي حول الأرض):
|
||||
- $r = 8.42 \times 10^6\text{ m}, T = 7740\text{ s} \implies v_s \approx 6832\text{ m/s}, a_c \approx 5.54\text{ m/s}^2$.
|
||||
|
||||
### أسئلة مراجعة الدرس الثاني (صفحة 66):
|
||||
1) أهمية التحليل: دراسة الحركة كحركتين مستقلتين في بعد واحد.
|
||||
2) أمثلة: المقذوفات (كرة السلة، المدفع)، الدائرية المنتظمة (عقارب الساعة، مدار الأقمار الصناعية).
|
||||
3) سبب وجود تسارع مركزي: تغير اتجاه السرعة نحو المركز.
|
||||
4) مقارنة المركبات الأفقية والرأسية (الإزاحة، السرعة، التسارع).
|
||||
5) قذف كرة بزاوية $30^\circ$ وبسرعة $15.8\text{ m/s} \implies T \approx 1.61\text{ s}, h \approx 3.18\text{ m}$.
|
||||
6) قذف أفقي من ارتفاع $44.1\text{ m} \implies t = 3.0\text{ s}, R = 36\text{ m}$.
|
||||
7) كتلة بخيط $r=0.8\text{ m}, T=1.0\text{ s} \implies v \approx 5.03\text{ m/s}, a_c \approx 31.6\text{ m/s}^2$.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,32 @@
|
||||
## الدرس 3: قوانين الحركة لنيوتن (Newton's Laws of Motion)
|
||||
*(الصفحات 67 - 81)*
|
||||
|
||||
- **فكرة الدرس:** القصور الذاتي وقانون نيوتن الأول، القانون الثاني $\sum \vec{F} = m \vec{a}$، القانون الثالث (الفعل ورد الفعل $\vec{F}_{AB} = -\vec{F}_{BA}$)، وقانون الجذب العام.
|
||||
|
||||
### 1. القانون الأول لنيوتن والقصور الذاتي
|
||||
- الجسم الساكن يبقى ساكناً، والمتحرك بسرعة ثابتة يستمر بحركته ما لم تؤثر فيه قوة محصلة ($\sum \vec{F} = \vec{0} \iff \vec{a} = \vec{0}$).
|
||||
- **الكتلة ($m$):** المقياس الكمي للقصور الذاتي.
|
||||
|
||||
### 2. القانون الثاني لنيوتن
|
||||
- $\sum \vec{F} = m \vec{a}$، و $1\text{ N} = 1\text{ kg}\cdot\text{m/s}^2$.
|
||||
- مثال 17 (سحب سيارة $800\text{ kg}$ بقوة $1000\text{ N}$ واحتكاك $400\text{ N}$):
|
||||
$$\sum F = 600\text{ N} \implies a = \frac{600}{800} = 0.75\text{ m/s}^2 \implies v(10\text{ s}) = 7.5\text{ m/s}$$
|
||||
|
||||
### 3. القانون الثالث لنيوتن
|
||||
- لكل فعل رد فعل مساوٍ له في المقدار ومعاكس له في الاتجاه ($\vec{F}_{AB} = -\vec{F}_{BA}$).
|
||||
- تؤثران في جسمين مختلفين لذا لا تُلغي إحداهما الأخرى ولا تُحسب محصلتهما.
|
||||
|
||||
### 4. قانون الجذب العام لنيوتن
|
||||
- $F = G \frac{m_1 m_2}{r^2}$ حيث $G = 6.67 \times 10^{-11}\text{ N}\cdot\text{m}^2/\text{kg}^2$.
|
||||
- تسارع الجاذبية على سطح الكوكب: $g = G \frac{M}{R^2}$.
|
||||
- مثال 19: تسارع الجاذبية على سطح القمر $g_M \approx 1.62\text{ m/s}^2$.
|
||||
|
||||
### أسئلة مراجعة الدرس الثالث (صفحة 81):
|
||||
1) اتزان الجسم عندما $\sum \vec{F} = 0$، وأزواج القوى المتبادلة.
|
||||
2) سيارة بسرعة ثابتة وقوة محرك $6000\text{ N} \implies$ القوة المعيقة $6000\text{ N}$ للخلف.
|
||||
3) عربة تسوق $40\text{ kg} \implies \sum F = 80\text{ N}$؛ وبكتلة $60\text{ kg}$ واحتكاك $30\text{ N} \implies F_{\text{push}} = 150\text{ N}$.
|
||||
4) مناقشة قول يوسف: غير صحيح، فالجسم يستمر بحركته بفضل قصوره الذاتي دون الحاجة لقوة محصلة.
|
||||
5) تغير قوة الجذب: عند $2r \implies \frac{1}{4}F$؛ عند $2m_1 \implies 2F$؛ عند مضاعفة الكتلتين $\implies 4F$.
|
||||
6) تفكير ناقد: تحليل نظام الأرض والكرة بقوانين نيوتن الثلاثة والجذب العام.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,33 @@
|
||||
## اختبار ومراجعة الوحدة الثانية: الحركة والقوى
|
||||
*(الصفحات 83 - 86)*
|
||||
|
||||
### أسئلة الاختيار من متعدد:
|
||||
1. التغير في الموقع: **جـ. الإزاحة**.
|
||||
2. المسافة الكلية / الزمن الكلي: **أ. السرعة القياسية المتوسطة**.
|
||||
3. عند أقصى ارتفاع للمقذوف الرأسي: **د. سرعته تساوي صفراً**.
|
||||
4. حركة المقذوف: **أ. التسارع الأفقي صفر، والرأسي $g$**.
|
||||
5. الإزاحة الأفقية عند العودة لنفس المستوى: **ب. المدى الأفقي**.
|
||||
6. انسكاب العصير عند الفرملة: **أ. من الجهة $A$ (نحو الأمام بالقصور الذاتي)**.
|
||||
7. ممانعة تغيير الحالة الحركية: **د. القصور الذاتي**.
|
||||
8. نقصان القوة للنصف مع ثبات الكتلة: **جـ. يقل التسارع بمقدار النصف**.
|
||||
9. الوزن على القمر أقل من الأرض: **أ. لأن كتلة القمر أقل من كتلة الأرض**.
|
||||
10. نقصان البعد إلى $0.8d \implies$ **د. $\frac{F}{0.64}$**.
|
||||
|
||||
### حل المسائل الحسابية والتفكير الناقد:
|
||||
- **سؤال 3 (دراجة هوائية):** $v_s = 36\text{ km/h} (10\text{ m/s})$، و $\bar{v} \approx 25.7\text{ km/h}$ بزاوية $37^\circ$ شمال الشرق.
|
||||
- **سؤال 4 (طول مدرج الطائرات):** $\Delta x = \frac{60^2}{2(2.4)} = 750\text{ m}$.
|
||||
- **سؤال 5 (زمن أقصى ارتفاع):** $t_h = \frac{98}{9.8} = 10\text{ s}$.
|
||||
- **سؤال 6 (تغير الزاوية إلى $45^\circ$):** يزداد المدى الأفقي بنسبة $15.5\%$ ليصل قيمته العظمى.
|
||||
- **سؤال 8 (عربتان):** العربة $B$ تؤثر فيها قوة أكبر لأن كتلتها أكبر وتسارعهما متساوٍ ($a_A = a_B$).
|
||||
- **سؤال 9 (فرملة سيارة $1000\text{ kg}$):** $a = -6\text{ m/s}^2 \implies \sum F = 6000\text{ N}$ بعكس اتجاه الحركة.
|
||||
- **سؤال 10 (قارب $200\text{ kg}$):** $R_x = 300\text{ N}, R_y = 0 \implies R = 300\text{ N} (+x), a_x = 1.5\text{ m/s}^2$.
|
||||
- **سؤال 11 (وزن على المشتري):** $g_J \approx 24.79\text{ m/s}^2 \implies F_g \approx 1487.4\text{ N}$.
|
||||
- **سؤال 12 (نقطة التعادل بين الأرض والقمر):** تبعد $3.6 \times 10^8\text{ m}$ عن مركز الأرض.
|
||||
- **سؤال 13 (منحنى $v-t$):** $v(1\text{ s}) = 1.0\text{ m/s}$، أكبر تسارع بالمرحلة $CD$ ($2.0\text{ m/s}^2$)، مسافة المرحلة $DE$ $= 1200\text{ m}$.
|
||||
|
||||
### أسئلة الاختبارات الدولية (كتاب الأنشطة - صفحات 33 - 35):
|
||||
1. سقوط الريشة والمطرقة: **ب. مقاومة الهواء في الأرض أثرت على الريشة، ولا يوجد هواء على القمر**.
|
||||
2. حركة الدراجة: **د. المسافة $100\text{ m}$ والإزاحة $20\text{ m}$**.
|
||||
3. هبوط طائرة $8\times 10^4\text{ kg}$: $a \approx -2.33\text{ m/s}^2, \sum F \approx 1.87 \times 10^5\text{ N}, \Delta x = 1050\text{ m}$.
|
||||
4. صاروخ $2\times 10^4\text{ kg}$: $\sum F = 2.04 \times 10^5\text{ N}, a = 10.2\text{ m/s}^2$ للأعلى.
|
||||
5. كتلة بالميزان النابضي: $\sum F = 0$ بالسرعة الثابتة، و $\sum F = 0.03\text{ N}$ عند التسارع $0.5\text{ m/s}^2$.
|
||||
@@ -571,8 +571,57 @@
|
||||
]
|
||||
},
|
||||
"unit_02": {
|
||||
"name": "الوحدة الثانية: الحركة والقوة (Motion and Forces) — (الصفحات 33 - 85)",
|
||||
"lessons": []
|
||||
"name": "الوحدة الثانية: الحركة والقوى (Motion and Forces)",
|
||||
"lessons": [
|
||||
{
|
||||
"id": "intro_and_project",
|
||||
"title": "مقدمة الوحدة والتجربة الاستهلالية: وصف الحركة بالمدرج الهوائي",
|
||||
"outcomes": [
|
||||
"مقدمة الوحدة والتجربة الاستهلالية: وصف الحركة بالمدرج الهوائي"
|
||||
],
|
||||
"file": "grade_10\/physics_10\/semester_1\/unit_02\/intro_and_project.md"
|
||||
},
|
||||
{
|
||||
"id": "lesson_01",
|
||||
"title": "الدرس 1: الحركة في بُعد واحد (Motion in One Dimension)",
|
||||
"outcomes": [
|
||||
"الدرس 1: الحركة في بُعد واحد (Motion in One Dimension)"
|
||||
],
|
||||
"file": "grade_10\/physics_10\/semester_1\/unit_02\/lesson_01.md"
|
||||
},
|
||||
{
|
||||
"id": "lesson_02",
|
||||
"title": "الدرس 2: الحركة في بُعدين (Motion in Two Dimensions)",
|
||||
"outcomes": [
|
||||
"الدرس 2: الحركة في بُعدين (Motion in Two Dimensions)"
|
||||
],
|
||||
"file": "grade_10\/physics_10\/semester_1\/unit_02\/lesson_02.md"
|
||||
},
|
||||
{
|
||||
"id": "lesson_03",
|
||||
"title": "الدرس 3: قوانين الحركة لنيوتن (Newton's Laws of Motion)",
|
||||
"outcomes": [
|
||||
"الدرس 3: قوانين الحركة لنيوتن (Newton's Laws of Motion)"
|
||||
],
|
||||
"file": "grade_10\/physics_10\/semester_1\/unit_02\/lesson_03.md"
|
||||
},
|
||||
{
|
||||
"id": "enrichment_and_expansion",
|
||||
"title": "الإثراء والتوسع: حزام الأمان في السيارة (Seat Belts)",
|
||||
"outcomes": [
|
||||
"الإثراء والتوسع: حزام الأمان في السيارة (Seat Belts)"
|
||||
],
|
||||
"file": "grade_10\/physics_10\/semester_1\/unit_02\/enrichment_and_expansion.md"
|
||||
},
|
||||
{
|
||||
"id": "unit_exam",
|
||||
"title": "اختبار ومراجعة الوحدة الثانية: الحركة والقوى",
|
||||
"outcomes": [
|
||||
"اختبار ومراجعة الوحدة الثانية: الحركة والقوى"
|
||||
],
|
||||
"file": "grade_10\/physics_10\/semester_1\/unit_02\/unit_exam.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
|
||||
Reference in New Issue
Block a user