import axios from 'axios';
import FormData from 'form-data';
import * as fs from 'fs';
import path from 'path';
function extractQuestionsImproved(text) {
const questions = [];
// Split into sections and process each
const sections = [Link](/(?=\d+\.\s)/);
for (const section of sections) {
if (![Link]()) continue;
const lines = [Link]('\n').map(l => [Link]()).filter(l => [Link] >
0);
if ([Link] === 0) continue;
// Find question number and text
const firstLine = lines[0];
const qMatch = [Link](/^(\d+)\.\s*(.+)/);
if (!qMatch) continue;
let questionText = qMatch[2];
let currentLineIndex = 1;
// Continue collecting question text until we hit options
while (currentLineIndex < [Link] &&
!lines[currentLineIndex].match(/^\([A-D]\)/)) {
if (!lines[currentLineIndex].match(/^\d+\./) &&
!lines[currentLineIndex].includes('\\') &&
!lines[currentLineIndex].includes('স্তম্ভ')) {
questionText += ' ' + lines[currentLineIndex];
}
currentLineIndex++;
}
// Extract options
const options = [];
const remainingText = [Link](currentLineIndex).join(' ');
const optionMatches = [...[Link](/\([A-D]\)\s*([^(]+?)(?=\
s*\([A-D]\)|$)/g)];
if ([Link] >= 4) {
for (let i = 0; i < 4; i++) {
[Link](optionMatches[i][1].trim());
}
// Clean question text
questionText = questionText
.replace(/\s+/g, ' ')
.replace(/হলে\s*নীচের\s*কোন্টি/g, 'হলে নীচের কোনটি')
.trim();
[Link]({
question: questionText,
diagram: null,
options: options
});
}
}
return questions;
}
const upload = async (req, res) => {
const pdf_file = [Link];
try {
const form = new FormData();
[Link]('file', [Link](pdf_file.path), pdf_file.path);
[Link]('options_json', '{ "math_inline_delimiters": ["$", "$"],
"rm_spaces": true}');
// Upload PDF
const postResponse = await [Link](
'[Link]
form,
{
headers: {
...[Link](),
'app_id': [Link].MATHPIX_API_ID,
'app_key': [Link].MATHPIX_API_KEY
}
}
);
const pdf_id = [Link].pdf_id;
[Link](pdf_file.path); // Clean up uploaded file
[Link](`PDF uploaded successfully. PDF ID: ${pdf_id}`);
// Poll for completion
const maxAttempts = 5;
const pollInterval = 7000;
let attempts = 0;
let isComplete = false;
while (!isComplete && attempts < maxAttempts) {
attempts++;
[Link](`Checking processing status... Attempt ${attempts}`);
try {
const statusResponse = await [Link](
`[Link]
{
headers: {
'app_id': [Link].MATHPIX_API_ID,
'app_key': [Link].MATHPIX_API_KEY
}
}
);
const status = [Link];
[Link](`Status: ${status}`);
if (status === 'completed') {
isComplete = true;
// Get the processed data directly in memory
const resultResponse = await [Link](
`[Link]
{
headers: {
'app_id': [Link].MATHPIX_API_ID,
'app_key': [Link].MATHPIX_API_KEY
}
}
);
// Extract questions from the MMD content
const extractedQuestions =
extractQuestionsImproved([Link]);
[Link](`Extracted ${[Link]}
questions`);
// Send JSON response with extracted questions
[Link](200).json({
success: true,
message: "PDF processed and questions extracted
successfully",
data: {
pdf_id: pdf_id,
total_questions: [Link],
questions: extractedQuestions,
processing_time: `${attempts * pollInterval / 1000}
seconds`
}
});
} else if (status === 'error' || status === 'failed') {
throw new Error(`PDF processing failed with status: $
{status}`);
} else {
// Still processing, wait before next poll
await new Promise(resolve => setTimeout(resolve,
pollInterval));
}
} catch (pollError) {
[Link](`Error checking status: ${[Link]}`);
if ([Link]?.status === 404) {
throw new Error('PDF not found - may have expired');
}
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
}
if (!isComplete) {
throw new Error(`PDF processing timeout after ${maxAttempts *
pollInterval / 1000} seconds`);
}
} catch (error) {
[Link]('Upload error:', error);
[Link](500).json({
success: false,
message: "Failed to process PDF",
error: [Link]
});
}
};
export { upload };