claude-code-ultimate-guide/quiz/src/questions.js
Florian BRUNIAUX bc07651cdf refactor: restructure repo into thematic directories v3.1.0
Major repository reorganization for improved navigation:

New directory structure:
- guide/ - Core documentation (ultimate-guide, cheatsheet, adoption)
- tools/ - Interactive utilities (audit, onboarding, mobile-access)
- machine-readable/ - LLM/AI consumption (reference.yaml, llms.txt)
- exports/ - Generated outputs (PDFs)

Changes:
- Move 10 files to thematic directories with cleaner names
- Create README.md index for each new directory
- Update 150+ internal links across all documentation
- Add "Repository Structure" section to main README
- Remove redundant npm install command from README header
- Remove unverified cost estimate from prerequisites
- Fix broken anchor link (#-quick-start-15-minutes)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 15:30:02 +01:00

124 lines
3.7 KiB
JavaScript

/**
* Question loading and filtering
*/
import { readdir, readFile } from 'fs/promises';
import { join } from 'path';
import YAML from 'yaml';
/**
* Load all questions from YAML files in the questions directory
*/
export async function loadQuestions(questionsDir) {
const allQuestions = [];
try {
const files = await readdir(questionsDir);
const yamlFiles = files.filter(f => f.endsWith('.yaml') || f.endsWith('.yml'));
for (const file of yamlFiles) {
try {
const content = await readFile(join(questionsDir, file), 'utf-8');
const parsed = YAML.parse(content);
if (parsed && parsed.questions && Array.isArray(parsed.questions)) {
// Add category info to each question
const questionsWithCategory = parsed.questions.map(q => ({
...q,
category: parsed.category || 'Unknown',
category_id: parsed.category_id || 0,
source_file: parsed.source_file || 'guide/ultimate-guide.md'
}));
allQuestions.push(...questionsWithCategory);
}
} catch (err) {
console.warn(`Warning: Could not parse ${file}: ${err.message}`);
}
}
} catch (err) {
console.error(`Error reading questions directory: ${err.message}`);
}
return allQuestions;
}
/**
* Filter questions based on profile, topics, and difficulty
*/
export function filterQuestions(questions, options) {
const { profile, topics, count, difficultyWeight } = options;
// Filter by topics
let filtered = questions.filter(q => topics.includes(q.category_id));
// Filter by profile (if profiles array exists on question)
filtered = filtered.filter(q => {
if (!q.profiles || !Array.isArray(q.profiles)) return true;
return q.profiles.includes(profile);
});
// Weight by difficulty
if (difficultyWeight) {
filtered = weightByDifficulty(filtered, difficultyWeight, count);
}
return filtered;
}
/**
* Weight questions by difficulty distribution
*/
function weightByDifficulty(questions, weights, targetCount) {
const byDifficulty = {
junior: questions.filter(q => q.difficulty === 'junior'),
senior: questions.filter(q => q.difficulty === 'senior'),
power: questions.filter(q => q.difficulty === 'power'),
all: questions.filter(q => q.difficulty === 'all' || !q.difficulty)
};
const result = [];
// Add 'all' difficulty questions first
result.push(...byDifficulty.all);
// Calculate target counts for each difficulty
const remaining = targetCount - result.length;
const juniorCount = Math.floor(remaining * (weights.junior || 0));
const seniorCount = Math.floor(remaining * (weights.senior || 0));
const powerCount = Math.floor(remaining * (weights.power || 0));
// Add questions by difficulty
result.push(...shuffleArray(byDifficulty.junior).slice(0, juniorCount));
result.push(...shuffleArray(byDifficulty.senior).slice(0, seniorCount));
result.push(...shuffleArray(byDifficulty.power).slice(0, powerCount));
// Fill remaining slots with any available questions
const used = new Set(result.map(q => q.id));
const unused = questions.filter(q => !used.has(q.id));
const stillNeeded = targetCount - result.length;
if (stillNeeded > 0) {
result.push(...shuffleArray(unused).slice(0, stillNeeded));
}
return result;
}
/**
* Shuffle array using Fisher-Yates algorithm
*/
export function shuffleArray(array) {
const result = [...array];
for (let i = result.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[result[i], result[j]] = [result[j], result[i]];
}
return result;
}
/**
* Get category name from ID
*/
export function getCategoryName(categoryId, topics) {
return topics[categoryId] || 'Unknown';
}