cli-prep
Version:
A fun and interactive command-line interview preparation game to test your programming knowledge with 80+ questions across multiple categories!
192 lines (158 loc) ⢠6.67 kB
JavaScript
import chalk from 'chalk';
import chalkAnimation from 'chalk-animation';
import gradient from 'gradient-string';
import figlet from 'figlet';
import inquirer from 'inquirer';
import { createSpinner } from 'nanospinner';
import { questionBank } from './questions.js';
import { getPersonalizedFeedback, getCategoryAnalysis, getMotivationalMessage } from './feedback.js';
let playerName;
let score = 0;
let currentQuestion = 0;
let selectedQuestions = [];
let numQuestions = 0;
let categoryStats = {};
const sleep = (ms = 1000) => new Promise(resolve => setTimeout(resolve, ms));
// Function to shuffle array
function shuffleArray(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
// Function to get random questions
function getRandomQuestions(count) {
const shuffled = shuffleArray(questionBank);
return shuffled.slice(0, count);
}
async function welcome() {
const rainbowTitle = chalkAnimation.rainbow('Welcome to the CLI Prep Game!');
await sleep(2000);
rainbowTitle.stop();
console.log(chalk.blueBright(figlet.textSync('CLI Prep', { horizontalLayout: 'full' })));
console.log(chalk.cyan(`šÆ Test your knowledge with ${questionBank.length}+ programming questions!`));
console.log(chalk.yellow('š Categories: Algorithms, Data Structures, JavaScript, Web Dev, and more!\n'));
}
async function askName() {
const answers = await inquirer.prompt({
name: 'player_name',
type: 'input',
message: 'What is your name?',
default() {
return 'Player';
}
});
playerName = answers.player_name;
console.log(chalk.green(`Hello, ${playerName}! Let's get started!`));
}
async function askNumberOfQuestions() {
const answer = await inquirer.prompt({
name: 'num_questions',
type: 'input',
message: `How many questions would you like to practice? (1-${questionBank.length}):`,
default: '10',
validate: (input) => {
const num = parseInt(input);
if (isNaN(num) || num < 1 || num > questionBank.length) {
return `Please enter a number between 1 and ${questionBank.length}`;
}
return true;
}
});
numQuestions = parseInt(answer.num_questions);
selectedQuestions = getRandomQuestions(numQuestions);
// Initialize category stats
selectedQuestions.forEach(q => {
categoryStats[q.category] = categoryStats[q.category] || { correct: 0, total: 0 };
categoryStats[q.category].total++;
});
console.log(chalk.yellowBright(`\nš² Great! I've selected ${numQuestions} random questions for you.\n`));
}
async function askQuestion(questionData) {
const question = {
name: 'answer',
type: 'list',
message: `Question ${currentQuestion + 1}/${numQuestions}: ${questionData.question}`,
choices: questionData.choices
};
const answer = await inquirer.prompt(question);
return answer.answer;
}
async function checkAnswer(userAnswer, correctAnswer, category) {
const spinner = createSpinner('Checking your answer...').start();
await sleep(1000);
if (userAnswer === correctAnswer) {
score++;
categoryStats[category].correct++;
spinner.success({ text: `Correct, ${playerName}! š Score: ${score}/${numQuestions}` });
return true;
} else {
spinner.error({ text: `Wrong answer, ${playerName}. The correct answer is: ${correctAnswer} ā Score: ${score}/${numQuestions}` });
return false;
}
}
async function playGame() {
console.log(chalk.yellowBright(`Let's start the quiz, ${playerName}! You have ${numQuestions} questions to answer.\n`));
for (let i = 0; i < selectedQuestions.length; i++) {
currentQuestion = i;
const questionData = selectedQuestions[i];
// Show category
console.log(chalk.magenta(`š Category: ${questionData.category}`));
const userAnswer = await askQuestion(questionData);
await checkAnswer(userAnswer, questionData.correctAnswer, questionData.category);
if (i < selectedQuestions.length - 1) {
await sleep(1000);
console.log(chalk.cyan('\n' + '='.repeat(50) + '\n'));
}
}
await showResults();
}
async function showResults() {
console.log('\n' + '='.repeat(60));
console.log(chalk.magentaBright(`\nšÆ QUIZ RESULTS FOR ${playerName.toUpperCase()}`));
console.log('='.repeat(60));
const percentage = (score / numQuestions) * 100;
const { performanceLevel, emoji, feedback, suggestions } = getPersonalizedFeedback(score, numQuestions, playerName);
// Overall Score
console.log(chalk.whiteBright(`š Final Score: ${score}/${numQuestions} (${percentage.toFixed(1)}%)`));
console.log(chalk.yellowBright(`š
Performance Level: ${performanceLevel} ${emoji}\n`));
// Personalized Feedback
console.log(chalk.greenBright(`š¬ Personal Feedback:`));
console.log(chalk.white(` ${feedback}\n`));
// Category Breakdown
console.log(chalk.blueBright(`š Category Analysis:`));
const categoryAnalysis = getCategoryAnalysis(categoryStats, chalk);
categoryAnalysis.forEach(line => console.log(line));
// Suggestions
console.log(chalk.yellowBright(`\nš” Suggestions for Improvement:`));
suggestions.forEach((suggestion, index) => {
console.log(chalk.white(` ${index + 1}. ${suggestion}`));
});
if (percentage >= 80) {
await winner();
} else {
console.log(getMotivationalMessage(percentage, chalk));
}
console.log(chalk.greenBright(`\nš Thanks for playing, ${playerName}!`));
console.log(gradient('blue', 'purple')('š Keep coding and never stop learning! š'));
}
// Winner Function using figlet and chalk-animation
async function winner() {
console.clear();
const msg = chalkAnimation.rainbow('Congratulations! š');
await sleep(2000);
msg.stop();
console.log(chalk.yellowBright(figlet.textSync('WINNER!', { horizontalLayout: 'full' })));
console.log(gradient.pastel.multiline('You have mastered the CLI Prep Game!\nExcellent performance! š'));
}
async function main() {
await welcome();
await askName();
await askNumberOfQuestions();
await playGame();
}
// Start the application
main().catch(console.error);