|
<template> |
|
<div id="app"> |
|
<h1>{{ gameTitle }}</h1> |
|
<div class="character"> |
|
<img :src="characterImage" alt="Character Image" /> |
|
<p>{{ characterName }}</p> |
|
<p>Puissance: {{ power }}</p> |
|
</div> |
|
<div v-if="currentQuestion < questions.length"> |
|
<div class="question">{{ questions[currentQuestion].question }}</div> |
|
<ul class="options"> |
|
<li |
|
v-for="(option, index) in questions[currentQuestion].options" |
|
:key="index" |
|
@click="selectOption(index)" |
|
:class="{ |
|
correct: option.isCorrect && selectedOption === index, |
|
incorrect: !option.isCorrect && selectedOption === index |
|
}" |
|
> |
|
{{ option.text }} |
|
</li> |
|
</ul> |
|
</div> |
|
<div v-else> |
|
<div class="score">Score: {{ score }}</div> |
|
<button @click="resetQuiz">Recommencer le Quiz</button> |
|
</div> |
|
<div class="cloud-button"> |
|
<a |
|
href="https://shiny-dollop-quizz-da86060a8495.herokuapp.com/" |
|
target="_blank" |
|
> |
|
<button class="cloud-btn">Try Harder Quiz</button> |
|
</a> |
|
</div> |
|
<div class="onboarding" v-if="showOnboarding"> |
|
<h2>Welcome to Quizz Flash Cards RPG!</h2> |
|
<p> |
|
Answer questions correctly to increase your score and character's power. |
|
If you answer incorrectly, your score and power will decrease. Advance |
|
through stages by completing all questions in the current stage. |
|
</p> |
|
<button @click="startGame">Start Game</button> |
|
</div> |
|
<footer> |
|
<p> |
|
Consultez mon |
|
<a href="https://github.com/kvnbbg" target="_blank">GitHub</a> |
|
et suivez-moi sur |
|
<a href="https://x.com/techandstream" target="_blank">Twitter</a> |
|
</p> |
|
</footer> |
|
</div> |
|
</template> |
|
|
|
<script> |
|
export default { |
|
data() { |
|
return { |
|
showOnboarding: true, |
|
gameTitle: "Quizz Flash Cards RPG", |
|
currentQuestion: 0, |
|
score: 0, |
|
selectedOption: null, |
|
characterName: "", |
|
characterImage: "", |
|
power: 0, |
|
questions: [], |
|
stage: -1, |
|
characterNames: [ |
|
"Elrond le Sage", |
|
"Gorbag le FΓ©roce", |
|
"Legolas le Rapide", |
|
"GrishnΓ‘kh le Brutal", |
|
"Arwen la Brave", |
|
"UglΓΊk le Fort" |
|
], |
|
characterImages: [ |
|
"https://images.pexels.com/photos/354951/pexels-photo-354951.jpeg", |
|
"https://images.pexels.com/photos/3115523/pexels-photo-3115523.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2", |
|
"https://images.pexels.com/photos/3115523/pexels-photo-3115523.jpeg?auto=compress&cs=tinysrgb&w=1200", |
|
"https://images.pexels.com/photos/17824134/pexels-photo-17824134/free-photo-of-hobbiton.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2", |
|
"https://media.istockphoto.com/id/104240543/fr/photo/portrait-de-lassistant.jpg?b=1&s=612x612&w=0&k=20&c=y4Fq7vDdXpYGMWBFjgriBkrx9lmRyItX5H0zywaww-8=", |
|
"https://media.istockphoto.com/id/1324198853/fr/photo/un-redoutable-guerrier-orque-court-%C3%A0-travers-la-for%C3%AAt-ensoleill%C3%A9e-pour-combattre-les-ennemis.jpg?b=1&s=612x612&w=0&k=20&c=4KgldeOcY_6vYHO0udiEop8HBE2tXidYZAaTEZjxST4=", |
|
"https://images.pexels.com/photos/16015770/pexels-photo-16015770/free-photo-of-rhume-froid-neige-femme.jpeg?auto=compress&cs=tinysrgb&w=1200" |
|
] |
|
}; |
|
}, |
|
methods: { |
|
startGame() { |
|
this.showOnboarding = false; |
|
}, |
|
getRandomItem(arr) { |
|
return arr[Math.floor(Math.random() * arr.length)]; |
|
}, |
|
getQuestionsByStage(stage) { |
|
const stages = { |
|
"-1": [ |
|
{ |
|
question: "Quelle est la diffΓ©rence entre HTML et HTML5 ?", |
|
options: [ |
|
{ |
|
text: "HTML5 est une version amΓ©liorΓ©e de HTML", |
|
isCorrect: true |
|
}, |
|
{ |
|
text: "HTML5 est une bibliothèque JavaScript", |
|
isCorrect: false |
|
}, |
|
{ |
|
text: |
|
"HTML5 est utilisΓ© uniquement pour les applications mobiles", |
|
isCorrect: false |
|
} |
|
] |
|
}, |
|
{ |
|
question: |
|
"Comment crΓ©ez-vous une page responsive avec CSS et Bootstrap ?", |
|
options: [ |
|
{ |
|
text: "En utilisant des media queries et des classes Bootstrap", |
|
isCorrect: true |
|
}, |
|
{ |
|
text: "En utilisant uniquement des tables HTML", |
|
isCorrect: false |
|
}, |
|
{ text: "En utilisant JavaScript", isCorrect: false } |
|
] |
|
} |
|
], |
|
0: [ |
|
{ |
|
question: |
|
"Comment fonctionne la gestion des sessions et des cookies en PHP ?", |
|
options: [ |
|
{ |
|
text: "En utilisant la fonction session_start() et des cookies", |
|
isCorrect: true |
|
}, |
|
{ |
|
text: "En utilisant uniquement des variables globales", |
|
isCorrect: false |
|
}, |
|
{ text: "En utilisant des fichiers XML", isCorrect: false } |
|
] |
|
}, |
|
{ |
|
question: |
|
"Quelle est la diffΓ©rence entre une fonction dΓ©clarΓ©e et une fonction flΓ©chΓ©e en JavaScript ?", |
|
options: [ |
|
{ |
|
text: "Les fonctions flΓ©chΓ©es ne lient pas leur propre this", |
|
isCorrect: true |
|
}, |
|
{ |
|
text: "Les fonctions dΓ©clarΓ©es ne peuvent pas Γͺtre anonymes", |
|
isCorrect: false |
|
}, |
|
{ |
|
text: "Les fonctions flΓ©chΓ©es sont plus lentes", |
|
isCorrect: false |
|
} |
|
] |
|
}, |
|
{ |
|
question: |
|
"Quel est le but de l'utilisation de Docker dans le dΓ©veloppement logiciel ?", |
|
options: [ |
|
{ |
|
text: |
|
"Conteneuriser les applications pour assurer leur portabilitΓ©", |
|
isCorrect: true |
|
}, |
|
{ |
|
text: "CrΓ©er des interfaces utilisateur dynamiques", |
|
isCorrect: false |
|
}, |
|
{ text: "GΓ©rer les versions du code source", isCorrect: false } |
|
] |
|
}, |
|
{ |
|
question: "Comment utilise-t-on les hooks dans React ?", |
|
options: [ |
|
{ |
|
text: |
|
"En appelant useState et useEffect Γ l'intΓ©rieur d'un composant fonctionnel", |
|
isCorrect: true |
|
}, |
|
{ |
|
text: "En crΓ©ant une classe hΓ©ritant de React.Component", |
|
isCorrect: false |
|
}, |
|
{ |
|
text: "En dΓ©finissant des mΓ©thodes dans le constructeur", |
|
isCorrect: false |
|
} |
|
] |
|
}, |
|
{ |
|
question: |
|
"Quelle est la principale utilisation de GraphQL dans une application web ?", |
|
options: [ |
|
{ |
|
text: |
|
"Interroger des APIs de manière plus flexible et efficace", |
|
isCorrect: true |
|
}, |
|
{ text: "GΓ©nΓ©rer des pages HTML", isCorrect: false }, |
|
{ text: "Styler les composants React", isCorrect: false } |
|
] |
|
}, |
|
{ |
|
question: "Qu'est-ce qu'un Promise en JavaScript ?", |
|
options: [ |
|
{ |
|
text: |
|
"Un objet représentant l'achèvement ou l'échec éventuel d'une opération asynchrone", |
|
isCorrect: true |
|
}, |
|
{ |
|
text: "Une fonction qui exécute du code de manière synchrone", |
|
isCorrect: false |
|
}, |
|
{ |
|
text: "Une bibliothèque pour gérer les états", |
|
isCorrect: false |
|
} |
|
] |
|
}, |
|
{ |
|
question: |
|
"Comment sΓ©curiser une application web contre les attaques XSS ?", |
|
options: [ |
|
{ |
|
text: |
|
"En Γ©chappant les entrΓ©es utilisateur avant de les afficher", |
|
isCorrect: true |
|
}, |
|
{ |
|
text: "En utilisant des mots de passe forts", |
|
isCorrect: false |
|
}, |
|
{ |
|
text: "En configurant correctement les pare-feux", |
|
isCorrect: false |
|
} |
|
] |
|
}, |
|
{ |
|
question: "Quel est le rΓ΄le de l'ORM (Object-Relational Mapping) ?", |
|
options: [ |
|
{ |
|
text: |
|
"Permettre de manipuler la base de donnΓ©es en utilisant des objets", |
|
isCorrect: true |
|
}, |
|
{ text: "Optimiser le rendu des pages HTML", isCorrect: false }, |
|
{ text: "GΓ©rer les appels API", isCorrect: false } |
|
] |
|
}, |
|
{ |
|
question: |
|
"Quel outil permet de gΓ©rer les versions de code source ?", |
|
options: [ |
|
{ text: "Git", isCorrect: true }, |
|
{ text: "Node.js", isCorrect: false }, |
|
{ text: "Webpack", isCorrect: false } |
|
] |
|
}, |
|
{ |
|
question: |
|
"Quelle est la commande pour dΓ©marrer un nouveau projet Vue.js avec Vue CLI ?", |
|
options: [ |
|
{ text: "vue create my-project", isCorrect: true }, |
|
{ text: "vue init my-project", isCorrect: false }, |
|
{ text: "npm start vue-app", isCorrect: false } |
|
] |
|
}, |
|
{ |
|
question: "Qu'est-ce qu'une Single Page Application (SPA) ?", |
|
options: [ |
|
{ |
|
text: |
|
"Une application web qui fonctionne sur une seule page sans rechargement complet", |
|
isCorrect: true |
|
}, |
|
{ |
|
text: "Une page web qui charge des fichiers JavaScript", |
|
isCorrect: false |
|
}, |
|
{ |
|
text: "Une application web avec une seule fonctionnalitΓ©", |
|
isCorrect: false |
|
} |
|
] |
|
}, |
|
{ |
|
question: |
|
"Comment Γ©crivez-vous une requΓͺte SQL pour joindre deux tables ?", |
|
options: [ |
|
{ |
|
text: |
|
"SELECT * FROM table1 JOIN table2 ON table1.id = table2.id", |
|
isCorrect: true |
|
}, |
|
{ text: "SELECT * FROM table1 UNION table2", isCorrect: false }, |
|
{ text: "SELECT * FROM table1, table2", isCorrect: false } |
|
] |
|
} |
|
], |
|
1: [ |
|
{ |
|
question: "Quelle est la dΓ©finition d'une API REST ?", |
|
options: [ |
|
{ |
|
text: |
|
"Une interface de programmation permettant l'Γ©change de donnΓ©es", |
|
isCorrect: true |
|
}, |
|
{ |
|
question: "Quelle est la diffΓ©rence entre SQL et NoSQL ?", |
|
options: [ |
|
{ |
|
text: "SQL est relationnel, NoSQL est non relationnel", |
|
isCorrect: true |
|
}, |
|
{ text: "SQL est plus rapide que NoSQL", isCorrect: false }, |
|
{ text: "NoSQL utilise des requΓͺtes SQL", isCorrect: false } |
|
] |
|
}, |
|
{ |
|
question: |
|
"Quel est le rΓ΄le du framework Angular dans une application web ?", |
|
options: [ |
|
{ |
|
text: "Construire des interfaces utilisateur dynamiques", |
|
isCorrect: true |
|
}, |
|
{ text: "GΓ©rer les bases de donnΓ©es", isCorrect: false }, |
|
{ text: "Faire des appels rΓ©seau", isCorrect: false } |
|
] |
|
}, |
|
{ |
|
question: |
|
"Quelle commande Git est utilisΓ©e pour cloner un dΓ©pΓ΄t ?", |
|
options: [ |
|
{ text: "git clone", isCorrect: true }, |
|
{ text: "git pull", isCorrect: false }, |
|
{ text: "git commit", isCorrect: false } |
|
] |
|
}, |
|
{ |
|
question: "Qu'est-ce qu'un composant en React ?", |
|
options: [ |
|
{ |
|
text: "Un Γ©lΓ©ment rΓ©utilisable de l'interface utilisateur", |
|
isCorrect: true |
|
}, |
|
{ text: "Un fichier de configuration", isCorrect: false }, |
|
{ text: "Une base de donnΓ©es", isCorrect: false } |
|
] |
|
}, |
|
{ |
|
question: |
|
"Quelle mΓ©thode JavaScript est utilisΓ©e pour filtrer les Γ©lΓ©ments d'un tableau ?", |
|
options: [ |
|
{ text: "Array.filter()", isCorrect: true }, |
|
{ text: "Array.map()", isCorrect: false }, |
|
{ text: "Array.reduce()", isCorrect: false } |
|
] |
|
}, |
|
{ |
|
question: "Comment installe-t-on une dΓ©pendance avec npm ?", |
|
options: [ |
|
{ text: "npm install <package>", isCorrect: true }, |
|
{ text: "npm get <package>", isCorrect: false }, |
|
{ text: "npm add <package>", isCorrect: false } |
|
] |
|
}, |
|
{ |
|
question: "Que signifie 'responsive design' ?", |
|
options: [ |
|
{ |
|
text: |
|
"Un design qui s'adapte Γ diffΓ©rentes tailles d'Γ©cran", |
|
isCorrect: true |
|
}, |
|
{ |
|
text: "Un design qui utilise des animations", |
|
isCorrect: false |
|
}, |
|
{ |
|
text: "Un design qui inclut des composants JavaScript", |
|
isCorrect: false |
|
} |
|
] |
|
}, |
|
{ |
|
question: |
|
"Quel est le rΓ΄le de Node.js dans le dΓ©veloppement web ?", |
|
options: [ |
|
{ |
|
text: "Permettre l'exΓ©cution de JavaScript cΓ΄tΓ© serveur", |
|
isCorrect: true |
|
}, |
|
{ text: "Styler les pages web", isCorrect: false }, |
|
{ text: "GΓ©rer les bases de donnΓ©es", isCorrect: false } |
|
] |
|
}, |
|
{ |
|
question: |
|
"Quelle est la syntaxe correcte pour crΓ©er une fonction asynchrone en JavaScript ?", |
|
options: [ |
|
{ text: "async function maFonction() {}", isCorrect: true }, |
|
{ text: "function async maFonction() {}", isCorrect: false }, |
|
{ text: "async: maFonction() {}", isCorrect: false } |
|
] |
|
}, |
|
{ |
|
question: "Quel est l'objectif principal du framework Vue.js ?", |
|
options: [ |
|
{ |
|
text: "CrΓ©er des interfaces utilisateur interactives", |
|
isCorrect: true |
|
}, |
|
{ text: "GΓ©rer les requΓͺtes HTTP", isCorrect: false }, |
|
{ text: "Configurer les bases de donnΓ©es", isCorrect: false } |
|
] |
|
}, |
|
{ text: "Un serveur web", isCorrect: false }, |
|
{ text: "Un type de base de donnΓ©es", isCorrect: false } |
|
] |
|
}, |
|
{ |
|
question: "Qu'est-ce que le test UAT ?", |
|
options: [ |
|
{ text: "User Acceptance Testing", isCorrect: true }, |
|
{ text: "Unit Acceptance Testing", isCorrect: false }, |
|
{ text: "Universal Acceptance Testing", isCorrect: false } |
|
] |
|
} |
|
] |
|
}; |
|
return stages[stage] || stages[-1]; |
|
}, |
|
selectOption(index) { |
|
if (this.selectedOption === null) { |
|
this.selectedOption = index; |
|
if (this.questions[this.currentQuestion].options[index].isCorrect) { |
|
this.score += 10; |
|
this.power += Math.floor(Math.random() * 10) + 1; |
|
} else { |
|
this.score -= 5; |
|
this.power -= Math.floor(Math.random() * 10) + 1; |
|
} |
|
setTimeout(() => { |
|
this.currentQuestion++; |
|
this.selectedOption = null; |
|
if (this.currentQuestion >= this.questions.length) { |
|
this.stage++; |
|
this.questions = this.getQuestionsByStage(this.stage); |
|
this.currentQuestion = 0; |
|
} |
|
}, 1000); |
|
} |
|
}, |
|
resetQuiz() { |
|
this.stage = -1; |
|
this.currentQuestion = 0; |
|
this.score = 0; |
|
this.selectedOption = null; |
|
this.characterName = this.getRandomItem(this.characterNames); |
|
this.characterImage = this.getRandomItem(this.characterImages); |
|
this.power = Math.floor(Math.random() * 100) + 1; |
|
this.questions = this.getQuestionsByStage(this.stage); |
|
} |
|
}, |
|
mounted() { |
|
this.characterName = this.getRandomItem(this.characterNames); |
|
this.characterImage = this.getRandomItem(this.characterImages); |
|
this.power = Math.floor(Math.random() * 100) + 1; |
|
this.questions = this.getQuestionsByStage(this.stage); |
|
} |
|
}; |
|
</script> |
|
|
|
<!-- Use preprocessors via the lang attribute! e.g. <style lang="scss"> --> |
|
<style> |
|
#app { |
|
font-family: Avenir, Helvetica, Arial, sans-serif; |
|
text-align: center; |
|
color: #2c3e50; |
|
margin-top: 60px; |
|
background: #fff; |
|
border-radius: 10px; |
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); |
|
padding: 20px; |
|
width: 90%; |
|
max-width: 600px; |
|
margin: 20px auto; |
|
transition: all 0.3s ease; |
|
} |
|
|
|
h1 { |
|
font-size: 2em; |
|
margin-bottom: 20px; |
|
} |
|
|
|
.question { |
|
font-size: 1.2em; |
|
margin-bottom: 20px; |
|
} |
|
|
|
.options { |
|
list-style: none; |
|
padding: 0; |
|
} |
|
|
|
.options li { |
|
background: #ececec; |
|
border: 1px solid #ddd; |
|
margin: 10px 0; |
|
padding: 15px; |
|
cursor: pointer; |
|
border-radius: 5px; |
|
transition: background 0.3s, color 0.3s; |
|
} |
|
|
|
.options li.correct { |
|
background: #d4edda; |
|
color: #155724; |
|
} |
|
|
|
.options li.incorrect { |
|
background: #f8d7da; |
|
color: #721c24; |
|
} |
|
|
|
.options li:hover { |
|
background: #d1e0e0; |
|
} |
|
|
|
.score { |
|
font-size: 1.5em; |
|
margin-top: 20px; |
|
} |
|
|
|
.character { |
|
font-size: 1.2em; |
|
margin-top: 10px; |
|
margin-bottom: 20px; |
|
} |
|
|
|
.character img { |
|
width: 100px; |
|
height: 100px; |
|
border-radius: 50%; |
|
} |
|
|
|
footer { |
|
margin-top: 20px; |
|
} |
|
|
|
footer a { |
|
color: #4fc08d; |
|
text-decoration: none; |
|
} |
|
.cloud-button { |
|
position: fixed; |
|
bottom: 20px; |
|
right: 20px; |
|
animation: float 5s ease-in-out infinite; |
|
} |
|
|
|
.cloud-btn { |
|
background: #e0f7fa; |
|
border: 1px solid #b2ebf2; |
|
color: #00796b; |
|
font-size: 16px; |
|
padding: 10px 20px; |
|
border-radius: 50px; |
|
cursor: pointer; |
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); |
|
transition: background 0.3s, transform 0.3s; |
|
} |
|
|
|
.cloud-btn:hover { |
|
background: #b2ebf2; |
|
transform: translateY(-5px); |
|
} |
|
|
|
@keyframes float { |
|
0% { |
|
transform: translateY(0); |
|
} |
|
50% { |
|
transform: translateY(-10px); |
|
} |
|
100% { |
|
transform: translateY(0); |
|
} |
|
} |
|
|
|
.onboarding { |
|
position: fixed; |
|
top: 0; |
|
left: 0; |
|
width: 100%; |
|
height: 100%; |
|
background: rgba(0, 0, 0, 0.7); |
|
color: #fff; |
|
display: flex; |
|
flex-direction: column; |
|
align-items: center; |
|
justify-content: center; |
|
text-align: center; |
|
padding: 20px; |
|
} |
|
|
|
.onboarding h2 { |
|
font-size: 2em; |
|
margin-bottom: 20px; |
|
} |
|
|
|
.onboarding p { |
|
font-size: 1.2em; |
|
margin-bottom: 20px; |
|
} |
|
|
|
.onboarding button { |
|
background: #4fc08d; |
|
color: #fff; |
|
border: none; |
|
padding: 10px 20px; |
|
border-radius: 5px; |
|
cursor: pointer; |
|
font-size: 1em; |
|
transition: background 0.3s; |
|
} |
|
|
|
.onboarding button:hover { |
|
background: #3da76f; |
|
} |
|
</style> |