├── .gitignore ├── vercel.json ├── package.json ├── README.md ├── index.js └── public ├── style.css ├── vanta.waves.min.js └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "builds": [ 4 | { 5 | "src": "index.js", 6 | "use": "@vercel/node", 7 | "config": { "includeFiles": ["dist/**"] } 8 | } 9 | ], 10 | "routes": [ 11 | { 12 | "src": "/(.*)", 13 | "dest": "index.js" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yt-quiz-generator", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "dev": "nodemon index.js", 9 | "start": "node index.js" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "@google/generative-ai": "^0.12.0", 16 | "dotenv": "^16.4.5", 17 | "express": "^4.19.2" 18 | }, 19 | "devDependencies": { 20 | "nodemon": "^3.1.2" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AIQuizGen 2 | 3 | AIQuizGen is a web application that allows users to generate quizzes using topic names. Leveraging AI technology, the application automatically creates engaging and educational quizzes based on the provided content. 4 | 5 | ## Features 6 | 7 | - *Topic-Based Quizzes*: Create quizzes by specifying a topic name. 8 | - *AI-Powered*: Utilizes AI to generate accurate and relevant quiz questions. 9 | - *Difficulty Levels*: Choose the difficulty level (easy, medium, hard) for the quiz. 10 | - *Customizable Number of Questions*: Select how many questions you want in the quiz. 11 | - *User-Friendly Interface*: Easy-to-use platform for both quiz creators and participants. 12 | 13 | ## Getting Started 14 | 15 | ### Prerequisites 16 | 17 | - Web browser (e.g., Chrome, Firefox, Safari) 18 | 19 | ### Usage 20 | 21 | 1. *Generate Quiz from Topic*: 22 | - Enter a topic name. 23 | - Select difficulty level (easy, medium, hard). 24 | - Choose the number of questions. 25 | - Click "Generate Quiz". 26 | - The AI will create a quiz based on the selected options. 27 | 28 | ## Contributing 29 | 30 | We welcome contributions! Please fork the repository and submit a pull request. 31 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | const express = require("express"); 3 | const { GoogleGenerativeAI } = require("@google/generative-ai"); 4 | const path = require("path"); 5 | 6 | const app = express(); 7 | const port = process.env.PORT || 3000; 8 | 9 | const genAI = new GoogleGenerativeAI(process.env.API_KEY); 10 | 11 | app.use(express.static(path.join(__dirname, "public"))); 12 | app.use(express.json()); 13 | app.post("/generate-quiz", async (req, res) => { 14 | const { topic, difficulty, numberOfQuestions } = req.body; 15 | try { 16 | const model = genAI.getGenerativeModel({ 17 | model: "gemini-1.5-flash-latest", 18 | }); 19 | const prompt = `You are an expert quiz generator specializing in educational content. Your task is to create a well-structured, engaging, and informative quiz based on the following parameters: 20 | Topic: ${topic} 21 | Difficulty level: ${difficulty} 22 | Number of questions: ${numberOfQuestions} 23 | Please follow these guidelines: 24 | 25 | Assess the topic: 26 | 27 | Ensure the topic is educational and appropriate for quiz creation. 28 | If the topic is not educational or suitable, respond with: 29 | {"error": "Unfortunately, this topic does not meet the standards of educational content."} 30 | 31 | 32 | Create the quiz: 33 | If the topic is suitable, generate a quiz adhering to these criteria: 34 | a. Title: Create a concise, relevant title that accurately reflects the quiz content. 35 | b. Questions: Formulate clear, unambiguous questions that align with the specified difficulty level. 36 | c. Options: Provide exactly 4 options (A, B, C, D) for each question. 37 | d. Correct answer: Clearly indicate the correct option. 38 | e. Explanation: Offer a brief, informative explanation for the correct answer. 39 | Ensure variety: 40 | 41 | Mix different types of questions (e.g., multiple-choice, true/false formatted as multiple-choice, fill-in-the-blank presented as multiple-choice). 42 | Cover various aspects of the topic to provide a comprehensive assessment. 43 | 44 | 45 | Maintain consistency: 46 | 47 | Use a uniform style and formatting throughout the quiz. 48 | Ensure all questions have only 4 options. 49 | 50 | 51 | Tailor to difficulty level: 52 | 53 | Adjust the complexity of questions, vocabulary, and concepts to match the specified difficulty level. 54 | 55 | 56 | Verify accuracy: 57 | 58 | Double-check all information for factual correctness. 59 | Ensure there is only one unambiguously correct answer per question. 60 | 61 | 62 | Output format: 63 | Present the quiz in the following JSON format: 64 | { 65 | "title": "Title of the Quiz", 66 | "quizzes": [ 67 | { 68 | "question": "Question", 69 | "options": ["Option A", "Option B", "Option C", "Option D"], 70 | "correct_option": "Option A", 71 | "explanation": "Explanation of the correct answer" 72 | } 73 | ] 74 | } 75 | Final check: 76 | 77 | Confirm that the number of questions matches ${numberOfQuestions}. 78 | Verify that each question has exactly 4 options. 79 | Ensure the JSON structure is valid and properly formatted. 80 | `; 81 | 82 | const result = await model.generateContent(prompt); 83 | const text = result.response.text(); 84 | const jsonString = text.replace(/^```json\s*|```$/g, ""); 85 | res.json(JSON.parse(jsonString)); 86 | } catch (e) { 87 | console.error(e); 88 | res 89 | .status(500) 90 | .json({ 91 | error: 92 | "Sorry, the request can't be processed at this moment. Please try again.", 93 | }); 94 | } 95 | }); 96 | 97 | app.listen(port, () => { 98 | console.log(`Server is running on port ${port}`); 99 | }); 100 | -------------------------------------------------------------------------------- /public/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap'); 2 | 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | box-sizing: border-box; 7 | } 8 | 9 | body { 10 | background: #0f0f0f; 11 | font-family: 'Poppins', sans-serif; 12 | color: #f0f0f0; 13 | line-height: 1.6; 14 | height: 120vh 15 | } 16 | .header { 17 | font-size: 4rem; 18 | } 19 | .home-div, 20 | .quiz-div { 21 | display: flex; 22 | flex-direction: column; 23 | align-items: center; 24 | justify-content: center; 25 | gap: 2rem; 26 | max-width: 600px; 27 | width: 100%; 28 | padding: 2rem; 29 | margin: 0 auto; 30 | min-height: 100vh; 31 | } 32 | 33 | h1 { 34 | font-size: 3.5rem; 35 | font-weight: 700; 36 | text-align: center; 37 | } 38 | 39 | .text { 40 | color: #b0b0b0; 41 | text-align: center; 42 | font-size: 1rem; 43 | max-width: 450px; 44 | } 45 | 46 | .select-div { 47 | width: 100%; 48 | display: flex; 49 | justify-content: space-between; 50 | gap: 1rem; 51 | margin-bottom: 1rem; 52 | } 53 | 54 | .gradient-text { 55 | background: linear-gradient(135deg, #f8f8f8, #c0c0c0); 56 | -webkit-background-clip: text; 57 | background-clip: text; 58 | -webkit-text-fill-color: transparent; 59 | } 60 | 61 | #topic, 62 | .selectOptions { 63 | padding: 1rem; 64 | width: 100%; 65 | border-radius: 0.5rem; 66 | border: 1px solid #333; 67 | background-color: #ffffff; 68 | color: #000000; 69 | font-size: 1rem; 70 | transition: all 0.3s ease; 71 | } 72 | 73 | #topic:focus, 74 | #difficulty:focus { 75 | outline: none; 76 | border-color: #ffffff; 77 | box-shadow: 0 0 0 2px rgba(0, 114, 255, 0.2); 78 | } 79 | 80 | .gradient-btn { 81 | background: linear-gradient(135deg, #f8f8f8, #c0c0c0); 82 | color: black; 83 | font-weight: 600; 84 | padding: 1rem 2rem; 85 | border-radius: 0.5rem; 86 | border: none; 87 | cursor: pointer; 88 | width: 100%; 89 | transition: all 0.3s ease; 90 | } 91 | 92 | .gradient-btn:hover { 93 | opacity: 0.8; 94 | } 95 | 96 | #generateBtn:disabled { 97 | opacity: 0.5; 98 | cursor: not-allowed; 99 | } 100 | 101 | .quiz-container { 102 | background: #1a1a1a; 103 | padding: 2rem; 104 | border-radius: 1rem; 105 | box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); 106 | width: 100%; 107 | max-width: 600px; 108 | } 109 | 110 | .quiz { 111 | display: flex; 112 | flex-direction: column; 113 | align-items: center; 114 | gap: 1.5rem; 115 | } 116 | 117 | #quizTitle { 118 | font-size: 1.5rem; 119 | font-weight: 600; 120 | text-align: center; 121 | margin-bottom: 1.5rem; 122 | } 123 | 124 | .question-num { 125 | background-color: #2a2a2a; 126 | font-size: 0.8rem; 127 | border-radius: 2rem; 128 | padding: 0.5rem 1rem; 129 | text-align: center; 130 | } 131 | 132 | .question { 133 | font-size: 1.2rem; 134 | color: #f0f0f0; 135 | text-align: center; 136 | } 137 | 138 | .options { 139 | display: grid; 140 | gap: 1rem; 141 | width: 100%; 142 | } 143 | 144 | .option { 145 | background-color: #2a2a2a; 146 | border-radius: 0.5rem; 147 | padding: 1rem; 148 | width: 100%; 149 | text-align: left; 150 | cursor: pointer; 151 | transition: all 0.3s ease; 152 | border: none; 153 | color: #f0f0f0; 154 | } 155 | 156 | .option:hover { 157 | background-color: #333; 158 | } 159 | 160 | .correct-answer { 161 | background-color: rgba(0, 255, 0, 0.1); 162 | border: 1px solid #00ff00; 163 | } 164 | 165 | .incorrect-answer { 166 | background-color: rgba(255, 0, 0, 0.1); 167 | border: 1px solid #ff0000; 168 | } 169 | 170 | .scoreDiv { 171 | text-align: center; 172 | font-weight: 600; 173 | font-size: 1.2rem; 174 | margin-top: 2rem; 175 | } 176 | 177 | .explanationDiv { 178 | background-color: #2a2a2a; 179 | border-radius: 0.5rem; 180 | padding: 1rem; 181 | margin-top: 1.5rem; 182 | font-size: 0.9rem; 183 | width: 100%; 184 | } 185 | 186 | .hidden { 187 | display: none; 188 | } 189 | 190 | .chart-container { 191 | width: 100%; 192 | max-width: 300px; 193 | margin: 2rem auto; 194 | } 195 | 196 | .decorators { 197 | display: none; 198 | /* Removed for a cleaner look, can be re-enabled if desired */ 199 | } 200 | 201 | @media screen and (max-width: 480px) { 202 | h1 { 203 | font-size: 2rem; 204 | } 205 | 206 | .home-div, 207 | .quiz-div { 208 | padding: 1.5rem; 209 | } 210 | 211 | #quizTitle { 212 | font-size: 1.3rem; 213 | } 214 | 215 | .question { 216 | font-size: 1.1rem; 217 | } 218 | 219 | #topic, 220 | #difficulty { 221 | width: 100%; 222 | } 223 | } -------------------------------------------------------------------------------- /public/vanta.waves.min.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports._vantaEffect=e():t._vantaEffect=e()}("undefined"!=typeof self?self:this,(()=>(()=>{"use strict";var t={d:(e,i)=>{for(var s in i)t.o(i,s)&&!t.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:i[s]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};function i(t,e){return null==t&&(t=0),null==e&&(e=1),Math.floor(t+Math.random()*(e-t+1))}t.r(e),t.d(e,{default:()=>c}),Number.prototype.clamp=function(t,e){return Math.min(Math.max(this,t),e)};function s(t){for(;t.children&&t.children.length>0;)s(t.children[0]),t.remove(t.children[0]);t.geometry&&t.geometry.dispose(),t.material&&(Object.keys(t.material).forEach((e=>{t.material[e]&&null!==t.material[e]&&"function"==typeof t.material[e].dispose&&t.material[e].dispose()})),t.material.dispose())}const o="object"==typeof window;let n=o&&window.THREE||{};o&&!window.VANTA&&(window.VANTA={});const r=o&&window.VANTA||{};r.register=(t,e)=>r[t]=t=>new e(t),r.version="0.5.24";const h=function(){return Array.prototype.unshift.call(arguments,"[VANTA]"),console.error.apply(this,arguments)};r.VantaBase=class{constructor(t={}){if(!o)return!1;r.current=this,this.windowMouseMoveWrapper=this.windowMouseMoveWrapper.bind(this),this.windowTouchWrapper=this.windowTouchWrapper.bind(this),this.windowGyroWrapper=this.windowGyroWrapper.bind(this),this.resize=this.resize.bind(this),this.animationLoop=this.animationLoop.bind(this),this.restart=this.restart.bind(this);const e="function"==typeof this.getDefaultOptions?this.getDefaultOptions():this.defaultOptions;if(this.options=Object.assign({mouseControls:!0,touchControls:!0,gyroControls:!1,minHeight:200,minWidth:200,scale:1,scaleMobile:1},e),(t instanceof HTMLElement||"string"==typeof t)&&(t={el:t}),Object.assign(this.options,t),this.options.THREE&&(n=this.options.THREE),this.el=this.options.el,null==this.el)h('Instance needs "el" param!');else if(!(this.options.el instanceof HTMLElement)){const t=this.el;if(this.el=(i=t,document.querySelector(i)),!this.el)return void h("Cannot find element",t)}var i,s;this.prepareEl(),this.initThree(),this.setSize();try{this.init()}catch(t){return h("Init error",t),this.renderer&&this.renderer.domElement&&this.el.removeChild(this.renderer.domElement),void(this.options.backgroundColor&&(console.log("[VANTA] Falling back to backgroundColor"),this.el.style.background=(s=this.options.backgroundColor,"number"==typeof s?"#"+("00000"+s.toString(16)).slice(-6):s)))}this.initMouse(),this.resize(),this.animationLoop();const a=window.addEventListener;a("resize",this.resize),window.requestAnimationFrame(this.resize),this.options.mouseControls&&(a("scroll",this.windowMouseMoveWrapper),a("mousemove",this.windowMouseMoveWrapper)),this.options.touchControls&&(a("touchstart",this.windowTouchWrapper),a("touchmove",this.windowTouchWrapper)),this.options.gyroControls&&a("deviceorientation",this.windowGyroWrapper)}setOptions(t={}){Object.assign(this.options,t),this.triggerMouseMove()}prepareEl(){let t,e;if("undefined"!=typeof Node&&Node.TEXT_NODE)for(t=0;t=0&&s>=0&&i<=e.width&&s<=e.height&&(this.mouseX=i,this.mouseY=s,this.options.mouseEase||this.triggerMouseMove(i,s))}windowTouchWrapper(t){const e=this.getCanvasRect();if(!e)return!1;if(1===t.touches.length){const i=t.touches[0].clientX-e.left,s=t.touches[0].clientY-e.top;i>=0&&s>=0&&i<=e.width&&s<=e.height&&(this.mouseX=i,this.mouseY=s,this.options.mouseEase||this.triggerMouseMove(i,s))}}windowGyroWrapper(t){const e=this.getCanvasRect();if(!e)return!1;const i=Math.round(2*t.alpha)-e.left,s=Math.round(2*t.beta)-e.top;i>=0&&s>=0&&i<=e.width&&s<=e.height&&(this.mouseX=i,this.mouseY=s,this.options.mouseEase||this.triggerMouseMove(i,s))}triggerMouseMove(t,e){void 0===t&&void 0===e&&(this.options.mouseEase?(t=this.mouseEaseX,e=this.mouseEaseY):(t=this.mouseX,e=this.mouseY)),this.uniforms&&(this.uniforms.iMouse.value.x=t/this.scale,this.uniforms.iMouse.value.y=e/this.scale);const i=t/this.width,s=e/this.height;"function"==typeof this.onMouseMove&&this.onMouseMove(i,s)}setSize(){this.scale||(this.scale=1),"undefined"!=typeof navigator&&(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)||window.innerWidth<600)&&this.options.scaleMobile?this.scale=this.options.scaleMobile:this.options.scale&&(this.scale=this.options.scale),this.width=Math.max(this.el.offsetWidth,this.options.minWidth),this.height=Math.max(this.el.offsetHeight,this.options.minHeight)}initMouse(){(!this.mouseX&&!this.mouseY||this.mouseX===this.options.minWidth/2&&this.mouseY===this.options.minHeight/2)&&(this.mouseX=this.width/2,this.mouseY=this.height/2,this.triggerMouseMove(this.mouseX,this.mouseY))}resize(){this.setSize(),this.camera&&(this.camera.aspect=this.width/this.height,"function"==typeof this.camera.updateProjectionMatrix&&this.camera.updateProjectionMatrix()),this.renderer&&(this.renderer.setSize(this.width,this.height),this.renderer.setPixelRatio(window.devicePixelRatio/this.scale)),"function"==typeof this.onResize&&this.onResize()}isOnScreen(){const t=this.el.offsetHeight,e=this.el.getBoundingClientRect(),i=window.pageYOffset||(document.documentElement||document.body.parentNode||document.body).scrollTop,s=e.top+i;return s-window.innerHeight<=i&&i<=s+t}animationLoop(){this.t||(this.t=0),this.t2||(this.t2=0);const t=performance.now();if(this.prevNow){let e=(t-this.prevNow)/(1e3/60);e=Math.max(.2,Math.min(e,5)),this.t+=e,this.t2+=(this.options.speed||1)*e,this.uniforms&&(this.uniforms.iTime.value=.016667*this.t2)}return this.prevNow=t,this.options.mouseEase&&(this.mouseEaseX=this.mouseEaseX||this.mouseX||0,this.mouseEaseY=this.mouseEaseY||this.mouseY||0,Math.abs(this.mouseEaseX-this.mouseX)+Math.abs(this.mouseEaseY-this.mouseY)>.1&&(this.mouseEaseX+=.05*(this.mouseX-this.mouseEaseX),this.mouseEaseY+=.05*(this.mouseY-this.mouseEaseY),this.triggerMouseMove(this.mouseEaseX,this.mouseEaseY))),(this.isOnScreen()||this.options.forceAnimate)&&("function"==typeof this.onUpdate&&this.onUpdate(),this.scene&&this.camera&&(this.renderer.render(this.scene,this.camera),this.renderer.setClearColor(this.options.backgroundColor,this.options.backgroundAlpha)),this.fps&&this.fps.update&&this.fps.update(),"function"==typeof this.afterRender&&this.afterRender()),this.req=window.requestAnimationFrame(this.animationLoop)}restart(){if(this.scene)for(;this.scene.children.length;)this.scene.remove(this.scene.children[0]);"function"==typeof this.onRestart&&this.onRestart(),this.init()}init(){"function"==typeof this.onInit&&this.onInit()}destroy(){"function"==typeof this.onDestroy&&this.onDestroy();const t=window.removeEventListener;t("touchstart",this.windowTouchWrapper),t("touchmove",this.windowTouchWrapper),t("scroll",this.windowMouseMoveWrapper),t("mousemove",this.windowMouseMoveWrapper),t("deviceorientation",this.windowGyroWrapper),t("resize",this.resize),window.cancelAnimationFrame(this.req);const e=this.scene;e&&e.children&&s(e),this.renderer&&(this.renderer.domElement&&this.el.removeChild(this.renderer.domElement),this.renderer=null,this.scene=null),r.current===this&&(r.current=null)}};const a=r.VantaBase;let p="object"==typeof window&&window.THREE;class l extends a{static initClass(){this.prototype.ww=100,this.prototype.hh=80,this.prototype.waveNoise=4}constructor(t){p=t.THREE||p,super(t)}getMaterial(){const t={color:this.options.color,shininess:this.options.shininess,flatShading:!0,side:p.DoubleSide};return new p.MeshPhongMaterial(t)}onInit(){let t,e;const s=this.getMaterial(),o=new p.BufferGeometry;this.gg=[];const n=[];for(t=0;t<=this.ww;t++)for(this.gg[t]=[],e=0;e<=this.hh;e++){const i=n.length,s=new p.Vector3(18*(t-.5*this.ww),(null==(r=0)&&(r=0),null==(h=this.waveNoise)&&(h=1),r+Math.random()*(h-r)-10),18*(.5*this.hh-e));n.push(s),this.gg[t][e]=i}var r,h;o.setFromPoints(n);const a=[];for(t=1;t<=this.ww;t++)for(e=1;e<=this.hh;e++){let s,o;const n=this.gg[t][e],r=this.gg[t][e-1],h=this.gg[t-1][e],p=this.gg[t-1][e-1];i(0,1)?(s=[p,r,h],o=[r,h,n]):(s=[p,r,n],o=[p,h,n]),a.push(...s,...o)}o.setIndex(a),this.plane=new p.Mesh(o,s),this.scene.add(this.plane);const l=new p.AmbientLight(16777215,.9);this.scene.add(l);const c=new p.PointLight(16777215,.9);c.position.set(-100,250,-100),this.scene.add(c),this.camera=new p.PerspectiveCamera(35,this.width/this.height,50,1e4),this.cameraPosition=new p.Vector3(240,200,390),this.cameraTarget=new p.Vector3(140,-30,190),this.camera.position.copy(this.cameraPosition),this.scene.add(this.camera)}onUpdate(){let t;this.plane.material.color.set(this.options.color),this.plane.material.shininess=this.options.shininess,this.camera.ox=this.cameraPosition.x/this.options.zoom,this.camera.oy=this.cameraPosition.y/this.options.zoom,this.camera.oz=this.cameraPosition.z/this.options.zoom,null!=this.controls&&this.controls.update();const e=this.camera;Math.abs(e.tx-e.position.x)>.01&&(t=e.tx-e.position.x,e.position.x+=.02*t),Math.abs(e.ty-e.position.y)>.01&&(t=e.ty-e.position.y,e.position.y+=.02*t),Math.abs(e.tz-e.position.z)>.01&&(t=e.tz-e.position.z,e.position.z+=.02*t),e.lookAt(this.cameraTarget),this.oy=this.oy||{};for(let t=0;t 2 | 3 | 4 | 5 | 6 | AI Quiz Generator 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |

15 | Topic Based Quiz
16 | Generator 17 |

18 |

📜Enter Topic 📝 Generate Quiz 🧠 Test Yourself

19 | 26 |
27 |
28 | 29 | 34 |
35 |
36 | 37 | 45 |
46 |
47 | 50 |
51 | 107 |
108 |
109 | 110 | 111 | 296 | 297 | 298 | --------------------------------------------------------------------------------