Initial commit (code), runtime ignoré, secrets exclus
This commit is contained in:
562
voir_resultat.php
Normal file
562
voir_resultat.php
Normal file
@ -0,0 +1,562 @@
|
||||
<?php
|
||||
/**
|
||||
* VISUALISATION RÉSULTATS ÉLÈVE
|
||||
* Affiche les résultats d'une tentative avec correction si activée
|
||||
*/
|
||||
|
||||
require_once 'config/database.php';
|
||||
require_once 'config/session.php';
|
||||
|
||||
// Session déjà démarrée dans session.php
|
||||
|
||||
// Vérification élève connecté
|
||||
if (!SessionManager::isEleve()) {
|
||||
header('Location: login.php?error=access_denied');
|
||||
exit();
|
||||
}
|
||||
|
||||
$user = SessionManager::getUser();
|
||||
$db = Database::getInstance()->getConnection();
|
||||
|
||||
$id_evaluation = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
$id_tentative = isset($_GET['tentative']) ? (int)$_GET['tentative'] : 0;
|
||||
$nouvelle_soumission = isset($_GET['new']) && $_GET['new'] == 1;
|
||||
|
||||
if ($id_evaluation <= 0) {
|
||||
die("Évaluation invalide");
|
||||
}
|
||||
|
||||
// Récupérer l'évaluation
|
||||
$stmt = $db->prepare("SELECT * FROM evaluations WHERE id_evaluation = ?");
|
||||
$stmt->execute([$id_evaluation]);
|
||||
$evaluation = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$evaluation) {
|
||||
die("Évaluation introuvable");
|
||||
}
|
||||
|
||||
// Récupérer les tentatives de l'élève
|
||||
$stmt = $db->prepare("
|
||||
SELECT * FROM tentatives_eleves
|
||||
WHERE id_evaluation = ?
|
||||
AND id_eleve = ?
|
||||
ORDER BY numero_tentative DESC
|
||||
");
|
||||
$stmt->execute([$id_evaluation, $user['id']]);
|
||||
$tentatives = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if (empty($tentatives)) {
|
||||
die("Aucune tentative trouvée");
|
||||
}
|
||||
|
||||
// Si tentative spécifique demandée
|
||||
if ($id_tentative > 0) {
|
||||
$tentative_affichee = null;
|
||||
foreach ($tentatives as $t) {
|
||||
if ($t['id_tentative'] == $id_tentative) {
|
||||
$tentative_affichee = $t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$tentative_affichee) {
|
||||
die("Tentative introuvable");
|
||||
}
|
||||
} else {
|
||||
// Afficher la dernière tentative terminée
|
||||
$tentative_affichee = null;
|
||||
foreach ($tentatives as $t) {
|
||||
if ($t['statut'] == 'terminee') {
|
||||
$tentative_affichee = $t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$tentative_affichee) {
|
||||
$tentative_affichee = $tentatives[0];
|
||||
}
|
||||
}
|
||||
|
||||
// Récupérer les questions
|
||||
$stmt = $db->prepare("
|
||||
SELECT * FROM questions
|
||||
WHERE id_evaluation = ?
|
||||
ORDER BY ordre
|
||||
");
|
||||
$stmt->execute([$id_evaluation]);
|
||||
$questions = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$reponses_eleve = json_decode($tentative_affichee['reponses_json'], true) ?: [];
|
||||
|
||||
// Calculer statistiques
|
||||
$nb_questions_repondues = count($reponses_eleve);
|
||||
$note_sur_20 = ($tentative_affichee['note'] / $evaluation['note_totale']) * 20;
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Résultats - <?= htmlspecialchars($evaluation['titre']) ?></title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.header {
|
||||
background: white;
|
||||
padding: 25px;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
color: #667eea;
|
||||
font-size: 24px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.header p {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
<?php if ($nouvelle_soumission): ?>
|
||||
.success-banner {
|
||||
background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%);
|
||||
color: white;
|
||||
padding: 20px;
|
||||
border-radius: 15px;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
animation: slideIn 0.5s;
|
||||
}
|
||||
|
||||
@keyframes slideIn {
|
||||
from { transform: translateY(-20px); opacity: 0; }
|
||||
to { transform: translateY(0); opacity: 1; }
|
||||
}
|
||||
|
||||
.success-banner h2 {
|
||||
font-size: 20px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
<?php endif; ?>
|
||||
|
||||
.score-card {
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.score-big {
|
||||
font-size: 64px;
|
||||
font-weight: 800;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.score-details {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||
gap: 15px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.score-item {
|
||||
padding: 15px;
|
||||
background: #f8f9fa;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.score-label {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.score-value {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.tentatives-list {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.tentatives-list h3 {
|
||||
color: #667eea;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.tentative-item {
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
background: #f8f9fa;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tentative-item.active {
|
||||
background: #e8eeff;
|
||||
border: 2px solid #667eea;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 12px 24px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: #f5f5f5;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.correction-section {
|
||||
background: white;
|
||||
padding: 25px;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.correction-section h3 {
|
||||
color: #667eea;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.question-result {
|
||||
padding: 20px;
|
||||
border: 2px solid #e0e0e0;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.question-result.correct {
|
||||
border-color: #4CAF50;
|
||||
background: #f1f8f4;
|
||||
}
|
||||
|
||||
.question-result.incorrect {
|
||||
border-color: #f44336;
|
||||
background: #fef3f2;
|
||||
}
|
||||
|
||||
.question-result.partial {
|
||||
border-color: #ff9800;
|
||||
background: #fff8f0;
|
||||
}
|
||||
|
||||
.question-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: start;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.question-number {
|
||||
font-weight: 700;
|
||||
color: #667eea;
|
||||
}
|
||||
|
||||
.points-badge {
|
||||
padding: 4px 12px;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.points-badge.correct {
|
||||
background: #4CAF50;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.points-badge.incorrect {
|
||||
background: #f44336;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.points-badge.partial {
|
||||
background: #ff9800;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.question-enonce {
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
margin-bottom: 15px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.reponse-block {
|
||||
background: white;
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.reponse-label {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
margin-bottom: 5px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.reponse-value {
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.explication {
|
||||
background: #f0f7ff;
|
||||
padding: 12px;
|
||||
border-left: 4px solid #667eea;
|
||||
border-radius: 8px;
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.back-link {
|
||||
display: inline-block;
|
||||
margin-bottom: 20px;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
padding: 10px 20px;
|
||||
background: rgba(255,255,255,0.2);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
body {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.score-big {
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
.score-details {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<a href="eleve/dashboard.php" class="back-link">← Retour au tableau de bord</a>
|
||||
|
||||
<?php if ($nouvelle_soumission): ?>
|
||||
<div class="success-banner">
|
||||
<h2>✓ Évaluation soumise avec succès !</h2>
|
||||
<p>Voici vos résultats</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="header">
|
||||
<h1><?= htmlspecialchars($evaluation['titre']) ?></h1>
|
||||
<p>Tentative n°<?= $tentative_affichee['numero_tentative'] ?> -
|
||||
<?= ($tentative_affichee['statut'] == 'terminee') ? 'Terminée' : 'En cours' ?></p>
|
||||
</div>
|
||||
|
||||
<div class="score-card">
|
||||
<h2>Votre note</h2>
|
||||
<div class="score-big"><?= number_format($note_sur_20, 1) ?>/20</div>
|
||||
<div class="score-details">
|
||||
<div class="score-item">
|
||||
<div class="score-label">Points obtenus</div>
|
||||
<div class="score-value"><?= $tentative_affichee['note'] ?> / <?= $evaluation['note_totale'] ?></div>
|
||||
</div>
|
||||
<div class="score-item">
|
||||
<div class="score-label">Questions répondues</div>
|
||||
<div class="score-value"><?= $nb_questions_repondues ?> / <?= count($questions) ?></div>
|
||||
</div>
|
||||
<div class="score-item">
|
||||
<div class="score-label">Durée</div>
|
||||
<div class="score-value">
|
||||
<?php
|
||||
if ($tentative_affichee['date_fin']) {
|
||||
$debut = new DateTime($tentative_affichee['date_debut']);
|
||||
$fin = new DateTime($tentative_affichee['date_fin']);
|
||||
$duree = $debut->diff($fin);
|
||||
echo $duree->i . ' min ' . $duree->s . ' s';
|
||||
} else {
|
||||
echo 'En cours';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (count($tentatives) > 1): ?>
|
||||
<div class="tentatives-list">
|
||||
<h3>Historique de vos tentatives</h3>
|
||||
<?php foreach ($tentatives as $t): ?>
|
||||
<div class="tentative-item <?= ($t['id_tentative'] == $tentative_affichee['id_tentative']) ? 'active' : '' ?>">
|
||||
<div>
|
||||
<strong>Tentative n°<?= $t['numero_tentative'] ?></strong>
|
||||
<span style="margin-left: 15px; color: #666;">
|
||||
<?= ($t['statut'] == 'terminee') ? 'Note: ' . $t['note'] . '/' . $evaluation['note_totale'] : 'En cours' ?>
|
||||
</span>
|
||||
</div>
|
||||
<?php if ($t['id_tentative'] != $tentative_affichee['id_tentative'] && $t['statut'] == 'terminee'): ?>
|
||||
<a href="voir_resultat.php?id=<?= $id_evaluation ?>&tentative=<?= $t['id_tentative'] ?>"
|
||||
class="btn btn-secondary" style="padding: 6px 12px; font-size: 12px;">
|
||||
Voir
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($evaluation['afficher_correction'] && $tentative_affichee['statut'] == 'terminee'): ?>
|
||||
<div class="correction-section">
|
||||
<h3>📝 Correction détaillée</h3>
|
||||
|
||||
<?php foreach ($questions as $index => $q): ?>
|
||||
<?php
|
||||
$id_question = $q['id_question'];
|
||||
$reponse_eleve = $reponses_eleve[$id_question] ?? null;
|
||||
$reponse_correcte = json_decode($q['reponse_correcte_json'], true);
|
||||
|
||||
// Déterminer si correct
|
||||
$est_correct = false;
|
||||
$classe_css = 'incorrect';
|
||||
|
||||
switch ($q['type_question']) {
|
||||
case 'qcm':
|
||||
$correct = $reponse_correcte[0] ?? null;
|
||||
$est_correct = ($reponse_eleve === $correct);
|
||||
break;
|
||||
case 'checkbox':
|
||||
if (is_array($reponse_eleve) && is_array($reponse_correcte)) {
|
||||
sort($reponse_eleve);
|
||||
sort($reponse_correcte);
|
||||
$est_correct = ($reponse_eleve === $reponse_correcte);
|
||||
}
|
||||
break;
|
||||
case 'select':
|
||||
$correct = $reponse_correcte['reponse'] ?? null;
|
||||
$est_correct = ($reponse_eleve === $correct);
|
||||
break;
|
||||
}
|
||||
|
||||
$classe_css = $est_correct ? 'correct' : 'incorrect';
|
||||
$badge_classe = $est_correct ? 'correct' : 'incorrect';
|
||||
$badge_texte = $est_correct ? '✓ ' . $q['points'] . ' pts' : '✗ 0 pt';
|
||||
?>
|
||||
|
||||
<div class="question-result <?= $classe_css ?>">
|
||||
<div class="question-header">
|
||||
<div class="question-number">Question <?= $index + 1 ?></div>
|
||||
<div class="points-badge <?= $badge_classe ?>"><?= $badge_texte ?></div>
|
||||
</div>
|
||||
|
||||
<div class="question-enonce"><?= nl2br(strip_tags($q['enonce'], '<img><a><br><strong><em><u><b><i><span>')) ?></div>
|
||||
|
||||
<div class="reponse-block">
|
||||
<div class="reponse-label">Votre réponse</div>
|
||||
<div class="reponse-value">
|
||||
<?php
|
||||
if ($reponse_eleve === null) {
|
||||
echo '<em style="color: #999;">Non répondu</em>';
|
||||
} elseif (is_array($reponse_eleve)) {
|
||||
echo htmlspecialchars(implode(', ', $reponse_eleve));
|
||||
} else {
|
||||
echo htmlspecialchars($reponse_eleve);
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (!$est_correct): ?>
|
||||
<div class="reponse-block">
|
||||
<div class="reponse-label">Réponse correcte</div>
|
||||
<div class="reponse-value" style="color: #4CAF50; font-weight: 600;">
|
||||
<?php
|
||||
if (is_array($reponse_correcte)) {
|
||||
echo htmlspecialchars(implode(', ', $reponse_correcte));
|
||||
} else {
|
||||
$correct_display = $reponse_correcte['reponse'] ?? $reponse_correcte[0] ?? 'N/A';
|
||||
echo htmlspecialchars($correct_display);
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($q['explication'])): ?>
|
||||
<div class="explication">
|
||||
<strong>💡 Explication :</strong><br>
|
||||
<?= nl2br(htmlspecialchars($q['explication'])) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div style="text-align: center; margin-top: 30px;">
|
||||
<?php if (count($tentatives) < $evaluation['tentatives_max']): ?>
|
||||
<a href="passer_evaluation.php?id=<?= $id_evaluation ?>" class="btn btn-primary">
|
||||
🔄 Refaire l'évaluation (Tentative <?= count($tentatives) + 1 ?>/<?= $evaluation['tentatives_max'] ?>)
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<p style="color: white; font-size: 14px;">
|
||||
Vous avez utilisé toutes vos tentatives (<?= $evaluation['tentatives_max'] ?>)
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user