examforge / src /services /ParsingService.ts
Benjahmin's picture
feat: Introduce question bank and group management
3fd70bc
Raw
History Blame Contribute Delete
1.79 kB
import { Question } from '../types';
export class ParsingService {
static parseText(text: string): Question[] {
const lines = text.split('\n').map(l => l.trim()).filter(l => l.length > 0);
const questions: Question[] = [];
let currentQuestion: Partial<Question> | null = null;
lines.forEach((line) => {
// Detect Question: 1. or 1) or Question 1
const qMatch = line.match(/^(\d+)[\.\)]\s*(.*)$/i) || line.match(/^Question\s*(\d+)[:\.]?\s*(.*)$/i) || line.match(/^Q(\d+)[:\.]?\s*(.*)$/i);
if (qMatch) {
if (currentQuestion && currentQuestion.text) {
questions.push(currentQuestion as Question);
}
currentQuestion = {
id: qMatch[1],
text: qMatch[2],
options: [],
correctOptionId: '',
category: 'General',
difficulty: 'medium'
};
return;
}
// Detect Option: A. or A) or (A)
const oMatch = line.match(/^([A-D])[\.\)]\s*(.*)$/i) || line.match(/^\(([A-D])\)\s*(.*)$/i);
if (oMatch && currentQuestion) {
currentQuestion.options?.push({
id: `opt-${oMatch[1].toLowerCase()}`,
text: oMatch[2]
});
return;
}
// Detect Answer: Answer: A
const aMatch = line.match(/^Answer:\s*([A-D])/i);
if (aMatch && currentQuestion) {
currentQuestion.correctOptionId = `opt-${aMatch[1].toLowerCase()}`;
return;
}
// If it's just more text for the current question
if (currentQuestion && !oMatch && !aMatch) {
currentQuestion.text += ' ' + line;
}
});
if (currentQuestion && currentQuestion.text) {
questions.push(currentQuestion as Question);
}
return questions;
}
}