Quiz sur l’expression de l’opinion (vocabulaire, indicatif, subjonctif)

body {
font-family: ‘Segoe UI’, Tahoma, Geneva, Verdana, sans-serif;
max-width: 100%;
margin: 0 auto;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}
h1, h2, h3 {
color: #2c3e50;
}
.container {
background: rgba(255, 255, 255, 0.95);
padding: 30px;
border-radius: 15px;
box-shadow: 0 8px 32px rgba(0,0,0,0.1);
backdrop-filter: blur(10px);
max-width: 100%;
margin: 0 auto;
}
.subscription-form {
background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);
padding: 25px;
border-radius: 12px;
margin-bottom: 30px;
border: 1px solid rgba(76, 175, 80, 0.2);
}
.exercise-container {
display: none;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
color: #2c3e50;
}
input, select, textarea {
width: 100%;
padding: 12px;
border: 2px solid #e9ecef;
border-radius: 8px;
font-size: 16px;
transition: border-color 0.3s ease;
box-sizing: border-box;
}
input:focus, select:focus, textarea:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 15px 25px;
border-radius: 8px;
cursor: pointer;
font-size: 16px;
font-weight: bold;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}
.question {
margin-bottom: 25px;
padding: 25px;
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
border-radius: 12px;
border-left: 5px solid #667eea;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}
.question-number {
font-weight: bold;
color: #2c3e50;
margin-bottom: 12px;
font-size: 18px;
}
.question-text {
font-size: 16px;
margin-bottom: 15px;
line-height: 1.6;
color: #2c3e50;
}
.question-type {
background: #667eea;
color: white;
padding: 4px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: bold;
display: inline-block;
margin-bottom: 10px;
}
.options {
display: grid;
gap: 12px;
}
.option {
display: flex;
align-items: center;
padding: 12px;
background: white;
border: 2px solid #e9ecef;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
}
.option:hover {
border-color: #667eea;
background: linear-gradient(135deg, #e8f5e9 0%, #f3e5f5 100%);
transform: translateX(5px);
}
.option input[type=”radio”], .option input[type=”checkbox”] {
margin-right: 12px;
width: auto;
transform: scale(1.2);
}
.option.correct {
background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%);
border-color: #28a745;
}
.option.incorrect {
background: linear-gradient(135deg, #f8d7da 0%, #f1b0b7 100%);
border-color: #dc3545;
}
.option.correct-answer {
background: linear-gradient(135deg, #d1ecf1 0%, #bee5eb 100%);
border-color: #17a2b8;
}
.result {
margin-top: 30px;
padding: 25px;
background: linear-gradient(135deg, #eafaf1 0%, #d4f1de 100%);
border-radius: 12px;
display: none;
border: 1px solid rgba(40, 167, 69, 0.2);
}
.certificate {
text-align: center;
margin-top: 30px;
padding: 25px;
border: 3px solid #2c3e50;
border-radius: 12px;
display: none;
background: white;
}
.error {
color: #dc3545;
font-size: 14px;
margin-top: 5px;
}
.progress-bar {
width: 100%;
height: 25px;
background: linear-gradient(135deg, #e9ecef 0%, #dee2e6 100%);
border-radius: 15px;
margin-bottom: 25px;
overflow: hidden;
box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
}
.progress-fill {
height: 100%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 15px;
transition: width 0.5s ease;
width: 0%;
box-shadow: 0 2px 4px rgba(102, 126, 234, 0.3);
}
#certificatePreview {
position: relative;
width: 100%;
height: 500px;
background: linear-gradient(135deg, #fff 0%, #f8f9fa 100%);
border: 12px solid transparent;
border-image: linear-gradient(45deg, #667eea, #764ba2, #f093fb, #4facfe) 1;
box-sizing: border-box;
overflow: hidden;
margin-bottom: 25px;
box-shadow: 0 8px 32px rgba(0,0,0,0.1);
}
.certificate-content {
position: relative;
z-index: 1;
padding: 25px;
width: 100%;
height: 100%;
box-sizing: border-box;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.certificate-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.certificate-title {
flex-grow: 1;
text-align: center;
}
.certificate-logo {
width: 140px;
height: 70px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
font-size: 18px;
}
.certificate-footer {
display: flex;
justify-content: space-between;
align-items: flex-end;
}
.certificate-qr {
width: 120px;
height: 120px;
display: flex;
justify-content: center;
align-items: center;
background: #f9f9f9;
border: 2px solid #dee2e6;
border-radius: 8px;
}
.certificate-signature {
flex-grow: 1;
text-align: center;
}
.loading {
display: none;
margin-top: 15px;
font-style: italic;
color: #6c757d;
text-align: center;
}
.instruction-box {
background: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%);
border: 2px solid #ffeaa7;
border-radius: 12px;
padding: 20px;
margin-bottom: 25px;
}
.theme-section {
margin-bottom: 35px;
padding: 25px;
background: linear-gradient(135deg, #f1f3f4 0%, #e8eaed 100%);
border-radius: 12px;
border-left: 6px solid #764ba2;
box-shadow: 0 4px 15px rgba(0,0,0,0.05);
}
.theme-title {
color: #764ba2;
font-size: 20px;
font-weight: bold;
margin-bottom: 20px;
text-transform: uppercase;
letter-spacing: 1px;
}
.multiple-choice-container {
display: grid;
gap: 10px;
}
.score-display {
font-size: 24px;
font-weight: bold;
color: #27ae60;
text-align: center;
margin: 20px 0;
padding: 15px;
background: linear-gradient(135deg, #d4f1de 0%, #c3e6cb 100%);
border-radius: 10px;
}

💬 Quiz B1 – Exprimer son Opinion en Français

Testez vos connaissances sur l’expression de l’opinion avec l’indicatif et le subjonctif ! Inscrivez-vous pour commencer.

💭 Quiz B1 – Les Expressions de l’Opinion

📋 Instructions: Ce quiz comprend 30 questions sur :

  • 💬 Les expressions pour donner son opinion
  • ✅ L’accord et le désaccord
  • 📖 L’indicatif vs le subjonctif
  • 🤔 Les hypothèses avec SI
  • 🔢 Les pronoms indéfinis

💬 Thème 1: Exprimer son Opinion
CHOIX MULTIPLE
Question 1
Complétez: “_______, le changement climatique est le plus grand défi de notre époque.”



RÉPONSES MULTIPLES
Question 2
Quelles expressions expriment une opinion personnelle? (Plusieurs réponses)



CHOIX MULTIPLE
Question 3
Quelle expression exprime une conviction forte?



CHOIX MULTIPLE
Question 4
“Sans aucun doute” exprime:



CHOIX MULTIPLE
Question 5
Comment dire qu’on trouve quelque chose intéressant?



✅ Thème 2: Accord et Désaccord
CHOIX MULTIPLE
Question 6
Quelle expression exprime un accord total?



RÉPONSES MULTIPLES
Question 7
Quelles expressions montrent qu’on est d’accord? (Plusieurs réponses)



CHOIX MULTIPLE
Question 8
Pour exprimer un désaccord poli, on peut dire:



RÉPONSES MULTIPLES
Question 9
Quelles expressions expriment un désaccord? (Plusieurs réponses)



CHOIX MULTIPLE
Question 10
“Je pense la même chose” signifie:



📖 Thème 3: Indicatif ou Subjonctif?
CHOIX MULTIPLE
Question 11
Je pense qu’il _______ (être) compétent.



CHOIX MULTIPLE
Question 12
Je ne crois pas qu’il _______ (pouvoir) venir.



CHOIX MULTIPLE
Question 13
Il est évident qu’elle _______ (avoir) du talent.



CHOIX MULTIPLE
Question 14
Je doute qu’ils _______ (finir) à temps.



CHOIX MULTIPLE
Question 15
J’espère qu’il _______ (faire) beau demain.



CHOIX MULTIPLE
Question 16
Il faut que tu _______ (être) à l’heure.



CHOIX MULTIPLE
Question 17
Il est possible qu’il _______ (pleuvoir) demain.



CHOIX MULTIPLE
Question 18
Il est probable qu’elle _______ (réussir).



CHOIX MULTIPLE
Question 19
Je ne suis pas sûr qu’il _______ (venir).



CHOIX MULTIPLE
Question 20
Je suis certain qu’ils _______ (comprendre).



🤔 Thème 4: Les Hypothèses Imaginaires
CHOIX MULTIPLE
Question 21
Si j’_______ (avoir) du temps, je voyagerais.



CHOIX MULTIPLE
Question 22
Si nous étions en vacances, nous _______ (se détendre) à la plage.



CHOIX MULTIPLE
Question 23
Si je gagnais à la loterie, je _______ (faire) le tour du monde.



CHOIX MULTIPLE
Question 24
Quelle structure est correcte pour une hypothèse imaginaire?



CHOIX MULTIPLE
Question 25
Si elle _______ (savoir) parler japonais, elle travaillerait à Tokyo.



🔢 Thème 5: Les Pronoms Indéfinis
CHOIX MULTIPLE
Question 26
J’ai invité 20 personnes. _______ ne peuvent pas venir.



CHOIX MULTIPLE
Question 27
Parmi ces robes, _______ sont très élégantes.



CHOIX MULTIPLE
Question 28
_______ étudiants ont déjà terminé l’examen.



RÉPONSES MULTIPLES
Question 29
Quels pronoms s’accordent en genre? (Plusieurs réponses)



CHOIX MULTIPLE
Question 30
_______ a le droit d’exprimer son opinion librement.



📊 Résultats de votre Quiz

🎓 Certificat de Réussite

CERTIFICAT D’EXCELLENCE

Exprimer son Opinion en Français

Ce certificat est décerné à

pour avoir complété avec succès le quiz B1
sur l’expression de l’opinion en français:

Opinions • Accord/Désaccord • Indicatif/Subjonctif • Hypothèses • Pronoms Indéfinis

Score obtenu:

Date:

⏳ Génération du PDF en cours…

document.addEventListener(‘DOMContentLoaded’, function() {
const totalQuestions = 30;
const passingScore = 70;

const subscriptionForm = document.getElementById(‘subscriptionForm’);
const exerciseContainer = document.getElementById(‘exerciseContainer’);
const startButton = document.getElementById(‘startButton’);
const verifyButton = document.getElementById(‘verifyButton’);
const resultContainer = document.getElementById(‘resultContainer’);
const scoreDisplay = document.getElementById(‘scoreDisplay’);
const resultText = document.getElementById(‘resultText’);
const mistakesContainer = document.getElementById(‘mistakesContainer’);
const showCertificateButton = document.getElementById(‘showCertificateButton’);
const certificateContainer = document.getElementById(‘certificateContainer’);
const downloadCertificateButton = document.getElementById(‘downloadCertificateButton’);
const pdfLoading = document.getElementById(‘pdfLoading’);
const progressFill = document.getElementById(‘progressFill’);

let userData = {
prenom: ”,
nom: ”,
email: ”,
score: 0
};

startButton.addEventListener(‘click’, function() {
if (validateForm()) {
subscriptionForm.style.display = ‘none’;
exerciseContainer.style.display = ‘block’;
exerciseContainer.scrollIntoView({ behavior: ‘smooth’ });
}
});

function validateForm() {
const prenom = document.getElementById(‘prenom’).value.trim();
const nom = document.getElementById(‘nom’).value.trim();
const email = document.getElementById(‘email’).value.trim();
const subscribe = document.getElementById(‘subscribe’).checked;

clearErrors();

let isValid = true;

if (!prenom) {
showError(‘prenomError’, ‘Veuillez entrer votre prénom’);
isValid = false;
}

if (!nom) {
showError(‘nomError’, ‘Veuillez entrer votre nom’);
isValid = false;
}

if (!email) {
showError(‘emailError’, ‘Veuillez entrer votre email’);
isValid = false;
} else if (!/^[^s@]+@[^s@]+.[^s@]+$/.test(email)) {
showError(‘emailError’, ‘Veuillez entrer un email valide’);
isValid = false;
}

if (!subscribe) {
showError(‘subscribeError’, ‘Veuillez accepter de vous abonner’);
isValid = false;
}

if (isValid) {
userData.prenom = prenom;
userData.nom = nom;
userData.email = email;
}

return isValid;
}

function clearErrors() {
const errorElements = [‘prenomError’, ‘nomError’, ‘emailError’, ‘subscribeError’];
errorElements.forEach(id => {
document.getElementById(id).textContent = ”;
});
}

function showError(elementId, message) {
document.getElementById(elementId).textContent = message;
}

function updateProgress() {
const answeredQuestions = getAnsweredQuestionsCount();
const progress = (answeredQuestions / totalQuestions) * 100;
progressFill.style.width = progress + ‘%’;
}

function getAnsweredQuestionsCount() {
let count = 0;

for (let i = 1; i 0) {
count++;
}
}

return count;
}

document.addEventListener(‘change’, updateProgress);
document.addEventListener(‘input’, updateProgress);

verifyButton.addEventListener(‘click’, function() {
const results = checkAnswers();
displayResults(results);
setTimeout(() => {
enviarResultadosAlServidor(results);
}, 1000);
});

function checkAnswers() {
let correctAnswers = 0;
const mistakes = [];
const questions = document.querySelectorAll(‘.question’);

questions.forEach((question, index) => {
const questionNum = index + 1;
const type = question.dataset.type;
const correctAnswer = question.dataset.answer;

let isCorrect = false;
let userAnswer = ”;
let correctText = ”;

if (type === ‘single’) {
const selectedRadio = question.querySelector(`input[name=”q${questionNum}”]:checked`);
if (selectedRadio) {
userAnswer = selectedRadio.value;
isCorrect = userAnswer === correctAnswer;

const options = question.querySelectorAll(‘.option’);
options.forEach(option => {
option.classList.remove(‘correct’, ‘incorrect’, ‘correct-answer’);
});

if (isCorrect) {
selectedRadio.closest(‘.option’).classList.add(‘correct’);
} else {
selectedRadio.closest(‘.option’).classList.add(‘incorrect’);
const correctOption = question.querySelector(`input[value=”${correctAnswer}”]`);
if (correctOption) {
correctOption.closest(‘.option’).classList.add(‘correct-answer’);
}
}
}
} else if (type === ‘multiple’) {
const selectedCheckboxes = question.querySelectorAll(`input[name=”q${questionNum}”]:checked`);
const selectedValues = Array.from(selectedCheckboxes).map(cb => cb.value).sort();
const correctValues = correctAnswer.split(‘,’).sort();

isCorrect = JSON.stringify(selectedValues) === JSON.stringify(correctValues);
userAnswer = selectedValues.join(‘, ‘);
correctText = correctValues.join(‘, ‘);
}

if (isCorrect) {
correctAnswers++;
} else {
const questionText = question.querySelector(‘.question-text’).textContent;
mistakes.push({
number: questionNum,
question: questionText,
userAnswer: userAnswer || ‘Non répondu’,
correctAnswer: correctText || correctAnswer
});
}
});

return {
correct: correctAnswers,
total: totalQuestions,
score: Math.round((correctAnswers / totalQuestions) * 100),
mistakes: mistakes
};
}

function displayResults(results) {
userData.score = results.score;

scoreDisplay.textContent = `${results.score}%`;
resultText.innerHTML = `Vous avez obtenu ${results.correct} réponses correctes sur ${results.total}.`;

mistakesContainer.innerHTML = ”;
if (results.mistakes.length > 0) {
const mistakesTitle = document.createElement(‘h4’);
mistakesTitle.textContent = `📝 Questions à revoir (${results.mistakes.length}):`;
mistakesContainer.appendChild(mistakesTitle);

results.mistakes.forEach(mistake => {
const mistakeItem = document.createElement(‘div’);
mistakeItem.style.cssText = `
margin-bottom: 15px;
padding: 15px;
background: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%);
border: 1px solid #ffeaa7;
border-radius: 8px;
border-left: 4px solid #f39c12;
`;
mistakeItem.innerHTML = `
Question ${mistake.number}:
${mistake.question}
Votre réponse: ${mistake.userAnswer}
Réponse correcte: ${mistake.correctAnswer}
`;
mistakesContainer.appendChild(mistakeItem);
});
} else {
mistakesContainer.innerHTML = ‘

🎉 Parfait ! Toutes vos réponses sont correctes !

‘;
}

const encouragementMsg = getEncouragementMessage(results.score);
const encouragementDiv = document.createElement(‘div’);
encouragementDiv.style.cssText = `
margin-top: 20px;
padding: 15px;
background: linear-gradient(135deg, #f0f8ff 0%, #e6f3ff 100%);
border-radius: 8px;
text-align: center;
font-style: italic;
color: #2c3e50;
`;
encouragementDiv.textContent = encouragementMsg;
resultText.appendChild(encouragementDiv);

if (results.score >= passingScore) {
showCertificateButton.style.display = ‘block’;
showCertificateButton.textContent = results.score === 100 ?
‘🏆 Certificat d’Excellence Parfaite’ :
‘🏆 Afficher mon certificat’;
} else {
showCertificateButton.style.display = ‘none’;
const encouragement = document.createElement(‘div’);
encouragement.style.cssText = `
margin-top: 20px;
padding: 15px;
background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
border-radius: 8px;
text-align: center;
`;
encouragement.innerHTML = `

💪 Continue tes efforts !

Il faut au moins ${passingScore}% pour obtenir le certificat. Révise et réessaie !

`;
mistakesContainer.appendChild(encouragement);
}

resultContainer.style.display = ‘block’;
resultContainer.scrollIntoView({ behavior: ‘smooth’ });
}

function getEncouragementMessage(score) {
if (score === 100) {
return “Parfait ! Vous maîtrisez parfaitement l’expression de l’opinion en français !”;
} else if (score >= 90) {
return “Excellent ! Vous avez une très bonne maîtrise de l’indicatif et du subjonctif !”;
} else if (score >= 80) {
return “Très bien ! Quelques révisions et vous serez parfait !”;
} else if (score >= 70) {
return “Bien ! Vous avez de bonnes bases. Continuez à pratiquer !”;
} else if (score >= 60) {
return “Pas mal ! Avec plus de pratique, vous progresserez rapidement !”;
} else {
return “Courage ! Continuez à étudier les modes et l’expression de l’opinion !”;}
}

showCertificateButton.addEventListener(‘click’, function() {
displayCertificate();
certificateContainer.style.display = ‘block’;
certificateContainer.scrollIntoView({ behavior: ‘smooth’ });
});

function displayCertificate() {
const now = new Date();
const dateString = now.toLocaleDateString(‘fr-FR’, {
year: ‘numeric’,
month: ‘long’,
day: ‘numeric’
});

document.getElementById(‘certificateName’).textContent =
`${userData.prenom} ${userData.nom}`;
document.getElementById(‘certificateScore’).textContent =
`${userData.score}%`;
document.getElementById(‘certificateDate’).textContent = dateString;
}

downloadCertificateButton.addEventListener(‘click’, function() {
downloadCertificate();
});

function downloadCertificate() {
pdfLoading.style.display = ‘block’;
downloadCertificateButton.disabled = true;

const certificatePreview = document.getElementById(‘certificatePreview’);

html2canvas(certificatePreview, {
scale: 2,
backgroundColor: ‘#ffffff’
}).then(canvas => {
const imgData = canvas.toDataURL(‘image/png’);
const { jsPDF } = window.jspdf;
const pdf = new jsPDF({
orientation: ‘landscape’,
unit: ‘mm’,
format: ‘a4’
});

const imgWidth = 297;
const imgHeight = (canvas.height * imgWidth) / canvas.width;

pdf.addImage(imgData, ‘PNG’, 0, 0, imgWidth, imgHeight);
pdf.save(`Certificat_${userData.prenom}_${userData.nom}.pdf`);

pdfLoading.style.display = ‘none’;
downloadCertificateButton.disabled = false;
}).catch(error => {
console.error(‘Erreur lors de la génération du PDF:’, error);
pdfLoading.style.display = ‘none’;
downloadCertificateButton.disabled = false;
alert(‘Erreur lors de la génération du certificat. Veuillez réessayer.’);
});
}

async function enviarResultadosAlServidor(results) {
const datosEnvio = {
prenom: userData.prenom,
nom: userData.nom,
email: userData.email,
score: results.score,
correct: results.correct,
total: results.total,
mistakes: results.mistakes
};

try {
const response = await fetch(‘TU_URL_DE_APPS_SCRIPT’, {
method: ‘POST’,
body: JSON.stringify(datosEnvio)
});

const resultado = await response.json();
console.log(resultado);

if (resultado.success) {
console.log(‘Datos guardados y correos enviados exitosamente’);
const confirmacion = document.createElement(‘div’);
confirmacion.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
background: #28a745;
color: white;
padding: 20px 30px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 9999;
animation: slideIn 0.5s ease;
`;
confirmacion.textContent = ‘✅ Correo enviado exitosamente a ‘ + userData.email;
document.body.appendChild(confirmacion);

setTimeout(() => confirmacion.remove(), 5000);
}
} catch (error) {
console.error(‘Error al enviar:’, error);
const errorDiv = document.createElement(‘div’);
errorDiv.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
background: #dc3545;
color: white;
padding: 20px 30px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 9999;
`;
errorDiv.textContent = ‘❌ Error al enviar los datos’;
document.body.appendChild(errorDiv);

setTimeout(() => errorDiv.remove(), 5000);
}
}
});