initial commit

This commit is contained in:
2025-10-26 23:39:49 -05:00
commit 5fb0909e8d
120 changed files with 11279 additions and 0 deletions

192
app.py Normal file
View File

@@ -0,0 +1,192 @@
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/<int:question_id>')
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)