getConnection(); $id_evaluation = isset($_GET['id_evaluation']) ? (int)$_GET['id_evaluation'] : 0; if ($id_evaluation <= 0) { die("Évaluation invalide"); } // === RÉCUPÉRATION ÉVALUATION === $stmt = $db->prepare(" SELECT e.*, COUNT(DISTINCT q.id_question) as nb_questions FROM evaluations e LEFT JOIN questions q ON e.id_evaluation = q.id_evaluation WHERE e.id_evaluation = ? GROUP BY e.id_evaluation "); $stmt->execute([$id_evaluation]); $evaluation = $stmt->fetch(PDO::FETCH_ASSOC); if (!$evaluation) { die("Évaluation introuvable"); } // === VÉRIFICATIONS ACCÈS === // 1. Évaluation active ? if (!$apercu_mode && !$evaluation['actif']) { die("Cette évaluation n'est pas active"); } // 2. Classe a accès ? (CORRECTION: Gérer élèves libres id_classe NULL) if (!$apercu_mode) { if ($user['id_classe'] !== null) { $stmt = $db->prepare(" SELECT * FROM acces_evaluations WHERE id_evaluation = ? AND id_classe = ? AND actif = 1 "); $stmt->execute([$id_evaluation, $user['id_classe']]); $acces = $stmt->fetch(PDO::FETCH_ASSOC); if (!$acces) { die("Votre classe n'a pas accès à cette évaluation"); } } else { // Élève libre : vérifier si classe soutien existe $stmt = $db->prepare(" SELECT ae.* FROM acces_evaluations ae INNER JOIN classes c ON ae.id_classe = c.id_classe WHERE ae.id_evaluation = ? AND c.type_classe = 'soutien' AND ae.actif = 1 LIMIT 1 "); $stmt->execute([$id_evaluation]); $acces = $stmt->fetch(PDO::FETCH_ASSOC); if (!$acces) { die("Cette évaluation n'est pas disponible pour le groupe soutien"); } } } // 3. Dates respectées ? if (!$apercu_mode) { $now = new DateTime(); $date_debut = new DateTime($acces['date_debut']); $date_fin = new DateTime($acces['date_fin']); if ($now < $date_debut) { die("Cette évaluation n'est pas encore disponible. Début : " . $date_debut->format('d/m/Y à H:i')); } if ($now > $date_fin) { die("Cette évaluation est terminée. Fin : " . $date_fin->format('d/m/Y à H:i')); } } else { // Mode aperçu : pas de vérification dates, $acces fictif $acces = ['date_debut' => date('Y-m-d H:i:s'), 'date_fin' => date('Y-m-d H:i:s')]; } // 4. Vérifier nombre de tentatives TERMINÉES uniquement (CORRECTION PRINCIPALE) if (!$apercu_mode) { $stmt = $db->prepare(" SELECT COUNT(*) as nb_tentatives_terminees FROM tentatives_eleves WHERE id_evaluation = ? AND id_eleve = ? AND statut = 'terminee' "); $stmt->execute([$id_evaluation, $user['id_utilisateur']]); $nb_tentatives_terminees = $stmt->fetchColumn(); if ($nb_tentatives_terminees >= $evaluation['tentatives_max']) { die("Vous avez déjà effectué le nombre maximum de tentatives pour cette évaluation (" . $evaluation['tentatives_max'] . " tentatives terminées)."); } } else { // Mode aperçu : pas de vérification tentatives $nb_tentatives_terminees = 0; } // === GESTION TENTATIVE === if (!$apercu_mode) { // MODE NORMAL: Gérer tentatives réelles // Chercher tentative en cours (CORRECTION: id_utilisateur) $stmt = $db->prepare(" SELECT * FROM tentatives_eleves WHERE id_evaluation = ? AND id_eleve = ? AND statut = 'en_cours' ORDER BY id_tentative DESC LIMIT 1 "); $stmt->execute([$id_evaluation, $user['id_utilisateur']]); $tentative = $stmt->fetch(PDO::FETCH_ASSOC); // Si pas de tentative en cours, en créer une (CORRECTION: utilise nb_tentatives_terminees) // APRÈS (CORRIGÉ) if (!$tentative) { $stmt = $db->prepare(" INSERT INTO tentatives_eleves ( id_evaluation, id_eleve, numero_tentative, statut, reponses_json, date_debut ) VALUES (?, ?, ?, 'en_cours', '{}', NOW()) "); $stmt->execute([$id_evaluation, $user['id_utilisateur'], $nb_tentatives_terminees + 1]); $id_tentative = $db->lastInsertId(); // Recharger la tentative $stmt = $db->prepare("SELECT * FROM tentatives_eleves WHERE id_tentative = ?"); $stmt->execute([$id_tentative]); $tentative = $stmt->fetch(PDO::FETCH_ASSOC); } else { // Reprendre la tentative existante $id_tentative = $tentative['id_tentative']; } // Calculer temps restant $date_debut_tentative = new DateTime($tentative['date_debut']); $duree_secondes = $evaluation['duree_minutes'] * 60; $temps_ecoule = $now->getTimestamp() - $date_debut_tentative->getTimestamp(); $temps_restant = max(0, $duree_secondes - $temps_ecoule); // Si temps écoulé, soumettre automatiquement if ($temps_restant <= 0) { header('Location: soumettre_evaluation.php?id_evaluation=' . $id_evaluation . '&id_tentative=' . $tentative['id_tentative'] . '&auto=1'); exit(); } } else { // MODE APERÇU: Variables fictives pour affichage $tentative = [ 'id_tentative' => 0, 'date_debut' => date('Y-m-d H:i:s'), 'reponses_json' => '{}' ]; $temps_restant = $evaluation['duree_minutes'] * 60; $reponses_sauvegardees = []; } // === RÉCUPÉRATION QUESTIONS AVEC RANDOMISATION === $stmt = $db->prepare(" SELECT * FROM questions WHERE id_evaluation = ? "); $stmt->execute([$id_evaluation]); $questions = $stmt->fetchAll(PDO::FETCH_ASSOC); // Randomisation par tentative (sauf mode aperçu enseignant) if (!$apercu_mode) { // Vérifier si ordre déjà sauvegardé pour cette tentative if (!empty($tentative['ordre_questions_json'])) { // Ordre existant : réappliquer le même ordre $ordre_ids = json_decode($tentative['ordre_questions_json'], true); $questions_ordonnees = []; foreach ($ordre_ids as $id_q) { foreach ($questions as $q) { if ($q['id_question'] == $id_q) { $questions_ordonnees[] = $q; break; } } } $questions = $questions_ordonnees; } else { // Première fois : randomiser et sauvegarder l'ordre shuffle($questions); $ordre_ids = array_column($questions, 'id_question'); $ordre_json = json_encode($ordre_ids); // Sauvegarder l'ordre dans la tentative $stmt = $db->prepare(" UPDATE tentatives_eleves SET ordre_questions_json = ? WHERE id_tentative = ? "); $stmt->execute([$ordre_json, $id_tentative]); } } else { // Mode aperçu enseignant : ordre normal usort($questions, fn($a, $b) => $a['ordre'] <=> $b['ordre']); } // Récupérer réponses sauvegardées $reponses_sauvegardees = json_decode($tentative['reponses_json'] ?? '{}', true) ?: []; ?> <?= htmlspecialchars($evaluation['titre']) ?>
👁️ MODE APERÇU ENSEIGNANT - Les réponses ne sont pas enregistrées
ℹ️ Information: Vous consultez cette évaluation en mode prévisualisation. Ce mode permet de vérifier le contenu avant de le proposer aux élèves.
$q): ?>
💾 Sauvegarde...