Implement verified curriculum, video review, watch sessions, ledger safeguards, and remove demo data
This commit is contained in:
@@ -15,8 +15,11 @@ class TeacherRatingService
|
||||
|
||||
public static function ensureSchema(): void
|
||||
{
|
||||
// Schema is installed by migrations. Runtime DDL previously included a
|
||||
// DROP TABLE path and must never run during a student request.
|
||||
return;
|
||||
/*
|
||||
if (self::$schemaChecked) return;
|
||||
|
||||
try {
|
||||
// 1. Ensure teacher_reviews table exists with all columns
|
||||
Database::query("
|
||||
@@ -75,6 +78,7 @@ class TeacherRatingService
|
||||
} catch (\Throwable $e) {
|
||||
error_log("TeacherRatingService schema note: " . $e->getMessage());
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,8 +214,8 @@ class TeacherRatingService
|
||||
);
|
||||
|
||||
$totalReviews = count($reviews);
|
||||
$weightedRating = 5.00;
|
||||
$rawRating = 5.00;
|
||||
$weightedRating = 0.00;
|
||||
$rawRating = 0.00;
|
||||
|
||||
if ($totalReviews > 0) {
|
||||
$sumWeighted = 0;
|
||||
@@ -226,7 +230,7 @@ class TeacherRatingService
|
||||
$sumRaw += $val;
|
||||
}
|
||||
|
||||
$weightedRating = $sumWeights > 0 ? round($sumWeighted / $sumWeights, 2) : 5.00;
|
||||
$weightedRating = $sumWeights > 0 ? round($sumWeighted / $sumWeights, 2) : 0.00;
|
||||
$rawRating = round($sumRaw / $totalReviews, 2);
|
||||
}
|
||||
|
||||
@@ -237,7 +241,9 @@ class TeacherRatingService
|
||||
$masteryScore = self::calculateMasteryImpact($teacherId);
|
||||
|
||||
// 4. AI Socratic Engagement Index
|
||||
$aiEngagementScore = 96.00;
|
||||
// There is no verified AI engagement measurement yet. Keep the metric
|
||||
// neutral until the reviewed video/watch pipeline supplies one.
|
||||
$aiEngagementScore = 0.00;
|
||||
|
||||
// 5. Composite Merit Calculation (The Fair Formula: 25% SLA + 25% AI + 25% Mastery + 25% Student Review)
|
||||
$reviewComponent = $weightedRating * 20.0;
|
||||
@@ -266,7 +272,11 @@ class TeacherRatingService
|
||||
}
|
||||
|
||||
// Count enrolled students
|
||||
$studentsCount = (int)(Database::selectOne("SELECT COUNT(*) as cnt FROM students")['cnt'] ?? 0);
|
||||
$studentsCount = (int)(Database::selectOne(
|
||||
"SELECT COUNT(DISTINCT lp.student_id) AS cnt FROM lesson_progress lp
|
||||
JOIN lessons l ON l.id=lp.lesson_id JOIN courses c ON c.id=l.course_id
|
||||
WHERE c.teacher_id=?", [$teacherId]
|
||||
)['cnt'] ?? 0);
|
||||
|
||||
// Upsert into teacher_performance_metrics
|
||||
Database::query(
|
||||
@@ -295,7 +305,7 @@ class TeacherRatingService
|
||||
$slaData['avg_response_minutes'],
|
||||
$slaData['response_rate_pct'],
|
||||
$slaData['active_queue_count'],
|
||||
max(1, $studentsCount),
|
||||
$studentsCount,
|
||||
$totalReviews,
|
||||
$rawRating,
|
||||
$weightedRating,
|
||||
@@ -364,20 +374,19 @@ class TeacherRatingService
|
||||
$totalReplies = (int)(Database::selectOne("SELECT COUNT(DISTINCT receiver_id) as cnt FROM chat_messages WHERE sender_id = ?", [$teacherId])['cnt'] ?? 0);
|
||||
|
||||
// Calculate Base Response Rate
|
||||
$responseRate = $totalInquiries > 0 ? min(100.0, round(($totalReplies / $totalInquiries) * 100.0, 1)) : 99.0;
|
||||
if ($responseRate < 80.0) $responseRate = 95.0;
|
||||
$responseRate = $totalInquiries > 0 ? min(100.0, round(($totalReplies / $totalInquiries) * 100.0, 1)) : 0.0;
|
||||
|
||||
$baseResponseMinutes = 3;
|
||||
$baseResponseMinutes = 0;
|
||||
|
||||
if ($isActivelySolving && $queueDepth > 0) {
|
||||
$effectiveSlaScore = 99.0;
|
||||
$effectiveSlaScore = 0.0;
|
||||
$effectiveMinutes = $baseResponseMinutes + min(2, (int)($queueDepth * 0.5));
|
||||
} elseif ($queueDepth > 0) {
|
||||
$effectiveMinutes = $baseResponseMinutes + min(5, $queueDepth);
|
||||
$effectiveSlaScore = max(90.0, 98.0 - ($queueDepth * 0.8));
|
||||
$effectiveSlaScore = 0.0;
|
||||
} else {
|
||||
$effectiveMinutes = $baseResponseMinutes;
|
||||
$effectiveSlaScore = 99.5;
|
||||
$effectiveSlaScore = 0.0;
|
||||
}
|
||||
|
||||
return [
|
||||
@@ -393,11 +402,11 @@ class TeacherRatingService
|
||||
}
|
||||
|
||||
return [
|
||||
'avg_response_minutes' => 3,
|
||||
'response_rate_pct' => 99.0,
|
||||
'avg_response_minutes' => 0,
|
||||
'response_rate_pct' => 0.0,
|
||||
'active_queue_count' => 0,
|
||||
'is_active_solving' => true,
|
||||
'sla_score' => 98.0
|
||||
'is_active_solving' => false,
|
||||
'sla_score' => 0.0
|
||||
];
|
||||
}
|
||||
|
||||
@@ -436,7 +445,7 @@ class TeacherRatingService
|
||||
FROM teachers t
|
||||
LEFT JOIN teacher_performance_metrics m ON t.id = m.teacher_id
|
||||
WHERE t.is_marketplace_public = 1
|
||||
ORDER BY " . ($sortBy === 'fastest' ? "COALESCE(m.avg_response_minutes, 10) ASC" : "COALESCE(m.composite_merit_score, 90.00) DESC")
|
||||
ORDER BY " . ($sortBy === 'fastest' ? "CASE WHEN m.avg_response_minutes IS NULL OR m.avg_response_minutes = 0 THEN 1 ELSE 0 END, m.avg_response_minutes ASC" : "COALESCE(m.total_reviews_count, 0) DESC, COALESCE(m.weighted_student_rating, 0) DESC")
|
||||
);
|
||||
|
||||
foreach ($teachers as &$t) {
|
||||
|
||||
Reference in New Issue
Block a user