lopezbec / AI_Gamification_Python

3 stars 2 forks source link

Add accent ot Modulo #116

Open lopezbec opened 1 month ago

lopezbec commented 1 month ago

We need to add the accent to the word "modulo" in the app. I was trying to fix it by changing all the strings that show as "Modulo" in the "Main_Modules_Intro.py" file, but it looks like the file/logic that controls when the lesson and modules are open, also assumes the work without accent. (this is a very low priority)

@Elmerluis0129 , you might be better suited for this since I think the "lock" logic script/files might need to be updates as well

image

DanielDD-UNPHU commented 3 weeks ago

Done

image

image

image

DanielDD-UNPHU commented 3 weeks ago

Documentación: Manejo del Número de Lecciones en Módulos

Antes: En la versión anterior del código, el número de lecciones en cada módulo se manejaba manualmente cuando se configuraban los menús de los módulos. El código conocía la cantidad de lecciones porque este número se pasaba explícitamente como un parámetro al momento de configurar cada módulo.

Ejemplo del Código Anterior:

Añadir botones de módulo debajo del título

self.modulo1_btn = self.setup_modulos_menu("Modulo 1", 5)
self.modulo2_btn = self.setup_modulos_menu("Modulo 2", 3)
self.modulo3_btn = self.setup_modulos_menu("Modulo 3", 5)
self.modulo4_btn = self.setup_modulos_menu("Modulo 4", 5)
self.modulo5_btn = self.setup_modulos_menu("Modulo 5", 7)

Ahora: Con la implementación de identificadores únicos para cada módulo, hemos centralizado la configuración de los módulos y el manejo del número de lecciones. Ahora, toda la información relevante (nombre del módulo y número de lecciones) se encapsula en un solo objeto o diccionario. Esto no solo mejora la claridad y la mantenibilidad del código, sino que también reduce la posibilidad de errores.

# Definir módulos con identificadores únicos
self.modulos = {
    "modulo_1": {"nombre": "Módulo 1", "lecciones": 5},
    "modulo_2": {"nombre": "Módulo 2", "lecciones": 3},
    "modulo_3": {"nombre": "Módulo 3", "lecciones": 5},
    "modulo_4": {"nombre": "Módulo 4", "lecciones": 5},
    "modulo_5": {"nombre": "Módulo 5", "lecciones": 7}
}

# Crear botones de módulos basados en identificadores únicos
self.modulo1_btn = self.setup_modulos_menu("modulo_1")
self.modulo2_btn = self.setup_modulos_menu("modulo_2")
self.modulo3_btn = self.setup_modulos_menu("modulo_3")
self.modulo4_btn = self.setup_modulos_menu("modulo_4")
self.modulo5_btn = self.setup_modulos_menu("modulo_5")

Ventajas:

DanielDD-UNPHU commented 3 weeks ago

Documentación de Modificaciones: Uso de id_modulo

1. setup_modulos_menu

Antes:

def setup_modulos_menu(self, nombre_modulo, numero_lecciones):
    modulos_btn = QtWidgets.QToolButton()
    modulos_btn.setText(nombre_modulo)
    modulos_btn.setStyleSheet(
        f"""
        background-color: {self.styles['submit_button_color']};
        font-size: {self.styles['font_size_buttons']}px;
        border: 2px solid black;
        border-radius: 10px;
        padding: 5px;
        """
    )
    modulos_btn.setFixedSize(171, 80)  # Ajusta el tamaño (ancho, alto)

    modulos_menu = QtWidgets.QMenu()
    self.añadir_submenu(nombre_modulo, numero_lecciones, modulos_menu)
    modulos_btn.setMenu(modulos_menu)
    modulos_btn.setPopupMode(QtWidgets.QToolButton.ToolButtonPopupMode.InstantPopup)

    return modulos_btn

Ahora:

def setup_modulos_menu(self, id_modulo):
    datos_modulo = self.modulos[id_modulo]
    modulos_btn = QtWidgets.QToolButton()
    modulos_btn.setText(datos_modulo["nombre"])
    modulos_btn.setStyleSheet(
        f"""
        background-color: {self.styles['submit_button_color']};
        font-size: {self.styles['font_size_buttons']}px;
        border: 2px solid black;
        border-radius: 10px;
        padding: 5px;
        """
    )
    modulos_btn.setFixedSize(171, 80)  # Ajusta el tamaño (ancho, alto)

    modulos_menu = QtWidgets.QMenu()
    self.añadir_submenu(id_modulo, modulos_menu)
    modulos_btn.setMenu(modulos_menu)
    modulos_btn.setPopupMode(QtWidgets.QToolButton.ToolButtonPopupMode.InstantPopup)

    return modulos_btn

2. añadir_submenu

Antes:

def añadir_submenu(self, nombre_modulo, numero_lecciones, boton_modulo):
    estado_modulo = self.progreso_usuario.get(nombre_modulo.replace(" ", ""), {})
    estado_completado = self.load_lesson_completed(self.usuario_actual)

    for leccion_numero in range(1, numero_lecciones + 1):
        leccion_clave = f"Leccion{leccion_numero}"
        estado_leccion = estado_modulo.get(leccion_clave, False)

        leccion_completada = estado_completado.get(nombre_modulo.replace(" ", ""), {}).get(
            f"Leccion_completada{leccion_numero}", False)

        if leccion_completada:
            icono = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Icons', 'completado_icon.png')
        elif estado_leccion:
            icono = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Icons', 'abierto_icon.png')
        else:
            icono = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Icons', 'cerrado_icon.jpg')

        accion_leccion = QAction(f"Lección {leccion_numero}", self)
        accion_leccion.setIcon(QIcon(icono))
        accion_leccion.triggered.connect(lambda _, n=leccion_numero, m=nombre_modulo: self.abrir_leccion(m, n))
        boton_modulo.addAction(accion_leccion)

Ahora:

def añadir_submenu(self, id_modulo, boton_modulo):
    datos_modulo = self.modulos[id_modulo]
    estado_modulo = self.progreso_usuario.get(id_modulo, {})
    estado_completado = self.load_lesson_completed(self.usuario_actual)

    for leccion_numero in range(1, datos_modulo["lecciones"] + 1):
        leccion_clave = f"Leccion{leccion_numero}"
        estado_leccion = estado_modulo.get(leccion_clave, False)

        leccion_completada = estado_completado.get(id_modulo, {}).get(f"Leccion_completada{leccion_numero}", False)

        if leccion_completada:
            icono = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Icons', 'completado_icon.png')
        elif estado_leccion:
            icono = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Icons', 'abierto_icon.png')
        else:
            icono = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Icons', 'cerrado_icon.jpg')

        accion_leccion = QAction(f"Lección {leccion_numero}", self)
        accion_leccion.setIcon(QIcon(icono))
        accion_leccion.triggered.connect(lambda _, n=leccion_numero, m=id_modulo: self.abrir_leccion(m, n))
        boton_modulo.addAction(accion_leccion)

3. abrir_leccion

Antes:

def abrir_leccion(self, nombre_modulo, numero_leccion):
    # Lógica basada en nombre_modulo
    if nombre_modulo == "Modulo 1":
        # Código para abrir lecciones de Modulo 1
    elif nombre_modulo == "Modulo 2":
        # Código para abrir lecciones de Modulo 2
    # Continúa para los demás módulos

Ahora:

def abrir_leccion(self, id_modulo, numero_leccion):
    try:
        if id_modulo == "modulo_1":
            # Código para abrir lecciones de modulo_1
        elif id_modulo == "modulo_2":
            # Código para abrir lecciones de modulo_2
        # Continúa para los demás módulos

    except Exception as e:
        print(f"Error al abrir {id_modulo} - Lección {numero_leccion}: {e}")
        print(f"Error en línea {sys.exc_info()[2].tb_lineno}")

4. actualizar_lecciones

Antes:

def actualizar_lecciones(self, estado_usuario):
    # Modulo 1
    self.estado_lecciones = {
        "Modulo1": {
            "Leccion1": estado_usuario.get("Modulo1", {}).get("Leccion1", False),
            "Leccion2": estado_usuario.get("Modulo1", {}).get("Leccion2", False),
            "Leccion3": estado_usuario.get("Modulo1", {}).get("Leccion3", False),
            "Leccion4": estado_usuario.get("Modulo1", {}).get("Leccion4", False),
            "Leccion5": estado_usuario.get("Modulo1", {}).get("Leccion5", False),
        },
        # Continúa para los demás módulos
    }

Ahora:

def actualizar_lecciones(self, estado_usuario):
    # Módulo 1
    self.estado_lecciones = {
        "modulo_1": {
            "Leccion1": estado_usuario.get("modulo_1", {}).get("Leccion1", False),
            "Leccion2": estado_usuario.get("modulo_1", {}).get("Leccion2", False),
            "Leccion3": estado_usuario.get("modulo_1", {}).get("Leccion3", False),
            "Leccion4": estado_usuario.get("modulo_1", {}).get("Leccion4", False),
            "Leccion5": estado_usuario.get("modulo_1", {}).get("Leccion5", False),
        },
        # Continúa para los demás módulos
    }
DanielDD-UNPHU commented 3 weeks ago

Modificación de Archivos JSON

Para soportar el uso de identificadores únicos (id_modulo), también fue necesario modificar la estructura de los archivos JSON utilizados en el proyecto.

1. progreso.json:

2. leccion_completada.json:

Nueva Estructura de los Archivos JSON

{
    "Daniel": {
        "modulo_1": {
            "Leccion_completada1": true,
            "Leccion_completada2": true,
            "Leccion_completada3": true,
            "Leccion_completada4": true,
            "Leccion_completada5": true
        },
        "modulo_2": {
            "Leccion_completada1": true,
            "Leccion_completada2": true,
            "Leccion_completada3": true
        },
        "modulo_3": {
            "Leccion_completada1": true,
            "Leccion_completada2": true,
            "Leccion_completada3": true,
            "Leccion_completada4": true,
            "Leccion_completada5": true
        },
        "modulo_4": {
            "Leccion_completada1": true,
            "Leccion_completada2": true,
            "Leccion_completada3": true,
            "Leccion_completada4": true,
            "Leccion_completada5": true
        },
        "modulo_5": {
            "Leccion_completada1": true,
            "Leccion_completada2": true,
            "Leccion_completada3": true,
            "Leccion_completada4": true,
            "Leccion_completada5": true,
            "Leccion_completada6": true,
            "Leccion_completada7": true
        }
    }
}
DLeonProyects commented 2 weeks ago

Documentación de Actualización de Funcionalidades: actualizar_progreso_usuario, actualizar_leccion_completada, y switch_page en los archivos Main de cada Modulo y Leccion Ejemplo (Elmer\Daniel_JSON_Files_Elmer\M1_LESSON_1_Codification\M1_L1_Main.py, M1_L2_Main.py, M1_L3_Main.py hasta M5_L7)

actualizar_progreso_usuario - Código Anterior

def actualizar_progreso_usuario(self, modulo, leccion_completada):
    try:
        with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'progreso.json'), 'r', encoding='UTF-8') as file:
            progreso = json.load(file)

        progreso_usuario = progreso.get(self.usuario_actual, {})

        # Calcula el número de la siguiente lección para desbloquearla en progreso.json
        numero_leccion_actual = int(leccion_completada.replace("Leccion", ""))
        siguiente_leccion = f'Leccion{numero_leccion_actual + 1}'

        if modulo in progreso_usuario:
            progreso_usuario[modulo][siguiente_leccion] = True  # Desbloquea la siguiente lección

        with open(os.path.join(os.path.dirname(os.path.abspath(__file__))), 'progreso.json'), 'w', encoding='UTF-8') as file:
            json.dump(progreso, file, indent=4)

    except Exception as e:
        print(f"Error al actualizar el progreso: {e}")

actualizar_progreso_usuario - Código Nuevo

def actualizar_progreso_usuario(self, id_modulo, leccion_completada):
    try:
        with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'progreso.json'), 'r', encoding='UTF-8') as file:
            progreso = json.load(file)

        progreso_usuario = progreso.get(self.usuario_actual, {})

        # Calcula el número de la siguiente lección para desbloquearla en progreso.json
        numero_leccion_actual = int(leccion_completada.replace("Leccion", ""))
        siguiente_leccion = f'Leccion{numero_leccion_actual + 1}'

        if id_modulo in progreso_usuario:
            progreso_usuario[id_modulo][siguiente_leccion] = True  # Desbloquea la siguiente lección

        with open(os.path.join(os.path.dirname(os.path.abspath(__file__))), 'progreso.json'), 'w', encoding='UTF-8') as file:
            json.dump(progreso, file, indent=4)

    except Exception as e:
        print(f"Error al actualizar el progreso: {e}")

actualizar_leccion_completada - Código Anterior

def actualizar_leccion_completada(self, modulo, leccion_completada):
    try:
        with open(os.path.join(os.path.dirname(os.path.abspath(__file__))), 'leccion_completada.json'), 'r', encoding='UTF-8') as file:
            leccion_completada_data = json.load(file)

        leccion_completada_usuario = leccion_completada_data.get(self.usuario_actual, {})

        # Marca la lección actual como completada en leccion_completada.json
        if modulo not in leccion_completada_usuario:
            leccion_completada_usuario[modulo] = {}
        leccion_completada_usuario[modulo][f"Leccion_completada{leccion_completada.replace('Leccion', '')}"] = True

        leccion_completada_data[self.usuario_actual] = leccion_completada_usuario

        with open(os.path.join(os.path.dirname(os.path.abspath(__file__))), 'leccion_completada.json'), 'w', encoding='UTF-8') as file:
            json.dump(leccion_completada_data, file, indent=4)

    except Exception as e:
        print(f"Error al actualizar lección completada: {e}")

actualizar_leccion_completada - Código Nuevo

def actualizar_leccion_completada(self, id_modulo, leccion_completada):
    try:
        with open(os.path.join(os.path.dirname(os.path.abspath(__file__))), 'leccion_completada.json'), 'r', encoding='UTF-8') as file:
            leccion_completada_data = json.load(file)

        leccion_completada_usuario = leccion_completada_data.get(self.usuario_actual, {})

        # Marca la lección actual como completada en leccion_completada.json
        if id_modulo not in leccion_completada_usuario:
            leccion_completada_usuario[id_modulo] = {}
        leccion_completada_usuario[id_modulo][f"Leccion_completada{leccion_completada.replace('Leccion', '')}"] = True

        leccion_completada_data[self.usuario_actual] = leccion_completada_usuario

        with open(os.path.join(os.path.dirname(os.path.abspath(__file__))), 'leccion_completada.json'), 'w', encoding='UTF-8') as file:
            json.dump(leccion_completada_data, file, indent=4)

    except Exception as e:
        print(f"Error al actualizar lección completada: {e}")

switch_page - Código Anterior

def switch_page(self, forward=True):
    current_index = self.stacked_widget.currentIndex()

    if forward:
        next_index = current_index + 1
    else:
        self.submit_button.hide()
        self.continue_button.show()
        next_index = current_index - 1

    current_page_type = self.stacked_widget.currentWidget().page_type.lower()  # Obtener el tipo de página actual
    self.log_event(
        f"{current_page_type.capitalize()} Page Close Time")  # Registrar el evento de cierre de la página actual

    current_widget = self.stacked_widget.currentWidget()
    if hasattr(current_widget, "lesson_completed"):
        self.lesson_finished_successfully = True

    # Si el siguiente índice es menor que el número total de páginas, continuar navegando
    if next_index < self.stacked_widget.count():
        if forward:
            self.update_highest_page(next_index)
            next_index = current_index + 1
            self.XP_Ganados += 1
            self.progress_bar.increment_page()
        else:
            self.is_rollback = True
            self.submit_button.hide()
            self.continue_button.show()
            next_index = current_index - 1
            self.XP_Ganados -= 1
            self.progress_bar.decrement_page()
        # Antes de cambiar de página, añadimos un punto y log para debug.
        self.stacked_widget.setCurrentIndex(next_index)  # Cambiar a la siguiente página
        self.log_part_change()  # Registrar el cambio a la "Parte 1"

        current_page_type = self.stacked_widget.currentWidget().page_type.lower()  # Obtener el tipo de página actualizado
        self.log_event(
            f"{current_page_type.capitalize()} Page Open Time")  # Registrar el evento de apertura de la nueva página

        if current_page_type == "pedagogical" or current_page_type == "pedagogical2":
            self.SubmitHideContinueShow(True,
                                        False)  # Si la nueva página es una pregunta, mostrar el botón de envío y ocultar el botón de continuar

        elif current_page_type == "practica":
            self.SubmitHideContinueShow(False,
                                        True)  # Si la nueva página no es una pregunta, y es práctica, ocultar el botón de envío y el de continuar, y mostrar el de practica
        else:
            self.SubmitHideContinueShow(False,
                                        False)  # Si la nueva página no es una pregunta, ocultar el botón de envío y mostrar el botón de continuar

        if not forward:
            self.submit_button.hide()
            self.continue_button.show()
            self.back_button.hide()
    # Sí se alcanza el final del recorrido de páginas, guardar el registro y cerrar la aplicación
    elif not next_index < self.stacked_widget.count():
        self.continue_button.hide()
        self.terminar_button.show()
        self.save_log(modulo=1, leccion=1)
        self.XP_Ganados += 5  # 5 puntos por terminar la lección.
        self.actualizar_puntos_en_leaderboard(self.usuario_actual, self.XP_Ganados)
        self.actualizar_progreso_usuario('Modulo1', 'Leccion1')
        self.actualizar_leccion_completada('Modulo1', 'Leccion1')
        update_lesson_status(self.usuario_actual, 'Modulo1', 'Leccion1', self.all_correct)

        if self.streak.get_current_streak() > 0:
            update_streak(self.usuario_actual, self.streak.get_current_streak())
        #Badge verification correct anwers streak
        check_streak_badges(int(read_stored_streak(self.usuario_actual)), self.usuario_actual)
        get_badge_level(self, score=self.leaderboard_window_instace.get_current_user_score() + self.XP_Ganados)
        update_lesson_dates(self.usuario_actual, "Modulo1", "Leccion_completada1")
        if are_lessons_completed_same_day(self.usuario_actual, "Modulo1") and not is_badge_earned(self.usuario_actual, 'modulo_rapido'):
                display_badge('modulo_rapido')
                update_badge_progress(self.usuario_actual, 'modulo_rapido')            
        if are_two_lessons_completed_same_day(self.usuario_actual, "Modulo1") and not is_badge_earned(self.usuario_actual, 'doble_aprendizaje'):
            display_badge('doble_aprendizaje')
            update_badge_progress(self.usuario_actual, 'doble_aprendizaje')
        if are_three_modules_completed(self.usuario_actual) and not is_badge_earned(self.usuario_actual, 'Explorador_curioso'):
            display_badge('Explorador_curioso')
            update_badge_progress(self.usuario_actual, 'Explorador_curioso')
        if check_module_streak_per_user(self.usuario_actual) and not is_badge_earned(self.usuario_actual, 'dominador_modulo'):
            display_badge('dominador_modulo')
            update_badge_progress(self.usuario_actual, 'dominador_modulo')
        self.close()
    else:
        print("¡La leccion no se completó, se cerró!.")
        self.close()

switch_page - Código Nuevo


    def switch_page(self, forward=True):
        current_index = self.stacked_widget.currentIndex()

        if forward:
            next_index = current_index + 1
        else:
            self.submit_button.hide()
            self.continue_button.show()
            next_index = current_index - 1

        current_page_type = self.stacked_widget.currentWidget().page_type.lower()  # Obtener el tipo de página actual
        self.log_event(
            f"{current_page_type.capitalize()} Page Close Time")  # Registrar el evento de cierre de la página actual

        current_widget = self.stacked_widget.currentWidget()
        if hasattr(current_widget, "lesson_completed"):
            self.lesson_finished_successfully = True

        # Si el siguiente índice es menor que el número total de páginas, continuar navegando
        if next_index < self.stacked_widget.count():
            if forward:
                self.update_highest_page(next_index)
                next_index = current_index + 1
                self.XP_Ganados += 1
                self.progress_bar.increment_page()
            else:
                self.is_rollback = True
                self.submit_button.hide()
                self.continue_button.show()
                next_index = current_index - 1
                self.XP_Ganados -= 1
                self.progress_bar.decrement_page()

            # Cambiar a la siguiente página
            self.stacked_widget.setCurrentIndex(next_index)
            self.log_part_change()  # Registrar el cambio a la "Parte 1"

            current_page_type = self.stacked_widget.currentWidget().page_type.lower()  # Obtener el tipo de página actualizado
            self.log_event(
                f"{current_page_type.capitalize()} Page Open Time")  # Registrar el evento de apertura de la nueva página

            if current_page_type == "pedagogical" or current_page_type == "pedagogical2":
                self.SubmitHideContinueShow(True, False)  # Mostrar el botón de envío y ocultar el botón de continuar
            elif current_page_type == "practica":
                self.SubmitHideContinueShow(False, True)  # Mostrar el botón de práctica y ocultar los demás
            else:
                self.SubmitHideContinueShow(False, False)  # Mostrar el botón de continuar y ocultar el botón de envío

            if not forward:
                self.submit_button.hide()
                self.continue_button.show()
                self.back_button.hide()

        # Sí se alcanza el final del recorrido de páginas, guardar el registro y cerrar la aplicación
        elif not next_index < self.stacked_widget.count():
            self.continue_button.hide()
            self.terminar_button.show()
            id_modulo = "modulo_1"
            leccion = f"Leccion{self.lesson_number}"

            self.save_log(modulo=id_modulo, leccion=self.lesson_number)
            self.XP_Ganados += 5  # 5 puntos por terminar la lección.
            self.actualizar_puntos_en_leaderboard(self.usuario_actual, self.XP_Ganados)
            self.actualizar_progreso_usuario(id_modulo, leccion)
            self.actualizar_leccion_completada(id_modulo, leccion)
            update_lesson_status(self.usuario_actual, id_modulo, leccion, self.all_correct)

            if self.streak.get_current_streak() > 0:
                update_streak(self.usuario_actual, self.streak.get_current_streak())

            # Verificación de insignias y actualizaciones
            check_streak_badges(int(read_stored_streak(self.usuario_actual)), self.usuario_actual)
            get_badge_level(self, score=self.leaderboard_window_instace.get_current_user_score() + self.XP_Ganados)
            update_lesson_dates(self.usuario_actual, id_modulo, f"Leccion_completada{self.lesson_number}")

            if are_lessons_completed_same_day(self.usuario_actual, id_modulo) and not is_badge_earned(
                    self.usuario_actual, 'modulo_rapido'):
                display_badge('modulo_rapido')
                update_badge_progress(self.usuario_actual, 'modulo_rapido')

            if are_two_lessons_completed_same_day(self.usuario_actual, id_modulo) and not is_badge_earned(
                    self.usuario_actual, 'doble_aprendizaje'):
                display_badge('doble_aprendizaje')
                update_badge_progress(self.usuario_actual, 'doble_aprendizaje')

            if are_three_modules_completed(self.usuario_actual) and not is_badge_earned(self.usuario_actual,
                                                                                        'Explorador_curioso'):
                display_badge('Explorador_curioso')
                update_badge_progress(self.usuario_actual, 'Explorador_curioso')

            if check_module_streak_per_user(self.usuario_actual) and not is_badge_earned(self.usuario_actual,
                                                                                         'dominador_modulo'):
                display_badge('dominador_modulo')
                update_badge_progress(self.usuario_actual, 'dominador_modulo')

            self.close()
        else:
            print("¡La lección no se completó, se cerró!.")
            self.close()

        if next_index == self.highest_page_reached and self.is_rollback:
            self.is_rollback = False
            self.json_windows[next_index].reset_button()
        self.current_page += 1  # Incrementar el número de la página actual

        # Verificación de insignias para la primera respuesta correcta
        if self.current_page == 2 and not is_badge_earned(self.usuario_actual, 'gran_paso'):
            if self.XP_Ganados > 0 and self.XP_Ganados <= 4:
                display_badge('gran_paso')
                update_badge_progress(self.usuario_actual, 'gran_paso')
DLeonProyects commented 2 weeks ago

en cada Main de las leccion recordar modificar la variable.

id_modulo = "modulo_1"

image