Fix student_question_answers table creation, clean manifest duplicate units, and calibrate Socratic timeline seeking
This commit is contained in:
@@ -157,6 +157,8 @@ class ExamController
|
||||
: "تحتاج لمراجعة المفاهيم المتعلقة بـ: " . 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),
|
||||
@@ -171,13 +173,17 @@ class ExamController
|
||||
[$uuid, $studentId, $examId, $earnedScore, $totalPoints, $percentage, $status, $timeSpent, json_encode(array_keys($weakTopics), JSON_UNESCAPED_UNICODE), $aiReport]
|
||||
);
|
||||
|
||||
// Save detailed question answers
|
||||
// Save detailed question answers safely
|
||||
foreach ($detailedAnswers as $dAns) {
|
||||
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]
|
||||
);
|
||||
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
|
||||
@@ -318,4 +324,37 @@ class ExamController
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,67 +8,6 @@
|
||||
"semester_1": {
|
||||
"name": "الفصل الدراسي الأول",
|
||||
"units": {
|
||||
"unit_01_exponents_equations": {
|
||||
"name": "الوحدة الأولى: الأسس والمعادلات",
|
||||
"lessons": [
|
||||
{
|
||||
"id": "u1_l1_solving_equations",
|
||||
"title": "الدرس 1: حل نظام مكون من معادلة خطية ومعادلة تربيعية",
|
||||
"outcomes": [
|
||||
"حل نظام معادلات",
|
||||
"التمثيل البياني"
|
||||
],
|
||||
"file": "grade_10\/math_10\/semester_1\/unit_01\/lesson_1.md"
|
||||
},
|
||||
{
|
||||
"id": "u1_l2_solving_quadratic_system",
|
||||
"title": "الدرس 2: حل نظام مكون من معادلتين تربيعيتين",
|
||||
"outcomes": [
|
||||
"استخدام التعويض",
|
||||
"استخدام الحذف"
|
||||
],
|
||||
"file": "grade_10\/math_10\/semester_1\/unit_01\/lesson_2.md"
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit_02_circle": {
|
||||
"name": "الوحدة الثانية: الدائرة",
|
||||
"lessons": [
|
||||
{
|
||||
"id": "u2_l1_circle_properties",
|
||||
"title": "الدرس 1: أوتار الدائرة وأقطارها ومماساتها",
|
||||
"outcomes": [
|
||||
"نظريات الدائرة",
|
||||
"تطبيقات المماسات"
|
||||
],
|
||||
"file": "grade_10\/math_10\/semester_1\/unit_02\/lesson_1.md"
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit_03_trigonometry": {
|
||||
"name": "الوحدة الثالثة: حساب المثلثات",
|
||||
"lessons": []
|
||||
},
|
||||
"unit_04_trig_apps": {
|
||||
"name": "الوحدة الرابعة: تطبيقات المثلثات",
|
||||
"lessons": []
|
||||
},
|
||||
"unit_05_functions": {
|
||||
"name": "الوحدة الخامسة: الاقترانات",
|
||||
"lessons": []
|
||||
},
|
||||
"unit_06_derivatives": {
|
||||
"name": "الوحدة السادسة: المشتقات",
|
||||
"lessons": []
|
||||
},
|
||||
"unit_07_vectors": {
|
||||
"name": "الوحدة السابعة: المتجهات",
|
||||
"lessons": []
|
||||
},
|
||||
"unit_08_stats": {
|
||||
"name": "الوحدة الثامنة: الإحصاء والاحتمالات",
|
||||
"lessons": []
|
||||
},
|
||||
"unit_01": {
|
||||
"name": "الوحدة الأولى: المعادلات (Equations)",
|
||||
"lessons": [
|
||||
|
||||
Reference in New Issue
Block a user