<?php
// Start session
session_start();
// Include database configuration
require_once '../config/database.php';
// Check if user is logged in and has admin role
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'admin') {
header('Location: login.php');
exit;
}
// Check if exam_id is provided
if (!isset($_GET['exam_id']) || !is_numeric($_GET['exam_id'])) {
header('Location: manage_exams.php');
exit;
}
$exam_id = $_GET['exam_id'];
// Get exam details
$exam_query = "SELECT es.*, c.title as course_title
FROM exam_schedules es
JOIN courses c ON es.course_id = c.id
WHERE es.id = ?";
$stmt = $conn->prepare($exam_query);
$stmt->bind_param("i", $exam_id);
$stmt->execute();
$exam_result = $stmt->get_result();
if ($exam_result->num_rows === 0) {
header('Location: manage_exams.php');
exit;
}
$exam = $exam_result->fetch_assoc();
// Process update student exam status
if (isset($_POST['update_status'])) {
$student_exam_id = $_POST['student_exam_id'];
$new_status = $_POST['new_status'];
$admin_remarks = $_POST['admin_remarks'];
$update_query = "UPDATE student_exams SET status = ?, admin_remarks = ? WHERE id = ?";
$stmt = $conn->prepare($update_query);
$stmt->bind_param("ssi", $new_status, $admin_remarks, $student_exam_id);
if ($stmt->execute()) {
$success_message = "Student exam status updated successfully.";
} else {
$error_message = "Failed to update student exam status.";
}
}
// Get total questions in the exam
$questions_count_query = "SELECT COUNT(*) as total FROM exam_question_maps WHERE exam_id = ?";
$stmt = $conn->prepare($questions_count_query);
$stmt->bind_param("i", $exam_id);
$stmt->execute();
$questions_count_result = $stmt->get_result()->fetch_assoc();
$total_questions = $questions_count_result['total'];
// Get total marks in the exam
$total_marks_query = "SELECT SUM(q.marks) as total_marks
FROM questions q
JOIN exam_question_maps eqm ON q.id = eqm.question_id
WHERE eqm.exam_id = ?";
$stmt = $conn->prepare($total_marks_query);
$stmt->bind_param("i", $exam_id);
$stmt->execute();
$total_marks_result = $stmt->get_result()->fetch_assoc();
$total_marks = $total_marks_result['total_marks'] ?? 0;
// Get student exam attempts
$student_exams_query = "SELECT se.*,
u.first_name, u.last_name, u.email, u.id,
(SELECT COUNT(*) FROM student_answers sa WHERE sa.student_exam_id = se.id AND sa.is_correct = 1) as correct_answers
FROM student_exams se
JOIN users u ON se.user_id = u.id
WHERE se.exam_id = ?
ORDER BY se.created_at DESC";
$stmt = $conn->prepare($student_exams_query);
$stmt->bind_param("i", $exam_id);
$stmt->execute();
$student_exams_result = $stmt->get_result();
$student_exams = [];
while ($student_exam = $student_exams_result->fetch_assoc()) {
$student_exams[] = $student_exam;
}
// Calculate statistics
$total_attempts = count($student_exams);
$completed_attempts = 0;
$passed_attempts = 0;
$failed_attempts = 0;
$avg_score = 0;
$total_score_sum = 0;
foreach ($student_exams as $exam_attempt) {
if (in_array($exam_attempt['status'], ['completed', 'graded', 'passed', 'failed'])) {
$completed_attempts++;
$total_score_sum += $exam_attempt['total_score'];
if ($exam_attempt['percentage'] >= $exam['passing_percentage']) {
$passed_attempts++;
} else {
$failed_attempts++;
}
}
}
$avg_score = $completed_attempts > 0 ? $total_score_sum / $completed_attempts : 0;
$pass_rate = $completed_attempts > 0 ? ($passed_attempts / $completed_attempts) * 100 : 0;
include_once 'includes/header.php';
?>
<div class="container-fluid">
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Exam Results: <?php echo htmlspecialchars($exam['title']); ?></h1>
<div>
<a href="student_answers.php?exam_id=<?php echo $exam_id; ?>" class="btn btn-info btn-sm shadow-sm mr-2">
<i class="fas fa-list fa-sm text-white-50"></i> View All Answers
</a>
<a href="manage_exams.php" class="btn btn-secondary btn-sm shadow-sm">
<i class="fas fa-arrow-left fa-sm text-white-50"></i> Back to Exams
</a>
</div>
</div>
<?php if (isset($error_message)): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<?php echo $error_message; ?>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<?php endif; ?>
<?php if (isset($success_message)): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<?php echo $success_message; ?>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<?php endif; ?>
<!-- Exam Information Row -->
<div class="row">
<!-- Exam Details Card -->
<div class="col-xl-8 col-lg-7">
<div class="card shadow mb-4">
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Exam Information</h6>
<?php if ($exam['is_active'] == 1): ?>
<span class="badge badge-success">Active</span>
<?php else: ?>
<span class="badge badge-danger">Inactive</span>
<?php endif; ?>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<p><strong>Course:</strong> <?php echo htmlspecialchars($exam['course_title'] ?? 'No course assigned'); ?></p>
<p><strong>Exam Title:</strong> <?php echo htmlspecialchars($exam['title']); ?></p>
<p><strong>Description:</strong> <?php echo htmlspecialchars($exam['description'] ?? 'No description'); ?></p>
<p><strong>Instructions:</strong> <?php echo htmlspecialchars($exam['instructions'] ?? 'No instructions'); ?></p>
</div>
<div class="col-md-6">
<p><strong>Duration:</strong> <?php echo $exam['duration_minutes']; ?> minutes</p>
<p><strong>Passing Score:</strong> <?php echo $exam['passing_percentage']; ?>%</p>
<p><strong>Questions:</strong> <?php echo $total_questions; ?></p>
<p><strong>Total Marks:</strong> <?php echo $total_marks; ?></p>
</div>
</div>
</div>
</div>
</div>
<!-- Results Statistics Card -->
<div class="col-xl-4 col-lg-5">
<div class="card shadow mb-4 border-left-primary">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Results Statistics</h6>
</div>
<div class="card-body">
<div class="row no-gutters align-items-center mb-3">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
Total Attempts
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo $total_attempts; ?></div>
</div>
<div class="col-auto">
<i class="fas fa-users fa-2x text-gray-300"></i>
</div>
</div>
<div class="row no-gutters align-items-center mb-3">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
Passed
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo $passed_attempts; ?></div>
</div>
<div class="col-auto">
<i class="fas fa-check-circle fa-2x text-gray-300"></i>
</div>
</div>
<div class="row no-gutters align-items-center mb-3">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
Failed
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo $failed_attempts; ?></div>
</div>
<div class="col-auto">
<i class="fas fa-times-circle fa-2x text-gray-300"></i>
</div>
</div>
<div class="row no-gutters align-items-center mb-3">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">
Average Score
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo number_format($avg_score, 2); ?> / <?php echo $total_marks; ?></div>
</div>
<div class="col-auto">
<i class="fas fa-chart-line fa-2x text-gray-300"></i>
</div>
</div>
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
Pass Rate
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo number_format($pass_rate, 2); ?>%</div>
</div>
<div class="col-auto">
<i class="fas fa-percent fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Students Results Table -->
<div class="card shadow mb-4">
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Student Results</h6>
<div>
<a href="#" class="btn btn-sm btn-success" onclick="exportToExcel()">
<i class="fas fa-file-excel"></i> Export to Excel
</a>
</div>
</div>
<div class="card-body">
<?php if (empty($student_exams)): ?>
<div class="alert alert-info">
<i class="fas fa-info-circle"></i> No student has attempted this exam yet.
</div>
<?php else: ?>
<div class="table-responsive">
<table class="table table-bordered" id="resultsTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Student</th>
<th>Start Time</th>
<th>End Time</th>
<th>Score</th>
<th>Percentage</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($student_exams as $student_exam): ?>
<tr>
<td>
<?php echo htmlspecialchars($student_exam['first_name'] . ' ' . $student_exam['last_name']); ?>
<div class="small text-muted"><?php echo htmlspecialchars($student_exam['user_id']); ?></div>
<div class="small text-muted"><?php echo htmlspecialchars($student_exam['email']); ?></div>
</td>
<td>
<?php echo $student_exam['start_time'] ? date('d M, Y H:i', strtotime($student_exam['start_time'])) : 'Not started'; ?>
</td>
<td>
<?php echo $student_exam['end_time'] ? date('d M, Y H:i', strtotime($student_exam['end_time'])) : 'In progress'; ?>
</td>
<td>
<?php
if ($student_exam['status'] === 'completed' || $student_exam['status'] === 'graded' ||
$student_exam['status'] === 'passed' || $student_exam['status'] === 'failed') {
echo $student_exam['total_score'] . ' / ' . $total_marks;
echo '<div class="small text-muted">Correct: ' . $student_exam['correct_answers'] . ' / ' . $total_questions . '</div>';
} else {
echo 'Not graded';
}
?>
</td>
<td>
<?php
if ($student_exam['percentage'] !== null) {
$percentage_class = ($student_exam['percentage'] >= $exam['passing_percentage']) ? 'success' : 'danger';
echo '<span class="badge badge-' . $percentage_class . '">' . number_format($student_exam['percentage'], 2) . '%</span>';
} else {
echo 'N/A';
}
?>
</td>
<td>
<?php
$status_badge_class = '';
switch ($student_exam['status']) {
case 'pending':
$status_badge_class = 'secondary';
break;
case 'in_progress':
$status_badge_class = 'info';
break;
case 'completed':
$status_badge_class = 'primary';
break;
case 'graded':
$status_badge_class = 'warning';
break;
case 'passed':
$status_badge_class = 'success';
break;
case 'failed':
$status_badge_class = 'danger';
break;
default:
$status_badge_class = 'secondary';
}
?>
<span class="badge badge-<?php echo $status_badge_class; ?>">
<?php echo ucfirst(str_replace('_', ' ', $student_exam['status'])); ?>
</span>
<?php if (!empty($student_exam['admin_remarks'])): ?>
<div class="small mt-1">
<a href="#" data-toggle="tooltip" title="<?php echo htmlspecialchars($student_exam['admin_remarks']); ?>">
<i class="fas fa-comment text-info"></i> Has remarks
</a>
</div>
<?php endif; ?>
</td>
<td>
<a href="view_student_answers.php?exam_id=<?php echo $exam_id; ?>&student_exam_id=<?php echo $student_exam['id']; ?>"
class="btn btn-info btn-sm mb-1">
<i class="fas fa-eye"></i> View Answers
</a>
<button type="button" class="btn btn-primary btn-sm mb-1"
onclick="showUpdateStatusModal(<?php echo $student_exam['id']; ?>, '<?php echo $student_exam['status']; ?>', '<?php echo addslashes($student_exam['admin_remarks'] ?? ''); ?>')">
<i class="fas fa-edit"></i> Update Status
</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
</div>
<!-- Update Status Modal -->
<div class="modal fade" id="updateStatusModal" tabindex="-1" role="dialog" aria-labelledby="updateStatusModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="updateStatusModalLabel">Update Student Exam Status</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form method="post" action="">
<div class="modal-body">
<input type="hidden" id="student_exam_id" name="student_exam_id">
<div class="form-group">
<label for="new_status">Status</label>
<select class="form-control" id="new_status" name="new_status" required>
<option value="pending">Pending</option>
<option value="in_progress">In Progress</option>
<option value="completed">Completed</option>
<option value="graded">Graded</option>
<option value="passed">Passed</option>
<option value="failed">Failed</option>
</select>
</div>
<div class="form-group">
<label for="admin_remarks">Admin Remarks</label>
<textarea class="form-control" id="admin_remarks" name="admin_remarks" rows="3"></textarea>
<small class="form-text text-muted">
Add any remarks or notes about this student's exam performance.
</small>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="submit" name="update_status" class="btn btn-primary">Update Status</button>
</div>
</form>
</div>
</div>
</div>
<script>
$(document).ready(function() {
// Initialize DataTable
$('#resultsTable').DataTable({
"order": [[ 1, "desc" ]], // Sort by start time by default (descending)
"columnDefs": [
{ "width": "20%", "targets": 0 }, // Student column
{ "width": "12%", "targets": 1 }, // Start Time column
{ "width": "12%", "targets": 2 }, // End Time column
{ "width": "12%", "targets": 3 }, // Score column
{ "width": "10%", "targets": 4 }, // Percentage column
{ "width": "14%", "targets": 5 }, // Status column
{ "width": "20%", "targets": 6 } // Actions column
]
});
// Initialize tooltips
$('[data-toggle="tooltip"]').tooltip();
});
// Function to show the update status modal
function showUpdateStatusModal(studentExamId, currentStatus, adminRemarks) {
$('#student_exam_id').val(studentExamId);
$('#new_status').val(currentStatus);
$('#admin_remarks').val(adminRemarks);
$('#updateStatusModal').modal('show');
}
// Function to export table to Excel
function exportToExcel() {
// Create a date string for the filename
const date = new Date();
const dateString = date.getFullYear() + '-' +
('0' + (date.getMonth() + 1)).slice(-2) + '-' +
('0' + date.getDate()).slice(-2);
// Get the exam title from the page heading
const examTitle = $('h1.h3').text().replace('Exam Results: ', '').trim();
// Create a filename
const filename = 'exam-results-' + examTitle.replace(/[^a-z0-9]/gi, '-').toLowerCase() + '-' + dateString + '.xlsx';
// Export the table
$("#resultsTable").table2excel({
name: "Exam Results",
filename: filename,
fileext: ".xlsx",
exclude_links: true,
exclude_img: true,
exclude: ".noExport",
preserveColors: true
});
}
</script>
<!-- Include Table2Excel for export functionality -->
<script src="../assets/js/table2excel.js"></script>
<?php
include_once 'includes/footer.php';
?>