Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/carlosgomezc7/plataforma_aprendizaje/llms.txt

Use this file to discover all available pages before exploring further.

La Plataforma Educativa Personalizada adopta un diseño local-first: todos los datos se almacenan en un archivo db_local.json en el directorio del proyecto, sin necesidad de una conexión a internet, un servidor externo ni bibliotecas de terceros. MotorBaseDatos es la capa de persistencia que abstrae completamente las operaciones de lectura y escritura sobre ese archivo, exponiendo una API sencilla al resto de la aplicación. Al encapsular el acceso al disco en una sola clase, cualquier cambio futuro en el backend de almacenamiento (por ejemplo, migrar a SQLite o a una API REST) requiere modificar únicamente esta clase, sin tocar la lógica de estructuras de datos ni la interfaz gráfica.

Clase MotorBaseDatos

La clase se inicializa con la ruta del archivo de base de datos (por defecto "db_local.json") y define la estructura de datos predeterminada que se usará si el archivo no existe aún:
class MotorBaseDatos:
    def __init__(self, archivo_db="db_local.json"):
        self.archivo_db = archivo_db
        self.default_db = {
            "cursos": [
                {"id": 101, "nombre": "Matemáticas Básicas", "relevancia": 85, "dificultad": 3},
                {"id": 102, "nombre": "Programación en Python", "relevancia": 95, "dificultad": 5},
                {"id": 103, "nombre": "Historia del Arte", "relevancia": 60, "dificultad": 2},
                {"id": 104, "nombre": "Física Cuántica", "relevancia": 90, "dificultad": 9},
                {"id": 105, "nombre": "Estructuras de Datos", "relevancia": 99, "dificultad": 8}
            ],
            "progresos": []
        }
        self.cargar_datos()
El constructor llama a cargar_datos() al final, de modo que self.data siempre está disponible y poblado cuando la instancia queda lista para usar.

Inicialización automática

Si db_local.json no existe en el momento en que se instancia MotorBaseDatos, el motor copia el catálogo predeterminado de cinco cursos a self.data y llama inmediatamente a guardar_datos(), creando el archivo en disco. Esto significa que la primera ejecución de la aplicación siempre genera un archivo funcional, sin pasos de configuración manual. Si el archivo existe pero está malformado (JSON inválido, por ejemplo por una escritura interrumpida), cargar_datos() captura la excepción, imprime un mensaje informativo en la consola y carga los valores predeterminados en memoria para que la aplicación pueda continuar funcionando.

Operaciones

cargar_datos()

Lee el archivo indicado en self.archivo_db y deserializa su contenido JSON en self.data. Si el archivo no existe, usa self.default_db como fuente y lo persiste en disco. Si ocurre cualquier error de parseo, cae al mismo respaldo de datos predeterminados:
def cargar_datos(self):
    if os.path.exists(self.archivo_db):
        try:
            with open(self.archivo_db, "r", encoding="utf-8") as f:
                self.data = json.load(f)
        except Exception as e:
            print(f"Error al cargar base de datos local: {e}. Usando valores predeterminados.")
            self.data = self.default_db.copy()
    else:
        self.data = self.default_db.copy()
        self.guardar_datos()

guardar_datos()

Serializa self.data completo de vuelta al archivo JSON, con sangría de 4 espacios para legibilidad humana y ensure_ascii=False para preservar caracteres acentuados y especiales del español:
def guardar_datos(self):
    try:
        with open(self.archivo_db, "w", encoding="utf-8") as f:
            json.dump(self.data, f, indent=4, ensure_ascii=False)
    except Exception as e:
        print(f"Error al guardar base de datos local: {e}")

obtener_cursos()

Retorna la lista completa de cursos almacenada en self.data["cursos"]. Si la clave no existe por algún motivo (archivo editado manualmente de forma incorrecta), retorna una lista vacía como valor seguro:
def obtener_cursos(self):
    return self.data.get("cursos", [])

guardar_progreso(estudiante, modulo)

Agrega un registro de progreso al arreglo self.data["progresos"] y persiste inmediatamente los cambios en disco. Crea la clave "progresos" si no existía previamente:
def guardar_progreso(self, estudiante, modulo):
    if "progresos" not in self.data:
        self.data["progresos"] = []
    self.data["progresos"].append({"estudiante": estudiante, "modulo": modulo})
    self.guardar_datos()

Esquema JSON

El archivo db_local.json sigue siempre esta estructura de dos claves raíz:
{
    "cursos": [
        {
            "id": 101,
            "nombre": "Matemáticas Básicas",
            "relevancia": 85,
            "dificultad": 3
        }
    ],
    "progresos": [
        {
            "estudiante": "Juan_Perez",
            "modulo": "Módulo 5"
        }
    ]
}
CampoTipoDescripción
cursos[].idintegerIdentificador numérico único del curso. Usado por la Búsqueda Binaria.
cursos[].nombrestringNombre legible del curso mostrado en la interfaz.
cursos[].relevanciaintegerÍndice de relevancia (0–100). Quick Sort ordena por este campo de forma descendente.
cursos[].dificultadintegerNivel de dificultad del curso (escala 1–10).
progresos[].estudiantestringIdentificador del estudiante que completó el módulo.
progresos[].modulostringNombre del módulo completado, tal como se registró en la cola.

Agregar cursos

Para extender el catálogo con nuevos cursos, instancia el motor, modifica self.data["cursos"] directamente y llama a guardar_datos():
db = MotorBaseDatos()
db.data["cursos"].append({
    "id": 106,
    "nombre": "Inteligencia Artificial",
    "relevancia": 98,
    "dificultad": 9
})
db.guardar_datos()
El nuevo curso quedará persistido en db_local.json y estará disponible inmediatamente para Quick Sort y Búsqueda Binaria en la próxima ejecución de la aplicación. Asegúrate de que el campo id sea único para que la Búsqueda Binaria produzca resultados deterministas.
db_local.json no es threadsafe. Si dos procesos de Python intentan escribir en el archivo al mismo tiempo, las operaciones de json.dump pueden entrelazarse y corromper el JSON. Esto es intencional: la plataforma es un prototipo de escritorio de proceso único donde solo una instancia de MotorBaseDatos escribe en el archivo en un momento dado. No uses este motor directamente en entornos multi-proceso o multi-hilo sin agregar un mecanismo de bloqueo (por ejemplo, threading.Lock o un lock de archivo con fcntl).

Para la referencia completa de la API de MotorBaseDatos y la especificación formal del esquema, consulta:

Build docs developers (and LLMs) love