import type { CodingQuestion } from '@/data/codingQuestions'; import { apiFetch } from '@/lib/authClient'; type DSADifficulty = CodingQuestion['difficulty']; type StarterCode = CodingQuestion['starterCode']; export type DSAMongoQuestion = { id: string; source?: string; questionNumber: number; title: string; difficulty: string; category: string; topics: string[]; companies?: string[]; hint?: string; problemStatement: string; examples?: { input: string; expectedOutput: string; explanation?: string; }[]; constraints?: string[]; }; type DSAQuestionsResponse = { questions?: DSAMongoQuestion[]; }; const emptyStarterCode: StarterCode = { javascript: '', python: '', cpp: '', java: '', go: '', }; function splitTopLevel(value: string) { const parts: string[] = []; let current = ''; let depth = 0; let quote: '"' | "'" | null = null; let escaped = false; for (const char of value) { if (escaped) { current += char; escaped = false; continue; } if (char === '\\') { current += char; escaped = true; continue; } if (quote) { current += char; if (char === quote) quote = null; continue; } if (char === '"' || char === "'") { current += char; quote = char; continue; } if (char === '[' || char === '{' || char === '(') depth += 1; if (char === ']' || char === '}' || char === ')') depth = Math.max(0, depth - 1); if (char === ',' && depth === 0) { parts.push(current.trim()); current = ''; continue; } current += char; } if (current.trim()) parts.push(current.trim()); return parts; } function parseExampleValue(raw: string): unknown { const value = raw.trim().replace(/^(?:Input|Output):\s*/i, ''); if (!value) return ''; const jsonLike = value .replace(/\bTrue\b/g, 'true') .replace(/\bFalse\b/g, 'false') .replace(/\bNone\b/g, 'null') .replace(/\bNULL\b/g, 'null') .replace(/\bnull\b/g, 'null') .replace(/'/g, '"'); try { return JSON.parse(jsonLike); } catch { if (/^-?\d+(?:\.\d+)?$/.test(value)) return Number(value); if (/^(true|false)$/i.test(value)) return value.toLowerCase() === 'true'; return value.replace(/^["']|["']$/g, ''); } } function parseExampleParams(input: string) { const value = input.trim().replace(/^Input:\s*/i, ''); if (!value) return []; const parts = splitTopLevel(value); const assignments = parts .map((part) => part.match(/^[A-Za-z_]\w*\s*=\s*([\s\S]+)$/)?.[1]) .filter((part): part is string => Boolean(part)); if (assignments.length > 0) { return assignments.map(parseExampleValue); } return [parseExampleValue(value)]; } function normalizeDifficulty(value: string): DSADifficulty { const normalized = value.trim().toLowerCase(); if (normalized === 'medium' || normalized === 'med.') return 'Medium'; if (normalized === 'hard') return 'Hard'; return 'Easy'; } function formatDSADescription(question: DSAMongoQuestion) { const sections = [question.problemStatement.trim()].filter(Boolean); if (question.examples?.length) { sections.push( [ 'Examples:', ...question.examples.map((example, index) => { const lines = [`${index + 1}. Input: ${example.input}`]; if (example.expectedOutput) lines.push(` Output: ${example.expectedOutput}`); if (example.explanation) lines.push(` Explanation: ${example.explanation}`); return lines.join('\n'); }), ].join('\n'), ); } if (question.constraints?.length) { sections.push(['Constraints:', ...question.constraints.map((constraint) => `- ${constraint}`)].join('\n')); } if (question.hint) { sections.push(`Hint: ${question.hint}`); } if (question.companies?.length) { sections.push(`Asked by: ${question.companies.join(', ')}`); } return sections.join('\n\n'); } function toTestCases(question: DSAMongoQuestion): CodingQuestion['testCases'] { return (question.examples ?? []).map((example) => ({ input: example.input, output: example.expectedOutput, params: parseExampleParams(example.input), expected: parseExampleValue(example.expectedOutput), })); } export function mapDSAQuestionToCodingQuestion(question: DSAMongoQuestion): CodingQuestion { return { id: question.id || `dsa-${question.questionNumber}`, title: question.title, difficulty: normalizeDifficulty(question.difficulty), category: question.category || question.topics?.[0] || 'DSA', companies: question.companies ?? [], description: formatDSADescription(question), starterCode: emptyStarterCode, testCases: toTestCases(question), hiddenTestCases: [], solution: { javascript: '', python: '', cpp: '', java: '', go: '', explanation: question.hint || 'A full solution is not available for this MongoDB question yet.', }, }; } export async function fetchDSAQuestions(): Promise { const res = await apiFetch('/api/dsa/questions'); if (!res.ok) { const text = await res.text(); throw new Error(text.trim() || `Failed to fetch DSA questions (${res.status})`); } const data = (await res.json()) as DSAQuestionsResponse; return (data.questions ?? []).map(mapDSAQuestionToCodingQuestion); }