from flask import Flask, request, jsonify import os import uuid import pdfplumber from docx import Document import openpyxl from werkzeug.utils import secure_filename from threading import Thread from model_utils import extract_mcqs_with_model app = Flask(__name__) # Use /tmp/uploads to avoid permission errors app.config['UPLOAD_FOLDER'] = '/tmp/uploads' os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) quiz_data_store = {} processing_results = {} # ------------------------------- # Text Extraction Functions # ------------------------------- def extract_text_from_pdf(filepath): with pdfplumber.open(filepath) as pdf: return "\n".join([p.extract_text() for p in pdf.pages if p.extract_text()]) def extract_text_from_docx(filepath): doc = Document(filepath) return "\n".join([para.text for para in doc.paragraphs]) def extract_text_from_excel(filepath): wb = openpyxl.load_workbook(filepath) sheet = wb.active text = "" for row in sheet.iter_rows(min_row=2, values_only=True): if any(row): text += " ".join([str(cell) for cell in row if cell is not None]) + "\n" return text # ------------------------------- # Background Thread Function # ------------------------------- def background_process(file_path, quiz_id, ext): try: if ext == 'pdf': text = extract_text_from_pdf(file_path) elif ext == 'docx': text = extract_text_from_docx(file_path) elif ext in ['xls', 'xlsx']: text = extract_text_from_excel(file_path) else: processing_results[quiz_id] = {'error': 'Unsupported file type'} return mcqs = extract_mcqs_with_model(text) processing_results[quiz_id] = {'mcqs': mcqs} quiz_data_store[quiz_id] = mcqs except Exception as e: processing_results[quiz_id] = {'error': str(e)} # ------------------------------- # Non-blocking Upload Route # ------------------------------- @app.route('/upload', methods=['POST']) def upload_file(): if 'file' not in request.files: return jsonify({'error': 'No file provided'}), 400 file = request.files['file'] filename = secure_filename(file.filename) ext = filename.split('.')[-1].lower() uid = str(uuid.uuid4()) save_path = os.path.join(app.config['UPLOAD_FOLDER'], uid + '_' + filename) file.save(save_path) quiz_id = str(uuid.uuid4()) thread = Thread(target=background_process, args=(save_path, quiz_id, ext)) thread.start() return jsonify({'quiz_id': quiz_id, 'status': 'processing'}) # ------------------------------- # Status Check Route # ------------------------------- @app.route('/status/', methods=['GET']) def check_status(quiz_id): if quiz_id not in processing_results: return jsonify({'status': 'processing'}), 202 result = processing_results[quiz_id] if 'error' in result: return jsonify({'status': 'failed', 'error': result['error']}), 500 return jsonify({'status': 'completed', 'mcqs': result['mcqs']}), 200 # ------------------------------- # Quiz Submission # ------------------------------- @app.route('/submit', methods=['POST']) def submit_quiz(): data = request.json quiz_id = data.get('quiz_id') user_answers = data.get('answers') if quiz_id not in quiz_data_store: return jsonify({'error': 'Invalid quiz ID'}), 404 mcqs = quiz_data_store[quiz_id] correct = 0 for i, ans in enumerate(user_answers): if i < len(mcqs) and ans.upper() == mcqs[i]['answer'].upper(): correct += 1 total = len(mcqs) accuracy = round((correct / total) * 100, 2) if total else 0 return jsonify({'score': correct, 'total': total, 'accuracy': accuracy}) # ------------------------------- # Root Route # ------------------------------- @app.route('/') def home(): return "MCQ Extraction Flask API is running!" # ------------------------------- # Start the App # ------------------------------- if __name__ == '__main__': app.run(host='0.0.0.0', port=7860)