Creating a Multiple-Choice Question (MCQ) generator can be a fun and educational project that highlights the power of JavaScript libraries. In this blog post, we'll walk through the process of building an MCQ generator that dynamically creates questions from a given paragraph. We'll explain the functions and dependencies involved, discuss the usefulness of such generators, provide a demo link, and conclude with the pros and cons of this approach.
Dependencies
To build our MCQ generator, we rely on two primary JavaScript libraries:
- Compromise: A lightweight natural language processing (NLP) library for extracting key information from the text.
- Faker.js: A library for generating random data, which we use to create plausible distractors for the MCQs.
You can include these libraries in your HTML file using the following script tags:
<script src="https://unpkg.com/compromise"></script>
<script src="https://cdn.jsdelivr.net/npm/faker@5.5.3/dist/faker.min.js"></script>
Functions
Our MCQ generator comprises several key functions:
1. extractKeySentences
This function uses the Compromise library to extract key sentences from the given paragraph. These sentences serve as the basis for generating questions.
function extractKeySentences(text) {
let doc = nlp(text);
let sentences = doc.sentences();
return sentences.out('array');
}
2. generateDistractors
This function generates context-aware distractors based on the keywords extracted from the paragraph. It ensures that the distractors are relevant and not too similar to the correct answer.
function generateDistractors(keyword, keywords) {
let distractors = [];
while (distractors.length < 3) {
let distractor = keywords[Math.floor(Math.random() * keywords.length)];
if (distractor !== keyword && !distractors.includes(distractor) && distractor.length > 3 && distractor.length <= 15) {
distractors.push(distractor);
}
}
return distractors;
}
3. createDynamicMCQ
This function combines the extracted sentences and generated distractors to create a set of MCQs. It replaces keywords with ellipses (...) to form questions and ensures that each question has a valid set of answer options.
function createDynamicMCQ(paragraph) {
const keySentences = extractKeySentences(paragraph);
const doc = nlp(paragraph);
const allKeywords = doc.nouns().out('array');
const questions = keySentences.map((sentence, index) => {
let sentenceDoc = nlp(sentence);
let keywords = sentenceDoc.nouns().out('array');
if (keywords.length === 0) keywords = sentenceDoc.terms().out('array');
let keyword = keywords.filter(word => word.length > 3 && word.length <= 15)[Math.floor(Math.random() * keywords.length)];
if (!keyword) {
keyword = "None of these";
}
let question = sentence.includes(keyword) ? sentence.replace(keyword, "...") : null;
let options = [keyword, ...generateDistractors(keyword, allKeywords)];
options = options.map(option => option ? option.charAt(0).toUpperCase() + option.slice(1) : "None of these");
options = options.sort(() => Math.random() - 0.5);
return {
question: question,
options: options,
answer: keyword.charAt(0).toUpperCase() + keyword.slice(1)
};
}).filter(mcq => mcq.question);
return questions;
}
4. displayMCQs
This function displays the generated MCQs in an HTML form, ensuring that each question is presented with its corresponding options.
function displayMCQs(mcqs) {
const mcqForm = document.getElementById('mcq-form');
mcqForm.innerHTML = "";
mcqs.forEach((mcq, index) => {
const questionDiv = document.createElement('div');
questionDiv.className = 'question';
const questionText = document.createElement('strong');
questionText.textContent = `${index + 1}. ${mcq.question}`;
questionDiv.appendChild(questionText);
const optionsDiv = document.createElement('div');
optionsDiv.className = 'options';
mcq.options.forEach((option, i) => {
const optionDiv = document.createElement('div');
optionDiv.className = 'form-check';
const optionInput = document.createElement('input');
optionInput.className = 'form-check-input';
optionInput.type = 'radio';
optionInput.name = `question${index}`;
optionInput.value = option;
optionInput.id = `question${index}_${i}`;
optionInput.required = true;
const optionLabel = document.createElement('label');
optionLabel.className = 'form-check-label';
optionLabel.htmlFor = `question${index}_${i}`;
optionLabel.textContent = option;
optionDiv.appendChild(optionInput);
optionDiv.appendChild(optionLabel);
optionsDiv.appendChild(optionDiv);
});
questionDiv.appendChild(optionsDiv);
mcqForm.appendChild(questionDiv);
});
}
5. generateMCQs
This function retrieves the paragraph input from a textarea, generates MCQs, and displays them on the page.
function generateMCQs() {
const paragraph = document.getElementById('input-paragraph').value;
mcqs = createDynamicMCQ(paragraph);
displayMCQs(mcqs);
}
6. submitForm
This function handles the form submission, checks if all questions are answered, calculates the score, and displays the result.
function submitForm() {
const mcqForm = document.getElementById('mcq-form');
const resultDiv = document.getElementById('result');
let score = 0;
let allAnswered = true;
mcqs.forEach((mcq, index) => {
const selectedOption = mcqForm.querySelector(`input[name="question${index}"]:checked`);
if (selectedOption && selectedOption.value === mcq.answer) {
score++;
} else if (!selectedOption) {
allAnswered = false;
}
});
if (allAnswered) {
resultDiv.textContent = `Your score: ${score} out of ${mcqs.length}`;
} else {
resultDiv.textContent = `Please complete all questions before submitting.`;
}
}
7. Prevent Page Reload
This function prevents the page from being reloaded to avoid losing data.
window.addEventListener('beforeunload', function (e) {
e.preventDefault();
e.returnValue = '';
});
Usefulness of the MCQ Generator
This type of MCQ generator can be incredibly useful in various contexts:
- Educational Tools: Teachers can quickly generate quizzes and practice tests for students based on study materials.
- E-learning Platforms: Online courses can dynamically create assessments to enhance interactive learning.
- Self-assessment: Learners can test their knowledge on specific topics by generating their own quizzes from textbooks or articles.
Live Demo
Check out the live demo here.
Conclusion
The dynamic MCQ generator we've built demonstrates the power of JavaScript libraries like Compromise and Faker.js in creating engaging and interactive content. By leveraging these libraries, we can automate the process of generating questions and enhance the learning experience for users.
Drawbacks
While this approach is effective, it does have some limitations:
- Contextual Accuracy: The generated questions may not always be perfectly accurate or relevant due to the limitations of the NLP library.
- Complex Sentences: The generator may struggle with complex sentences that contain multiple keywords or phrases.
- Limited Customization: The current implementation offers limited customization for question formatting and options.
Overall, this project showcases the potential of JavaScript libraries in building dynamic and useful educational tools. However, there is room for improvement and further development to address the identified limitations.
Happy coding
Leave a Reply