200 lines
6.4 KiB
Python
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()
|