@3bbas/quizme
Version:
quizme is tool that help to generate a cli quiz from json file.
112 lines (95 loc) • 3.35 kB
text/typescript
import Enquirer from 'enquirer';
import chalk from 'chalk';
import { IQuizQ, IQuizResult } from './types';
import { displayResult, suffleQuestions } from './utils';
import { QuizTimer } from './timer';
var Table = require('cli-table3');
export class QuizRunner {
private questions: IQuizQ[];
private timer: QuizTimer;
private results: IQuizResult;
constructor(questions: IQuizQ[]) {
this.questions = suffleQuestions(questions);
this.timer = new QuizTimer();
this.results = {
correct: 0,
total: questions.length,
incorrect: [],
timeTaken: 0,
};
}
async start() {
console.log(chalk.blue.bold('\nStarting Quiz...'));
console.log(chalk.yellow(`Total questions: ${this.results.total}\n`));
for (const [index, question] of this.questions.entries()) {
await this.askQuestion(question, index + 1);
}
this.results.timeTaken = this.timer.getElapsedTime();
this.showFinalResults();
}
private async askQuestion(question: IQuizQ, qNum: number) {
if (!question.options || Object.keys(question.options).length === 0) {
console.log(chalk.red.bold(`Error: Question ${qNum} has no options to choose from.`));
return;
}
const choices = Object.entries(question.options).map(([key, value]) => ({
name: key,
message: `${key}) ${value}`,
value: key,
}));
if (choices.length === 0) {
console.log(chalk.red.bold(`Error: Question ${qNum} has no valid choices.`));
return;
}
const { answer } = await Enquirer.prompt<{ answer: string }>({
type: 'select',
name: 'answer',
message: chalk.bold(`Q${qNum}: ${question.question}`),
choices,
prefix: chalk.cyan('?'),
});
const isCorrect = answer.toLowerCase() === question.answer.toLowerCase();
if (isCorrect) {
this.results.correct++;
} else {
this.results.incorrect.push(question);
}
displayResult(isCorrect, question.answer);
}
private async showFinalResults() {
console.log(chalk.bold('\nQUIZ COMPLETE!\n'));
console.log(chalk.blue(`Time taken: ${this.timer.formatTime(this.results.timeTaken)}`));
console.log(chalk.green(`Correct answers: ${this.results.correct}/${this.results.total}`));
console.log(chalk.red(`Incorrect answers: ${this.results.incorrect.length}\n\n`));
if (this.results.incorrect.length > 0) {
const { check } = await Enquirer.prompt<{ check: boolean }>({
type: 'confirm',
name: 'chk',
initial: true,
message: 'Want to show incorrect answer?',
});
if (!check) {
var table = new Table({
head: [
{ colSpan: 2, hAlign: 'center', content: chalk.blue.bold('Review incorrect answers') },
],
colWidths: [5, 120],
wordWrap: true,
});
this.results.incorrect.forEach((q, i) => {
table.push([
`${i + 1}`,
chalk.bold(`${q.question}`) +
'\n' +
chalk.green(`✓ ${q.answer}) ${q.options[q.answer]}`),
]);
});
console.log(table.toString());
}
}
console.log('\n');
}
getResults(): IQuizResult {
return this.results;
}
}