from flask import Flask, render_template, request, jsonify, session import json import random import re import os from datetime import datetime from config import config # Create Flask application app = Flask(__name__) # Configure the application config_name = os.environ.get('FLASK_CONFIG', 'default') app.config.from_object(config[config_name]) config[config_name].init_app(app) # Function to parse markdown and extract questions def parse_markdown_questions(): with open(app.config['MARKDOWN_FILE'], 'r', encoding='utf-8') as file: content = file.read() questions = [] # Split content by questions using ### as separator question_blocks = re.split(r'\n### (\d+)\n', content)[1:] # Ignore first empty element for i in range(0, len(question_blocks), 2): if i + 1 >= len(question_blocks): break question_num = int(question_blocks[i]) question_content = question_blocks[i + 1].strip() # Check if there's an image at the beginning (now supports both local and remote URLs) has_image = ('![](https://sierdgtt.mtc.gob.pe/Content/img-data/' in question_content or '![](/static/images/' in question_content) image_url = "" if has_image: # Try local images first, then remote img_match = re.search(r'!\[\]\((/static/images/[^)]+)\)', question_content) if not img_match: img_match = re.search(r'!\[\]\((https://sierdgtt\.mtc\.gob\.pe/Content/img-data/[^)]+)\)', question_content) if img_match: image_url = img_match.group(1) question_content = re.sub(r'!\[\]\([^)]+\)\n*', '', question_content).strip() # Separate question from options lines = question_content.split('\n') question_lines = [] option_lines = [] in_options = False for line in lines: line = line.strip() if not line: continue if re.match(r'^✅?\s*[a-d]\)', line): in_options = True option_lines.append(line) elif not in_options: question_lines.append(line) question_text = ' '.join(question_lines).strip() # Extract options and correct answer options = [] correct_option = "" for line in option_lines: original_line = line.strip() # Check if this line has the ✅ if '✅' in original_line: # Extract the letter of the correct option match = re.search(r'✅\s*([a-d])\)', original_line) if match: correct_option = match.group(1) # Clean the line by removing ✅ completely and any extra spaces clean_line = re.sub(r'✅\s*', '', original_line) clean_line = re.sub(r'✅', '', clean_line) # In case there's ✅ without spaces clean_line = clean_line.strip() options.append(clean_line) if len(options) >= 2 and correct_option and question_text: # Validate we have complete data questions.append({ 'id': question_num, 'question': question_text, 'options': options, 'correct': correct_option, 'image': image_url, 'has_image': has_image }) return sorted(questions, key=lambda x: x['id']) # Load questions when starting the application QUESTIONS = parse_markdown_questions() @app.route('/') def index(): return render_template('index.html', total_questions=len(QUESTIONS)) @app.route('/study') def study(): return render_template('study.html') @app.route('/practice') def practice(): return render_template('practice.html') @app.route('/exam') def exam(): return render_template('exam.html') @app.route('/api/questions') def get_questions(): mode = request.args.get('mode', 'all') count = request.args.get('count', type=int) if mode == 'random': questions = random.sample(QUESTIONS, min(count or 20, len(QUESTIONS))) elif mode == 'range': start = request.args.get('start', 1, type=int) end = request.args.get('end', len(QUESTIONS), type=int) questions = [q for q in QUESTIONS if start <= q['id'] <= end] else: questions = QUESTIONS return jsonify(questions) @app.route('/api/question/') def get_question(question_id): question = next((q for q in QUESTIONS if q['id'] == question_id), None) if question: return jsonify(question) return jsonify({'error': 'Pregunta no encontrada'}), 404 @app.route('/api/check_answer', methods=['POST']) def check_answer(): data = request.json question_id = data.get('question_id') user_answer = data.get('answer') question = next((q for q in QUESTIONS if q['id'] == question_id), None) if not question: return jsonify({'error': 'Pregunta no encontrada'}), 404 is_correct = user_answer == question['correct'] return jsonify({ 'correct': is_correct, 'correct_answer': question['correct'], 'explanation': f"La respuesta correcta es: {question['correct']}" }) @app.route('/api/stats') def get_stats(): # Statistics are now handled completely in client localStorage # This endpoint returns default stats for compatibility return jsonify({ 'total_answered': 0, 'correct_answers': 0, 'incorrect_answers': 0, 'accuracy': 0, 'message': 'Stats handled by localStorage' }) @app.route('/api/update_stats', methods=['POST']) def update_stats(): # Statistics are now handled completely in client localStorage # This endpoint only confirms that the update was received data = request.json is_correct = data.get('correct', False) return jsonify({ 'success': True, 'message': 'Stats updated in localStorage', 'received_correct': is_correct }) @app.route('/api/reset_stats', methods=['POST']) def reset_stats(): """Confirm that statistics were reset in localStorage""" return jsonify({ 'success': True, 'message': 'Estadísticas restablecidas correctamente en localStorage' }) if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=5000)