claude-code-ultimate-guide/quiz/src/index.js
Florian BRUNIAUX 5b526f5e53 feat(audit): enhanced stack detection with integrations
- Detailed stack breakdown: runtime, framework, test, bundler, database
- Generic integration detection (25+ packages: Clerk, Stripe, OpenAI, Sentry...)
- jq fallback: grep-based JSON parsing when jq not installed
- Stack recap at top of human output + full stack object in JSON
- README prompt updated: Stack Recap first, CLAUDE.md template ~100 lines

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 14:52:55 +01:00

187 lines
5.1 KiB
JavaScript

#!/usr/bin/env node
/**
* Claude Code Knowledge Quiz
* Test your understanding of Claude Code with interactive MCQs
*
* Part of: claude-code-ultimate-guide
* Author: Florian BRUNIAUX
*/
import { createRequire } from 'module';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { parseArgs } from 'util';
import { displayHeader, displayHelp } from './ui.js';
import { selectProfile, selectTopics } from './prompts.js';
import { loadQuestions, filterQuestions, shuffleArray } from './questions.js';
import { runQuiz } from './quiz.js';
import { displayFinalScore, offerRetry } from './score.js';
import { loadSession, saveSession } from './session.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// CLI argument parsing
const { values: args } = parseArgs({
options: {
profile: { type: 'string', short: 'p' },
topics: { type: 'string', short: 't' },
count: { type: 'string', short: 'c' },
dynamic: { type: 'boolean', short: 'd', default: false },
help: { type: 'boolean', short: 'h', default: false },
version: { type: 'boolean', short: 'v', default: false }
},
strict: false
});
// Profile configurations
const PROFILES = {
junior: {
name: 'Junior Developer',
description: '45 min to productivity',
questionCount: 15,
focusTopics: [1, 2, 3, 6],
difficultyWeight: { junior: 0.8, senior: 0.2, power: 0 }
},
senior: {
name: 'Senior Developer',
description: '40 min to mastery',
questionCount: 20,
focusTopics: [2, 3, 4, 7, 9],
difficultyWeight: { junior: 0.3, senior: 0.5, power: 0.2 }
},
power: {
name: 'Power User',
description: '2 hours for full mastery',
questionCount: 25,
focusTopics: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
difficultyWeight: { junior: 0.2, senior: 0.4, power: 0.4 }
},
pm: {
name: 'Product Manager',
description: '20 min overview',
questionCount: 10,
focusTopics: [1, 2, 3],
difficultyWeight: { junior: 1, senior: 0, power: 0 }
}
};
// Topic names
const TOPICS = {
1: 'Quick Start & Installation',
2: 'Core Concepts',
3: 'Memory & Settings',
4: 'Agents',
5: 'Skills',
6: 'Commands',
7: 'Hooks',
8: 'MCP Servers',
9: 'Advanced Patterns',
10: 'Reference & Troubleshooting'
};
async function main() {
// Handle help/version
if (args.help) {
displayHelp();
process.exit(0);
}
if (args.version) {
console.log('claude-code-quiz v1.0.0');
process.exit(0);
}
// Display header
displayHeader();
// Profile selection
let profile;
if (args.profile && PROFILES[args.profile]) {
profile = args.profile;
} else {
profile = await selectProfile(PROFILES);
}
// Topic selection
let selectedTopics;
if (args.topics) {
selectedTopics = args.topics.split(',').map(t => parseInt(t.trim())).filter(t => t >= 1 && t <= 10);
if (selectedTopics.length === 0) selectedTopics = PROFILES[profile].focusTopics;
} else {
selectedTopics = await selectTopics(TOPICS, PROFILES[profile].focusTopics);
}
// Question count
let questionCount = PROFILES[profile].questionCount;
if (args.count) {
const parsed = parseInt(args.count);
if (parsed > 0 && parsed <= 50) questionCount = parsed;
}
// Load and filter questions
const questionsDir = join(__dirname, '..', 'questions');
const allQuestions = await loadQuestions(questionsDir);
const filteredQuestions = filterQuestions(allQuestions, {
profile,
topics: selectedTopics,
count: questionCount,
difficultyWeight: PROFILES[profile].difficultyWeight
});
if (filteredQuestions.length === 0) {
console.log('\nNo questions available for selected criteria. Try different topics.');
process.exit(1);
}
// Shuffle questions
const quizQuestions = shuffleArray(filteredQuestions).slice(0, questionCount);
// Run quiz
const results = await runQuiz(quizQuestions, {
profile,
topics: selectedTopics,
dynamicEnabled: args.dynamic
});
// Display final score
displayFinalScore(results, TOPICS);
// Save session
await saveSession(results);
// Offer retry
const retryChoice = await offerRetry(results);
if (retryChoice === 'retry-wrong') {
// Filter to only wrong questions and run again
const wrongQuestions = results.questions.filter(q => !q.correct);
if (wrongQuestions.length > 0) {
const retryResults = await runQuiz(wrongQuestions.map(q => q.question), {
profile,
topics: selectedTopics,
dynamicEnabled: args.dynamic,
isRetry: true
});
displayFinalScore(retryResults, TOPICS);
await saveSession(retryResults);
}
} else if (retryChoice === 'new-quiz') {
// Restart with different questions
const newQuestions = shuffleArray(filteredQuestions).slice(0, questionCount);
const newResults = await runQuiz(newQuestions, {
profile,
topics: selectedTopics,
dynamicEnabled: args.dynamic
});
displayFinalScore(newResults, TOPICS);
await saveSession(newResults);
}
// else 'exit' - do nothing
}
main().catch(err => {
console.error('Error:', err.message);
process.exit(1);
});