Files
driving-academy/run.py
2025-10-26 23:39:49 -05:00

200 lines
6.4 KiB
Python

#!/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()