Update Saqel Platform: 2026-09-08 18:19:28
This commit is contained in:
@@ -42,6 +42,7 @@ class VideoController
|
||||
$courseId = (int)($request->getBody()['course_id'] ?? $_POST['course_id'] ?? 0);
|
||||
$title = trim((string)($request->getBody()['title'] ?? $_POST['title'] ?? ''));
|
||||
$seqOrder = (int)($request->getBody()['sequence_order'] ?? $_POST['sequence_order'] ?? 1);
|
||||
$curriculumKey = trim((string)($request->getBody()['curriculum_key'] ?? $_POST['curriculum_key'] ?? ''));
|
||||
|
||||
if (empty($title)) {
|
||||
$response->status(400)->json([
|
||||
@@ -64,13 +65,19 @@ class VideoController
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$existingCourse = Database::selectOne("SELECT id, teacher_id FROM courses WHERE teacher_id = ? LIMIT 1", [$request->user_id]);
|
||||
$subjectName = trim((string)($request->getBody()['subject'] ?? $_POST['subject'] ?? ''));
|
||||
$gradeLevel = trim((string)($request->getBody()['grade_level'] ?? $_POST['grade_level'] ?? ''));
|
||||
$existingCourse = Database::selectOne(
|
||||
"SELECT c.id, c.teacher_id FROM courses c
|
||||
JOIN subjects s ON s.id = c.subject_id
|
||||
WHERE c.teacher_id = ? AND c.grade_level = ? AND (s.name_ar = ? OR s.name_en = ?)
|
||||
LIMIT 1",
|
||||
[$request->user_id, $gradeLevel, $subjectName, $subjectName]
|
||||
);
|
||||
if ($existingCourse) {
|
||||
$courseId = (int)$existingCourse['id'];
|
||||
$course = $existingCourse;
|
||||
} else {
|
||||
$subjectName = trim((string)($request->getBody()['subject'] ?? $_POST['subject'] ?? ''));
|
||||
$gradeLevel = trim((string)($request->getBody()['grade_level'] ?? $_POST['grade_level'] ?? ''));
|
||||
$subject = Database::selectOne(
|
||||
"SELECT id FROM subjects WHERE name_ar = ? OR name_en = ? ORDER BY id LIMIT 1",
|
||||
[$subjectName, $subjectName]
|
||||
@@ -121,11 +128,12 @@ class VideoController
|
||||
|
||||
// Insert lesson record with HLS references
|
||||
$lessonId = Database::insert(
|
||||
"INSERT INTO lessons (course_id, title, sequence_order, storage_type, video_uuid, bunny_video_id, local_path, hls_url, thumbnail_url, duration_seconds, is_free_preview, encoding_status)
|
||||
VALUES (?, ?, ?, 'api_upload', ?, '', ?, ?, ?, ?, 0, 'ready')",
|
||||
"INSERT INTO lessons (course_id, title, curriculum_key, sequence_order, storage_type, video_uuid, bunny_video_id, local_path, hls_url, thumbnail_url, duration_seconds, is_free_preview, encoding_status)
|
||||
VALUES (?, ?, ?, ?, 'api_upload', ?, '', ?, ?, ?, ?, 0, 'ready')",
|
||||
[
|
||||
$courseId,
|
||||
$title,
|
||||
$curriculumKey !== '' ? $curriculumKey : null,
|
||||
$seqOrder,
|
||||
$uploadResult['video_uuid'],
|
||||
$uploadResult['local_path'],
|
||||
|
||||
@@ -78,7 +78,7 @@ class AiVideoAnalyzerService
|
||||
$report = json_decode($text, true);
|
||||
if ($code !== 200 || !is_array($report) || !in_array($report['decision'] ?? '', ['approved','needs_manual_review','rejected'], true)) throw new \RuntimeException('استجابة Gemini غير صالحة');
|
||||
$report['duration_seconds'] = $duration;
|
||||
if (($report['visual_clarity_score'] ?? 0) < 70 || ($report['pedagogical_readiness_score'] ?? 0) < 70) $report['decision'] = 'needs_manual_review';
|
||||
if (($report['visual_clarity_score'] ?? 0) < 85 || ($report['pedagogical_readiness_score'] ?? 0) < 85) $report['decision'] = 'needs_manual_review';
|
||||
return $report;
|
||||
} catch (\Throwable $e) {
|
||||
return ['decision' => 'needs_manual_review', 'reason' => 'تعذر إكمال تحليل Gemini؛ لم يتم رفع الفيديو'];
|
||||
|
||||
@@ -52,19 +52,19 @@ class TeacherRatingService
|
||||
Database::query("
|
||||
CREATE TABLE teacher_performance_metrics (
|
||||
teacher_id BIGINT UNSIGNED PRIMARY KEY,
|
||||
avg_response_minutes INT DEFAULT 4,
|
||||
response_rate_percentage DECIMAL(5, 2) DEFAULT 98.50,
|
||||
avg_response_minutes INT DEFAULT 0,
|
||||
response_rate_percentage DECIMAL(5, 2) DEFAULT 0,
|
||||
active_queue_count INT UNSIGNED DEFAULT 0,
|
||||
total_students_enrolled INT DEFAULT 0,
|
||||
total_reviews_count INT DEFAULT 0,
|
||||
raw_avg_rating DECIMAL(3, 2) DEFAULT 5.00,
|
||||
weighted_student_rating DECIMAL(3, 2) DEFAULT 5.00,
|
||||
ai_engagement_score DECIMAL(5, 2) DEFAULT 96.00,
|
||||
sla_speed_score DECIMAL(5, 2) DEFAULT 98.00,
|
||||
mastery_impact_score DECIMAL(5, 2) DEFAULT 94.00,
|
||||
composite_merit_score DECIMAL(5, 2) DEFAULT 96.50,
|
||||
star_equivalent DECIMAL(3, 2) DEFAULT 4.90,
|
||||
reputation_tier VARCHAR(100) DEFAULT 'معلم نخبوي معتمد 💎',
|
||||
raw_avg_rating DECIMAL(3, 2) DEFAULT 0,
|
||||
weighted_student_rating DECIMAL(3, 2) DEFAULT 0,
|
||||
ai_engagement_score DECIMAL(5, 2) DEFAULT 0,
|
||||
sla_speed_score DECIMAL(5, 2) DEFAULT 0,
|
||||
mastery_impact_score DECIMAL(5, 2) DEFAULT 0,
|
||||
composite_merit_score DECIMAL(5, 2) DEFAULT 0,
|
||||
star_equivalent DECIMAL(3, 2) DEFAULT 0,
|
||||
reputation_tier VARCHAR(100) DEFAULT 'بانتظار بيانات الأداء',
|
||||
last_calculated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT fk_tpm_teacher FOREIGN KEY (teacher_id) REFERENCES teachers(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -308,10 +308,6 @@ class TeacherRatingService
|
||||
]
|
||||
);
|
||||
|
||||
if ($studentsCount <= 0) {
|
||||
$studentsCount = 83;
|
||||
}
|
||||
|
||||
return [
|
||||
'teacher_id' => $teacherId,
|
||||
'composite_merit_score' => $compositeScore,
|
||||
@@ -327,12 +323,12 @@ class TeacherRatingService
|
||||
'sla_speed_score' => $slaComponent,
|
||||
'mastery_impact_score' => $masteryComponent,
|
||||
'ai_engagement_score' => $aiEngagementScore,
|
||||
'success_rate_percentage' => 98.2,
|
||||
'curriculum_alignment_pct' => 96.0,
|
||||
'socratic_interaction_pct' => 89.0,
|
||||
'audio_clarity_pct' => 94.0,
|
||||
'cognitive_focus_pct' => 92.0,
|
||||
'ai_recommendation' => 'توجيه الذكاء الاصطناعي الأسبوعي: نسبة الالتزام الوزاري ممتازة (96%). يُوصى بإضافة وقفة سقراطية استنتاجية في الدقيقة 14 من الدرس القادم لتعزيز تفاعل الطلبة.'
|
||||
'success_rate_percentage' => 0.0,
|
||||
'curriculum_alignment_pct' => 0.0,
|
||||
'socratic_interaction_pct' => 0.0,
|
||||
'audio_clarity_pct' => 0.0,
|
||||
'cognitive_focus_pct' => 0.0,
|
||||
'ai_recommendation' => 'ستظهر التوصية بعد توفر حصص محللة وتفاعل فعلي من الطلبة.'
|
||||
];
|
||||
}
|
||||
|
||||
@@ -419,7 +415,7 @@ class TeacherRatingService
|
||||
}
|
||||
} catch (\Throwable $e) {}
|
||||
|
||||
return 94.50;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -431,11 +427,11 @@ class TeacherRatingService
|
||||
|
||||
$teachers = Database::select(
|
||||
"SELECT t.id, t.full_name, t.specialization, t.bio,
|
||||
COALESCE(m.avg_response_minutes, 3) as avg_response_minutes,
|
||||
COALESCE(m.response_rate_percentage, 99.0) as response_rate_percentage,
|
||||
COALESCE(m.composite_merit_score, 96.50) as composite_merit_score,
|
||||
COALESCE(m.star_equivalent, 4.90) as star_equivalent,
|
||||
COALESCE(m.reputation_tier, 'معلم نخبوي معتمد 💎') as reputation_tier,
|
||||
COALESCE(m.avg_response_minutes, 0) as avg_response_minutes,
|
||||
COALESCE(m.response_rate_percentage, 0) as response_rate_percentage,
|
||||
COALESCE(m.composite_merit_score, 0) as composite_merit_score,
|
||||
COALESCE(m.star_equivalent, 0) as star_equivalent,
|
||||
COALESCE(m.reputation_tier, 'بانتظار بيانات الأداء') as reputation_tier,
|
||||
(SELECT COUNT(*) FROM lessons WHERE course_id IN (SELECT id FROM courses WHERE teacher_id = t.id)) as lessons_count
|
||||
FROM teachers t
|
||||
LEFT JOIN teacher_performance_metrics m ON t.id = m.teacher_id
|
||||
|
||||
Reference in New Issue
Block a user