#!/usr/bin/env python3 """ Script unificado para ejecutar la aplicación Balotario Maneja tanto desarrollo como producción según variables de entorno """ import os import sys import webbrowser import time from threading import Timer from pathlib import Path # Agregar el directorio actual al path sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) def load_env_file(): """Cargar variables de entorno desde archivo .env si existe""" env_file = Path('.env') if env_file.exists(): print("📄 Cargando variables de entorno desde .env") try: with open(env_file, 'r', encoding='utf-8') as f: for line in f: line = line.strip() # Ignorar líneas vacías y comentarios if line and not line.startswith('#'): # Separar clave=valor if '=' in line: key, value = line.split('=', 1) key = key.strip() value = value.strip() # Remover comillas si existen if value.startswith('"') and value.endswith('"'): value = value[1:-1] elif value.startswith("'") and value.endswith("'"): value = value[1:-1] # Solo establecer si no existe ya if key not in os.environ: os.environ[key] = value print("✅ Variables de entorno cargadas") except Exception as e: print(f"⚠️ Error cargando .env: {e}") else: print("💡 Archivo .env no encontrado, usando valores por defecto") print(" Copia .env.sample a .env para personalizar la configuración") def get_environment(): """Determinar el entorno de ejecución""" flask_env = os.environ.get('FLASK_ENV', 'development').lower() flask_debug = os.environ.get('FLASK_DEBUG', 'true').lower() == 'true' is_production = flask_env == 'production' or not flask_debug is_docker = os.path.exists('/.dockerenv') or os.environ.get('DOCKER_CONTAINER', False) return { 'is_production': is_production, 'is_docker': is_docker, 'flask_env': flask_env, 'flask_debug': flask_debug } def print_banner(env_info): """Mostrar banner de inicio""" if env_info['is_production']: print("🐳 BALOTARIO LICENCIA CLASE A - CATEGORÍA I") print("=" * 50) print("🚀 Modo: PRODUCCIÓN") print("🔒 Debug: Desactivado") print("📍 Puerto: 5000") if env_info['is_docker']: print("🐳 Ejecutándose en Docker") print("=" * 50) else: print("=" * 60) print("🚗 BALOTARIO LICENCIA CLASE A - CATEGORÍA I") print("=" * 60) print("📚 200 preguntas oficiales del MTC Perú") print("🎯 Modos: Estudio, Práctica y Examen Simulado") print("🌐 Interfaz moderna y responsive") print("📊 Seguimiento de progreso y estadísticas") print("=" * 60) def check_dependencies(): """Verificar que las dependencias estén instaladas""" try: import flask print("✅ Flask encontrado") return True except ImportError: print("❌ Flask no encontrado") print("💡 Instala las dependencias con: pip install -r requirements.txt") return False def check_files(): """Verificar que los archivos necesarios existan""" required_files = [ 'data/balotario_clase_a_cat_I.md', 'templates/base.html', 'templates/index.html', 'static/css/custom.css', 'static/js/app.js' ] missing_files = [] for file in required_files: if not Path(file).exists(): missing_files.append(file) if missing_files: print("❌ Archivos faltantes:") for file in missing_files: print(f" - {file}") return False print("✅ Todos los archivos necesarios están presentes") return True def open_browser(): """Abrir el navegador después de un breve delay (solo en desarrollo)""" try: webbrowser.open('http://localhost:5000') except Exception: # Si no puede abrir el navegador, no hacer nada pass def setup_production_config(): """Configurar variables de entorno para producción""" os.environ.setdefault('FLASK_ENV', 'production') os.environ.setdefault('FLASK_DEBUG', 'False') os.environ.setdefault('FLASK_CONFIG', 'production') def main(): """Función principal""" # Cargar variables de entorno load_env_file() # Determinar entorno env_info = get_environment() # Mostrar banner print_banner(env_info) # Verificar dependencias if not check_dependencies(): sys.exit(1) # Verificar archivos if not check_files(): sys.exit(1) try: from app import app print("✅ Aplicación cargada correctamente") if env_info['is_production']: # Configuración de producción print("🚀 Servidor iniciado en modo producción") app.run( host='0.0.0.0', port=5000, debug=False, threaded=True ) else: # Configuración de desarrollo print("\n🚀 Iniciando servidor...") print("📍 URL: http://localhost:5000") print("🔧 Modo: Desarrollo") print("💡 Presiona Ctrl+C para detener el servidor") print("🎨 Usa Ctrl+D para cambiar tema") print("=" * 60) # Abrir navegador automáticamente después de 2 segundos (solo en desarrollo local) if not env_info['is_docker']: Timer(2.0, open_browser).start() app.run( debug=True, host='0.0.0.0', port=5000, use_reloader=True, threaded=True ) except ImportError as e: print(f"❌ Error al importar la aplicación: {e}") sys.exit(1) except KeyboardInterrupt: if not env_info['is_production']: print("\n\n👋 Servidor detenido por el usuario") print("¡Gracias por usar el Balotario!") except Exception as e: print(f"❌ Error inesperado: {e}") sys.exit(1) if __name__ == "__main__": main()