Files
saqel/backend/app/Controllers/ErrorNotebookController.php
T

97 lines
4.3 KiB
PHP

<?php
namespace App\Controllers;
use App\Core\Database;
use App\Core\Request;
use App\Core\Response;
class ErrorNotebookController
{
public function getErrorNotebook(Request $request, Response $response): void
{
$studentId = (int)$request->user_id;
$sql = "SELECT * FROM student_error_notebook WHERE student_id = ?";
$params = [$studentId];
$subject = trim((string)$request->getQuery('subject', ''));
$status = trim((string)$request->getQuery('status', ''));
if ($subject !== '') { $sql .= ' AND subject_id = ?'; $params[] = $subject; }
if ($status !== '') { $sql .= ' AND status = ?'; $params[] = $status; }
$items = Database::select($sql . ' ORDER BY created_at DESC', $params);
$mastered = count(array_filter($items, fn($item) => ($item['status'] ?? '') === 'mastered'));
$bySubject = [];
foreach ($items as $item) {
$name = (string)($item['subject_name'] ?? '');
if ($name !== '') $bySubject[$name] = ($bySubject[$name] ?? 0) + 1;
}
$total = count($items);
$response->json(['status' => 'success', 'data' => [
'summary' => [
'total_errors' => $total,
'mastered_count' => $mastered,
'pending_count' => $total - $mastered,
'mastery_percentage' => $total ? round(($mastered / $total) * 100, 1) : 0.0,
'by_subject' => $bySubject,
],
'items' => $items,
]]);
}
public function logError(Request $request, Response $response): void
{
$body = $request->getBody();
foreach (['subject_id', 'subject_name', 'topic_name', 'source_type', 'question_text', 'student_wrong_answer', 'correct_answer'] as $field) {
if (trim((string)($body[$field] ?? '')) === '') {
$response->status(422)->json(['status' => 'error', 'message' => "الحقل {$field} مطلوب"]);
return;
}
}
$uuid = $this->uuid();
Database::insert(
"INSERT INTO student_error_notebook
(uuid, student_id, subject_id, subject_name, topic_name, lesson_id, source_type, question_text, options_json,
student_wrong_answer, correct_answer, socratic_hint, error_category, status, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending_remediation', NOW())",
[
$uuid, (int)$request->user_id, $body['subject_id'], $body['subject_name'], $body['topic_name'],
!empty($body['lesson_id']) ? (int)$body['lesson_id'] : null, $body['source_type'], $body['question_text'],
isset($body['options']) ? json_encode($body['options'], JSON_UNESCAPED_UNICODE) : null,
$body['student_wrong_answer'], $body['correct_answer'], (string)($body['socratic_hint'] ?? ''),
(string)($body['error_category'] ?? 'conceptual'),
]
);
$response->status(201)->json(['status' => 'success', 'uuid' => $uuid]);
}
public function getRemediationQuiz(Request $request, Response $response): void
{
$uuid = trim((string)$request->getQuery('error_uuid', ''));
$error = Database::selectOne(
"SELECT id FROM student_error_notebook WHERE uuid = ? AND student_id = ? LIMIT 1",
[$uuid, (int)$request->user_id]
);
if (!$error) {
$response->status(404)->json(['status' => 'error', 'message' => 'الفجوة التعليمية غير موجودة']);
return;
}
$response->status(409)->json(['status' => 'error', 'message' => 'لم يُولّد الخادم اختباراً علاجياً موثقاً لهذه الفجوة بعد']);
}
public function resolveError(Request $request, Response $response): void
{
$response->status(409)->json([
'status' => 'error',
'message' => 'يتم اعتماد الإتقان حصراً بعد تسليم اختبار علاجي وتصحيحه على الخادم',
]);
}
private function uuid(): string
{
$data = random_bytes(16);
$data[6] = chr((ord($data[6]) & 0x0f) | 0x40);
$data[8] = chr((ord($data[8]) & 0x3f) | 0x80);
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
}