1. Introducción y Metas

WIChat es una aplicación basada en el popular concurso "Saber y Ganar" y una versión actualizada de la aplicación WIQ creada por HappySw. El objetivo de este proyecto es añadir funcionalidad y modernizar la aplicación WIQ para mejor la experiencia de usuario cumpliendo con varios objetivos:

  • El aprendizaje por parte de los usuarios de los temas incluidos en las preguntas.

  • Mejorar la interfaz de la aplicación y adaptarla a las nuevas funciones introducidas.

  • Promover la interacción del usuario con la IA para asistirle.

  • Replicar al máximo posible el formato de un concurso de preguntas en WIChat.

1.1. Vista general de los requisitos

La función principal de WIChat es presentar a los usuarios una serie de preguntas que tienen que tratar de responder correctamente, similar al concurso de preguntas "Saber y Ganar".

Las preguntas tendrán un enunciado adjuntado a una imagen y una serie de respuestas posibles. A más preguntas respondidas correctamente, más puntuación.

Los usuarios pueden interactuar con un LLM que le brinde pistas y ayude al usuario.

Requisitos de alto nivel:

  1. El sistema permitirá a los usuarios no registrados registrarse en la aplicación.

    1. El registro pedirá obligatoriamente a los usuarios:

      1. Un nombre de usuario.

      2. Un correo.

      3. Una contraseña.

      4. La confirmación de esa contraseña.

    2. Si el registro es exitoso, se guardará la información del usuario en la base de datos y se le redirigirá a la pantalla principal.

    3. Si el registro NO es exitoso, notificará el fallo al usuario.

  2. El sistema permitirá a los usuarios registrados autentificarse en la aplicación.

    1. La autenticación pedirá obligatoriamente a los usuarios:

      1. Un nombre de usuario.

      2. Una contraseña.

    2. Si la autenticación es exitosa, se rederigirá al usuario registrado a la pantalla principal.

    3. Si la autenticación NO es exitosa, notificará el fallo al usuario.

  3. Los usuarios registrados podrán jugar concursos en los que responderán preguntas.

    1. El usuario podrá elegir la temática y dificultad del concurso.

      1. Las temáticas son variadas y contarán con categorías como banderas, ciudades, etc…​

      2. Habrá cuatro niveles de dificultad que alteren la cantidad de preguntas a contestar y el tiempo para responder la pregunta, fácil, medio, difícil y supervivencia.

      3. En el modo supervivencia si el usuario falla una pregunta, se acabará el juego automáticamente. Cada 5 preguntas se restará el tiempo que tiene el usuario para responder a la pregunta.

    2. Los concursos tiene un límite de tiempo indicado por un temporizador.

      1. Si el usuario se queda sin tiempo, se pasa a la siguiente pregunta del concurso, siempre que no esté en el modo supervivencia.

    3. El usuario puede acumular rachas de puntuación.

      1. Si el usuario responde varias preguntas consecutivas, se creará una racha que hará que el usuario gane más puntos por pregunta acertada.

    4. Las preguntas y respuestas se deben generar automáticamente con información conseguida de WikiData.

      1. Las preguntas deben incluir una imagen, un enunciado y varias respuestas incorrectas.

      2. Los datos de la pregunta deben ser guardados en base de datos.

    5. Los usuarios registrados pueden interactuar con un LLM.

      1. En forma de pistas de la pregunta actual.

      2. En forma de un chat conversacional simulando un "comodín de la llamada".

    6. Al acabar el concurso, se le mostrará al usuario información sobre el concurso.

      1. Se mostrará cuantas preguntas han sido acertadas.

      2. Se mostrará un botón por si el usuario quisiera volver a jugar otro concurso.

  4. Los usuarios registrados podrán consultar un histórico de su participación en el sistema con la siguiente información:

    1. Número de concursos jugados.

    2. Preguntas acertadas y falladas en cada concurso.

    3. Tiempo de juego de cada concurso.

    4. Puntuación de cada concurso.

  5. El sistema ofrecerá una API que permita obtener información sobre:

    1. Los usuarios registrados en la aplicación. Se puede obtener la siguiente información:

      1. Su nombre de usuario.

      2. Los concursos que han jugado.

      3. Las preguntas acertadas y falladas en los concursos jugados.

      4. Los tiempos de juego en los concursos jugados.

    2. Las preguntas generadas por la aplicación. Se puede obtener la siguiente información:

      1. Enunciado de la pregunta.

      2. Respuestas generadas, indicando cual es la correcta.

      3. Imagen utilizada en la pregunta.

La aplicación, debido a su enfoque para todos los públicos, debe tener un especial enfoque en la usabilidad. Debe ser fácil de usar y tener una curva de aprendizaje poco inclinada.

1.2. Metas de calidad

Atributo de calidad Motivación

Usabilidad

La aplicación, debido a su enfoque para todos los públicos, debe tener un especial enfoque en la usabilidad. Debe ser fácil de usar y tener una curva de aprendizaje poco inclinada.

Disponibilidad

La aplicación debe estar disponible una gran mayoría del tiempo.

Rendimiento

El tiempo de respuesta de la aplicación debe ser corto para ofrecer una experiencia de juego fluida y disfrutable

Interoperabilidad

WIChat tendrá una API con la que se puede obtener información relevante a los usuarios y las preguntas generadas. El sistema obtendrá información de WikiData y se comunicará con un LLM.

Modificabilidad

El sistema debe ser fácil de cambiar y de añadir nuevas funcionalidades para facilitar futuras actualizaciones.

Escalabilidad

El sistema tiene que ser escalable para que así, en un futuro, más usuarios puedan disfrutar al mismo tiempo de la app.

Sabiendo los atributos de calidad más relevantes, podemos definir unos requisitos no funcionales adecuados.

Requisitos no funcionales:

  1. El tiempo de aprendizaje de un nuevo usuario debe ser menor a 1 hora.

  2. El sistema será compatible con Windows, iOS y Linux.

  3. La aplicación deberá funcionar en navegadores web estándar, asegurando la compatibilidad con versiones recientes de Chrome, Firefox, Safari y Edge.

  4. El sistema debe ser capaz de operar adecuadamente con bastantes usuarios de forma concurrente.

  5. El tiempo para iniciar o reiniciar el sistema por si surgiese algún error no puede ser más de 30 minutos.

  6. El sistema debe emplear Wikidata para construir las preguntas.

  7. El sistema debe emplear un LLM para formular pistas para el usuario.

  8. El tiempo en generar las preguntas de un concurso no debe ser mayor a 20 segundos.

1.3. Stakeholders

Nombre Metas

Equipo de desarrollo

Desarrolladores que quieren crear una aplicación robusta. Se usan varias tecnologías nuevas que incitan al aprendizaje por parte del equipo.

ChattySw

Empresa responsable de WIChat. Quieren un producto satisfactorio que sea a gusto del cliente y que el desarrollo de la misma sea lo más ágil y lo menos costoso posible.

RTVE

El cliente que pidió el producto. Quiere el mejor producto posible y se beneficia directamente de el.

Usuarios

Los usuarios de la aplicación. Buscan la mejor experiencia de usuario posible y el aprendizaje derivado de las preguntas respondidas.

HappySw

Responsables de la version experimental anterior de WIChat. Competidora de ChattySw.

2. Restricciones de la arquitectura

2.1. Motivación

Es fundamental que los arquitectos de software sean capaces de distinguir dónde tienen libertad de decisión y dónde deben cumplir con ciertas restricciones.

Por ello, en este punto de la documentación se recoge cualquier requisito que limite la libertad de los arquitectos de software en sus decisiones de diseño, implementación o en el proceso de desarrollo.

Restricciones de negocio
  • Plazos de entrega: El sistema debe estar operativo en un tiempo limitado para cumplir con el contrato con RTVE.

  • Presupuesto: Se debe trabajar dentro de un presupuesto fijo acordado con RTVE.

Restricciones técnicas
  • Estructura: El sistema deberá de contar con un frontend web accesible (mostrará las imágenes y respuestas, además del sistema de pistas que permitirá a los usuarios obtener pistas sobre las imágenes) y una API documentada (permitirá acceder a la información de las preguntas generadas).

  • Infraestructura: La aplicación debe estar desplegada y accesible a través de la web.

  • Generación de contenido: Las preguntas y respuestas deben generarse automáticamente a partir de datos de Wikidata. Dichas preguntas deberán tener una respuesta correcta y varias distractoras, todas ellas generadas automáticamente por Wikidata.

  • Integración con un LLM: Se utilizará un modelo de lenguaje externo para generar pistas conversacionales (se debe mitigar la generación de respuestas incorrectas o alucinaciones).

Restricciones de dependencias
  • Disponibilidad de APIs externas: Dependencia de Wikidata y del LLM, que pueden tener tiempos de respuesta o restricciones de uso.

3. Contexto y alcance

En este capítulo se describe el ámbito de WIChat. Se ven los sistemas de los que depende la aplicación y los usuarios que la usan.

3.1. Contexto de negocio

Contexto de negocio WIChat
Usuario

Cualquier usuario que se disponga a usar la aplicación. Los usuarios deben de registrarse antes de acceder al juego. En el juego los usuarios responderán preguntas y aprenderán de ellas. También pueden consultar sus datos históricos en la aplicación.

Gemini

Los usuarios pueden interactuar con el LLM "Gemini" a través de WIChat para pedir pistas y asistencia para responder preguntas.

WikiData

La información necesaria para que la aplicación genere las preguntas automáticamente es obtenida de la API de WikiData. De esta se sacan los enunciados de las preguntas, las respuestas correctas e incorrectas y las imágenes que se adjuntan a las preguntas.

3.2. Contexto técnico

Contexto técnico WIChat

La arquitectura de WIChat es una estructura basada en microservicios:

Users

El paquete users se divide en dos paquetes, "Auth service" que se encarga de la autenficación de los usuarios ya registrados y "Users service", que se encarga del registro de nuevos usuarios. Ambos se comunican con la base de datos para guardar o obetener información.

Wiki service

Es el servicio encargado de comunicarse con la API de WikiData para generar las preguntas y respuestas mostradas a los usuarios. Las preguntas generadas son guardadas en base de datos para el historial de los usuarios.

Gateway service

El gateway se encarga de recibir las peticiones y redirigirlas al servicio correspondiente. Además será el que tenga la OpenApi con la que el usuario que quiera acceder a esta(representado como Usuario_API) pueda visualizar los datos relacionados a la aplicación, como los usuarios y las preguntas generadas.

History service

Es el servicio que se encarga con todo lo relacionado con el historial de partidas de la aplicación

WebApp

Donde se encuentra todo el front-end de la aplicación. Se encargará de pedirle servicios al gateway para que el usuario pueda interactuar con las distintas características de la aplicación.

Llm service

Es el servicio que se encarga de hacer llamadas a la Api de Gemini.

MongoDB

Todos los datos de la aplicación se guardarán en una base de datos hecha con MongoDB.

4. Estrategia de solución

4.1. Decisiones tecnológicas

Las siguientes tecnologías han sido usadas a lo largo del desarrollo de nuestra aplicación:

  • JavaScript: Hemos elegido usar JavaScript como el lenguaje de la aplicación debido a que el esqueleto que se nos proporcionó ya venía con código en este lenguaje, entonces para más comodidad, hemos seguido usándolo. Además, es un lenguaje compatible con todos los navegadores que maneja tanto programación orientada a objetos como funcional y que nos permite crear páginas web interactivas y dinámicas sin necesidad de recargar la página. Además de que maneja asincronía y es un lenguaje muy versátil.

  • MongoDB: Hemos elegido usar MongoDB para la base de datos de la aplicación debido a que tiene un modelo de datos flexible ya que no requiere esquema fijo, es fácil de modificar y además usa BSON (Binary JSON), lo que permite que no se requiera un alto conocimiento por ejemplo en SQL y se almacenen los datos de manera eficiente.

  • Gemini: Usamos Gemini como LLM de la aplicación ya que disponemos de una ApiKey de este, lo que nos permite poder procesar texto, imágenes, audios o vídeos con él. También puede analizar imágenes y responder preguntas sobre ellas en tiempo real, lo cual es bastante conveniente para el tipo de aplicación que deseamos hacer.

  • Wikidata: Nos sirve para usar los distintos datos que nos proporciona de manera totalmente gratuita. Cuenta con una traducción automática de datos y soporta más de 400 idiomas. Ofrece una API pública para consultar datos desde aplicaciones web o móviles y es compatible con tecnologías como TypeScript y JavaScript.

  • GitHub: Para subir el proyecto y sus respectivos cambios y poder tener un lugar de trabajo conjunto nos hemos decantado por GitHub porque nos permite un historial completo de los cambios que va a realizar cada miembro a lo largo del tiempo, así como la facilidad de trabajar en paralelo mediante el uso de ramas y que los distintos commits del proyecto se guardarán en la nube por si hubiera algún problema en el desarrollo. También cabe destacar el uso de issues y el de pull requests que nos sirven para revisar distitos cambios antes de fusionarlos con la rama principal del proyecto.

  • React: Hemos elegido React para construir nuestras interfaces de usuario debido a que es una biblioteca de JavaScript. React divide la interfaz de usuario en pqueños componentes reutilizables que facilitan el mantenimiento y escalabilidad del código. Además que al haber trabajado ya con JavaScript y HTML React es fácil de aprender y de usar.

  • Docker: Tecnología usada para desplegar el proyecto y todos sus distintos módulos en la web. Usamos docker ya que es el que se nos ha enseñado a utilizar en el laboratorio y además es un sistema portable que lo único que necesitamos es tener docker instalado para que funcione. Además de la eficiencia que nos permite empaquetar los contenedores en un período de tiempo razonable.

  • Node.js: Es una plataforma que nos permite ejecutar JavaScript en el servidor. Usamos Node.js debido a que viene incluido con NPM, es decir, con un gestor de paquetes que facilita la instalación y gestión de bibliotecas y módulos para nuestra aplicación ya que cuenta con una gran cantidad de módulos para cualquier cosa. También lo usamos debido a que nos permite crear servidores web rápidos que pueden manejar un gran número de conexiones simultáneas.

  • Express: Es un framework de JavaScript que se utiliza para desarrollar aplicaciones web y Apis en Node.js. Lo usamos debido a que es uno de los frameworks más populares para construir aplicaciones del lado del servidor debido a su simplicidad, flexibilidad y alto rendimiento.

  • Azure_Cloud: Para desplegar la aplicación usamos una máquina virtual hosteada en Azure_Cloud, ya que además de que todos los miembros del equipo de desarrollo tienen una cuenta, cuenta con ventajas como la escalabilidad, alta disponibilidad y fiabilidad.

  • Gatling: Hemos elegido Gatling para realizar las pruebas de carga debido a que se puede elegir entre java y scala a la hora de realizar los programas, nosotros hemos escogido scala, además de por proporcionar vistas claras y concisas en formato html y por disponer de un recorder con el que poder grabar las acciones que queremos que realicen los distintos usuarios de la aplicación.

4.2. Herramientas de apoyo

  • Visual Studio Code: Es el IDE que hemos usado los miembros del equipo por defecto ya que es un entorno con el que estamos familiarizados y que además contiene todos los mecanismos que necesitamos para trabajar con el proyecto y entre nosotros en el repositorio remoto.

  • Draw.io: A la hora de crear diagramas como los de bloques nos hemos decantado por esta herramienta online, debido a su facilidad de uso y varios tipos de plantillas para crear diagramas así como que es totalmente gratuita.

  • PlantUML: También para los diagramas hemos usado esta herramienta. Es totalmente gratuita y funciona escribiendo el diagrama UML en formato de texto y generándolo después en formato gráfico.

5. Vista de Bloques de Construcción

5.1. Visión general

BuildingBlock
Motivación

Esta es la visión general en la cual el usuario usa WIQ, que es la estructura general del proyecto y a su vez interactua con Wikidata para obtener los datos para poder desarrollar la aplicación

5.1.1. Componentes

Nombre Responsabilidad

Usuario

Usuario que interactuará con la aplicación.

Wichat

Responsable de la gestión del juego.

WikiData

Permite generar preguntas y respuestas, proporcionando la información.

Gemini

Permite generar pistas a las preguntas u consultas que haga el usuario de la aplicación.

5.2. Nivel 2

BuildingBlock2

5.2.1. Componentes

Nombre Responsabilidad

Usuario

Usuario que interactuará con la aplicación.

Webapp

Interfaz de la aplicación, que permite proporciona al usuario lo necesario para moverse por la aplicación: registrarse, iniciar sesión o jugar.

GatewayService

Sirve como punto de entrada para la aplicación, además de realizar las distintas llamadas a los diferentes servicios según el usuario lo requiera.

AuthService

Servicio de autenticación responsable de verificar los datos del usuario al iniciar sesión.

UserService

Servicio que se encarga de la gestión de los usuarios, añadir a la base de datos y validar los datos introducidos.

LlmService

Servicio responsable de realizar las llamadas a la api de llm y gestionar sus respuestas y comportamientos.

HistoryService

Servicio encargado de trabajar junto con la database para gestionar el historial de partidas del usuario.

WikiService

Servicio responsable de lanzar las querys a Wikidata para obtener la información.

MongoDB

Base de datos donde se almacenarán todos los datos relacionados con los usuarios y con las preguntas de los distintos juegos.

GeminiApi

Api proporcionada para interactuar con el modelo de lenguaje de Google Gemini.

5.3. Nivel 3-Servicio de Usuario

BuildingBlockuserservice

5.3.1. Componentes

Nombre Responsabilidad

AuthService

Solicitará a la base de datos un usuario para poder autentificarlo, verificará que el usuario suministrado por la base de datos nos proporcione el nombre de usuario y la contraseña correcta para poder acceder al juego.

UserService

Se encargará de todo lo relacionado con añadir usuarios a la base de datos. Se encargará de verificar el formato de los datos proporcioandos por el usuario para crearse una nueva cuenta, así como que la contraseña coincida con la validación de esta misma.

UserDb

La base de datos que se encargará de almacenar a los usuarios de la aplicación con su respectiva información como nombre, correo y la contraseña encriptada para más seguridad.

6. Vista de ejecución

6.1. Registrar usuario

  • Para poder jugar un usuario debe estar registrado

  • Para registrarse se necesita un nombre de usuario, un email y una contraseña

User registration diagram

6.2. Inicio de sesión

  • Un usuario ya registrado inicia sesión para poder jugar

  • El usuario debe introducr su nombre y contraseña correctos

Log in diagram

6.3. Generación de preguntas en una partida

  • Las preguntas necesarias para el juego son sacadas de WikiData

Play diagram

7. Diagrama de Despliegue

Diagrama de Despliegue

7.1. Motivación

En WIChat, los usuarios interactúan a través de una interfaz web basada en React.

Esta aplicación se despliega en un servidor en Azure, donde cada componente funciona dentro de contenedores Docker.

El WebApp será el front-end de la aplicación, el cual realizará llamadas de peticiones al Gateway Service, que hara llamadas al resto de servicios de la aplicación. El Gateway también contendrá una Api que almacenará todos los datos de los usuarios y las preguntas. Dos de los servicios antes mencionados son el WikiService y el LlmService, que realizarán solicitudes a sus respectivas Apis externas a la aplicación.

Los datos se almacenan en MongoDB, ejecutándose en un contenedor Docker en el mismo servidor.

7.2. Características de Calidad y Rendimiento

  • Escalabilidad: Cada servicio está encapsulado en un contenedor Docker, lo que permite escalar horizontalmente según la demanda.

  • Seguridad: Las interacciones con servicios externos requieren API Keys, tenemos doble verificación de la contraseña y esta se almacena encriptada en la base de datos.

  • Modularidad: La separación de servicios en microservicios facilita el mantenimiento y la extensibilidad del sistema.

7.3. Mapeo de Componentes a la Infraestructura

Servicio Descripción

WebApp

Frontend en React que permite la interacción del usuario con el sistema.

Gateway Service

Servicio que redirige las llamadas del WebApp a los distintos servicios de la aplicación. Contiene una Api que el usuario podrá consultar para mirar los datos de los usuarios de la aplicación como de las preguntas.

Auth Service

Responsable de la autenticación de los usuarios.

User Service

Maneja la gestión de usuarios, se encarga del registro de usuarios.

History Service

Gestiona y almacena el historial de participación de los usuarios.

Wiki Service

Servicio que interactúa con WikiData y que se encarga de la generación de preguntas.

LLM Service

Servicio que interactúa con la API de Gemini y que se encarga de generar las pistas para el usuario.

MongoDB

Base de datos utilizada para almacenar: - Información de usuarios. - Preguntas y respuestas generadas. - Historial de participación y partidas.

Gemini API

API de modelo de lenguaje utilizada para generar pistas en tiempo real.

API Wikidata

Fuente externa de información utilizada para la generación automática de preguntas.

8. Conceptos transversales

8.1. Modelo de Dominio

DiagramaDeClases
Nombre Descripción

Usuario

El usuario de la aplicación podrá acceder a un historial donde se guarden los datos de sus partidas anteriores, así como poder jugar la cantidad de juegos que el usuario vea necesario. También podrá acceder a su perfil y a un ranking donde estarán todas las puntaciones de los jugadores.

Historial

Contendrá tanto las preguntas falladas y acertadas de su usuario, como el número de juegos que ha jugado y los distintos tiempos que ha tardado en completar cada juego en segundos.

Juego

Será la clase encargada de toda la lógica de negocio, el usuario interactuará con el juego y el juego irá dándole preguntas al usuario para que este responda. A raíz de las respuestas del usuario el juego, al finalizarse, guardará los datos en el historial del usuario en concreto.

Pregunta

Las preguntas serán las que vea el usuario en pantalla, dependen enteramente de juego. Las preguntas tendrán una descripción y una lista de opciones de las cuales solo una será la correcta.

Perfil

Cada usuario tendrá un perfil, donde podrá cambiar sus datos personales así como ir a su historial.

8.2. Seguridad

La aplicación contará con un sistema de registro e inicio de sesión con contraseña que se almacenará encriptada en la base de datos para mayor privacidad del usuario. En el sistema de logueo se requerirá la doble autentificación de la contraseña y comprobar que ambos campos coincidan.

8.3. Interfaz de Usuario

Uso de ayuda: Nuestra interfaz de usuario contará con menús de ayuda para que los usuarios puedan acceder a ellos si se sienten perdidos o no entienden algo del funcionamiento de la aplicación. Estos menús estarán disponibles en todo momento y en la parte superior de la pantalla.

Usabilidad: El juego tendrá un formato parecido al de saber y ganar, ya que es el formato más cómodo para los usuarios y el más fidedigno a la vida real. Esto lo hacemos así debido a que es mucho mejor que el usuario sepa ya de antemano al ver la interfaz de usuario que es un juego de tipo "concurso de la tele" que experimentar con cosas raras y que el usuario se vea abrumado por la novedad.

Interacción en tiempo real: El usuario podrá ver si ha acertado o no la pregunta al momento de su respuesta, ya que esto es lo más amigable para el usuario y así puede llevar un conteo de las preguntas que ha respondido correctamente.

8.4. Arquitectura

Para la arquitectura inicial contamos con una aplicación divida en microservicios que engloban y encapsulan las distintas funcionalidades de la aplicación, esta es una buena manera de simplificar la creación y la gestión de una aplicación compleja, ya que cada funcionalidad es realizada por sistemas independientes. Algunos ejemplos de estos microservicios pueden ser el de Gestión de Usuarios que se encarga del registro, el inicio de sesión y todo lo relacionado con el usuario en la aplicación.

8.5. Procesos de Desarrollo

Testing: Se realizan pruebas unitarias relacionadas con cada funcionalidad del proyecto para asegurar su correcto funcionamiento.

Deployment: Es el proceso de poner en funcionamiento la aplicación para que se pueda ejecutar y acceder a ella. Para realizar el deployment utilizamos Docker para construir las imágenes de los servicios y subirlas al repositorio.

8.6. "Under-the-hood"

Persistencia: Los datos de los usarios y su historial de partidas quedarán almacenados en una base de datos para asegurar su integridad y disponibilidad.

Extensibilidad: La aplicación está diseñada para facilitar añadir nuevos contenidos y funcionalidades, esto lo conseguimos en gran parte gracias a la arquitectura basada en microservicios que dividen las funcionalidades en módulos independiente

9. Decisiones Arquitectónicas

9.1. Motivación

Las decisiones arquitectónicas de WIChat han sido tomadas con el objetivo de garantizar que la aplicación sea escalable, modular, segura y fácil de mantener. Dado que WIChat es una aplicación web interactiva que integra varias tecnologías y servicios externos, es fundamental que su arquitectura facilite tanto el desarrollo como el despliegue y la futura evolución del sistema.

9.2. Decisiones Claves

9.2.1. Arquitectura Basada en Microservicios

Motivación: Se ha optado por una arquitectura basada en microservicios para dividir la aplicación en módulos independientes que puedan gestionarse y escalarse de manera separada. Esta decisión se tomó considerando la complejidad de la aplicación y la necesidad de hacerla flexible ante futuras ampliaciones.

Consecuencias: Cada funcionalidad clave del sistema (autenticación, gestión de usuarios, generación de preguntas, etc.) está encapsulada en un servicio independiente, lo que facilita su mantenimiento y evolución. Se puede escalar individualmente cada servicio según su demanda, optimizando el uso de recursos. Se introduce la necesidad de gestionar la comunicación entre servicios, lo que aumenta la complejidad del sistema en comparación con una arquitectura monolítica. Se requiere un Gateway Service para orquestar las llamadas entre servicios y gestionar aspectos como autenticación y seguridad.

9.2.2. Uso de React para la Interfaz de Usuario

Motivación: Para la interfaz de usuario, se ha decidido utilizar React debido a su capacidad de construir aplicaciones web dinámicas y modulares. Al ser una biblioteca ampliamente utilizada en el desarrollo frontend, permite aprovechar su ecosistema y herramientas para mejorar la experiencia de usuario.

Consecuencias: React permite dividir la interfaz en componentes reutilizables, lo que facilita el mantenimiento y la evolución del sistema. La aplicación puede ofrecer una experiencia fluida gracias a su modelo de renderizado eficiente.

9.2.3. Base de Datos en MongoDB

Motivación: Para el almacenamiento de datos, se ha elegido MongoDB por su flexibilidad y capacidad de manejar información semiestructurada sin necesidad de definir un esquema rígido. Esto resulta ideal para gestionar datos de usuarios, preguntas generadas dinámicamente y registros históricos de partidas.

Consecuencias: Se pueden almacenar datos en un formato flexible, lo que facilita cambios futuros en la estructura de la base de datos. Se simplifica la escalabilidad, ya que MongoDB permite distribuir datos en múltiples servidores. Al ser una base de datos NoSQL, es necesario adoptar estrategias para mantener la consistencia y optimizar consultas.

9.2.4. Uso de Docker para Contenerización

Motivación: Para asegurar un entorno de desarrollo y producción consistente, se ha optado por contenerizar los servicios utilizando Docker. Esto permite desplegar la aplicación en cualquier servidor sin preocuparse por configuraciones específicas del sistema operativo.

Consecuencias: Cada microservicio se ejecuta en su propio contenedor, lo que facilita el despliegue y mantenimiento. Se mejora la portabilidad de la aplicación, ya que puede ejecutarse en distintos entornos sin cambios significativos. Se requiere gestionar adecuadamente los contenedores y la orquestación de servicios, lo que puede agregar complejidad al desarrollo y despliegue.

9.2.5. Integración con Wikidata y un Modelo de Lenguaje (LLM)

Motivación: Uno de los pilares de WIChat es la generación automática de preguntas basadas en información de Wikidata. Además, se ha integrado un modelo de lenguaje (LLM) para proporcionar pistas y mejorar la interacción con los usuarios.

Consecuencias: Se reduce la necesidad de intervención manual en la creación de preguntas, automatizando el proceso y permitiendo una mayor variedad de contenidos. Se introduce una dependencia con servicios externos, lo que puede afectar la disponibilidad y latencia del sistema en caso de problemas en estas APIs. Es necesario implementar mecanismos para validar y filtrar la información generada, evitando errores o inconsistencias en las preguntas y respuestas.

9.2.6. Seguridad mediante encriptación

Motivación: Dado que WIChat maneja información de usuarios, es esencial garantizar su seguridad. Para ello, las contraseñas se guardarán encriptadas en la base de datos y se requerirá de doble autentificación.

Consecuencias: Si el usuario se equivoca una vez escribiendo la contraseña podrá darse cuenta de su error. Se protege la integridad de los datos del usuario, ya que ni siquiera el equipo desarrollador tiene acceso a su contraseña.

10. Requisitos de calidad

10.1. Quality Tree

Árbol de atributos de calidad

10.2. Quality Scenarios

10.2.1. Usabilidad y experiencia de usuario

  • Interactividad fluida: La aplicación debe ser intuitiva y fácil de usar, es decir, los usuarios deben poder navegar entre preguntas, acceder a pistas y responder sin dificultades. El tiempo de respuesta del sistema debe ser bajo para evitar frustración.

  • Accesibilidad y diseño web: El sistema debe ser totalmente accesible desde la web.

10.2.2. Rendimiento

  • Tiempo de respuesta: El tiempo para obtener pistas, preguntas y procesar las respuestas debe ser mínimo. Con esto nos referimos a las consultas a APIs externas para la obtención de información de Wikidata y la generación de respuestas o pistas por parte del LLM.

10.2.3. Seguridad

  • Protección de la información del usuario: El sistema debe garantizar la seguridad de los datos personales de los usuarios relacionados con el histórico de su participación en el sistema.

  • Autenticación y autorización: El acceso a funcionalidades de usuario como consultar el número de juegos, preguntas acertadas/falladas… debe estar protegido mediante autenticación segura.

10.2.4. Mantenibilidad

  • Código limpio y documentado: El código fuente debe ser legible, bien estructurado y documentado para facilitar su mantenimiento y extensión. La calidad del código será evaluada mediante revisiones periódicas y el uso de herramientas de análisis estático de código.

  • Actualizaciones y despliegues continuos: La aplicación debe seguir un ciclo de vida de desarrollo ágil, con integración y despliegue continuos (CI/CD), permitiendo que las nuevas funcionalidades y correcciones sean implementadas de manera fluida y sin afectar a los usuarios finales.

10.2.5. Pruebas y calidad del software

  • Cobertura de pruebas: El sistema debe contar con un conjunto completo de pruebas unitarias e integración.

  • Pruebas de aceptación: Se deben realizar pruebas de aceptación (end-to-end).

  • Pruebas de carga: El sistema debe someterse a pruebas de carga.

  • Monitorización de la aplicación

*Pruebas de Usabilidad El sistema debe probarse con usuarios reales en su fase de desarrollo de manera continua.

11. Riesgos y Deuda Técnica

11.1. Riesgos

A continuación se expresan algunos riesgos encontrados que suponen un peligro al desarrollo del proyecto y pueden retrasarlo o mermar su calidad.

Riesgo Descripción Mitigación

Poco o nulo conocimiento de las tecnologías usadas

Varias de las tecnologías usadas en el proyecto son nuevas para el equipo de desarrollo, lo que puede llevar a mal uso de estas y un código deficiente.

Tratar de informarse bien de estas tecnologías mediante documentación, tutoriales u otras herramientas externas.

Poca experiencia en gestión de proyectos

Al ser uno de los primeros proyectos a mayor escala hecho por los desarrolladores, la gestión, decisiones y desarrollo del proyecto puede no ser el mejor posible.

Identificar los riesgos de proyectos pasados y escuchar las experiencias de compañeros y los consejos de los profesores puede ayudar a evitar los errores más comunes y encaminar el proyecto.

Trabajo en equipo deficiente

La falta de experiencia en proyectos puede llevar a un trabajo en equipo no muy favorable, ya sea por falta de comunicación, falta de organización o reparto ineficiente de las tareas.

Promover la comunicación, ayuda y cooperación entre los miembros del equipo.

Uso ineficiente del control de versiones

Aunque GitHub no es una tecnología nueva, contiene muchas funciones complejas y nuevas que aunque resultan útiles, pueden causar confusión.

Informarse de las posibilidades que ofrece GitHub y promover un buen uso de este.

Fechas de entregas

Debido a las estrictas fechas de entrega, puede llevar a prisa en las entregas y atajos poco recomendables.

Llevar un registro constante del trabajo realizado y promover el trabajo constante semana a semana.

Abandono de miembros del equipo

Alguno de los miembros del grupo puede abandonar el proyecto, perjudicando el ritmo del desarrollo y dejando tareas desasignadas.

Minimizar el "factor del autobús", revisando el trabajo de otros compañeros y asignando el trabajo a varios compañeros.

Problemas con el hardware o software del equipo

Cuestiones como apagones, corrupción de los datos de un programa o inabilitación del uso de un ordenador portátil son cosas que le podrían pasar a cualquier miembro del equipo

Haciendo que los demás tengan que repartirse sus tareas o si nadie puede, la anulación de la tarea en sí ayuda a paliar estos efectos.

11.2. Deuda Técnica

Atajos o compromisos que se han tomado para acortar el tiempo de desarrollo o bajar la complejidad de la implementación.

Deuda Técnica Descripción

Comienzo del desarrollo desde la base creada por los profesores

Usamos una base para el proyecto con varios microservicios ya incorporados y con algunas tecnologías ya usadas. Al ser código no desarrollado por el equipo, puede resultar en confusión e implementación deficiente.

Abandono de un miembro del equipo

Un miembro del equipo abandonó el proyecto entre el segundo y tercer sprint, es decir, antes de la entrega de la aplicación 1.0. Esto supuso un contratiempo para el equipo que se pudo recomponer pero que perdió todos los archivos de los que disponía el compañero y además nos tuvimos que readministrar las tareas de este último, las cuales si que se iban dejando un poco más de lado.

Apagón masivo

Hubo un apagón el día en el que el equipo quería dejar el repositorio totalmente listo para la entrega del proyecto al solicitante, esto impidió el avance del equipo durante un buen rato y llevo a la desmoralización de la plantilla.

Uso de tecnologías nuevas

Muchas de las tecnologías que se han usado, como por ejemplo Gatling para las pruebas de carga y el lenguaje scala, son tecnologías nuevas con documentaciones extensas y muchas versiones, las cuales nos ha costado adaptarnos en un principio. Muchas de estas tecnologías han provocado cambios luego en las tecnologías utilizadas por el equipo de desarrollo.

Ordenadores portátiles inhabilitados

A dos miembros del grupo se les estropeó el ordenador en dos momentos del desarrollo distintos. El equipo subo solucionarlo bastante rápido y los días que los compañeros estuvieron sin sus dispositivos tampoco fueron muchos.

12. Test

12.1. Test unitarios

Hemos realizado diversos test para cada servicio de la aplicación usando Jest y Testing Library de React. Para cada componente del Webapp por ejemplo hemos creado una clase test propia para probar sus funcionalidades, así como para cada servicio del backend.

Este ha sido un proceso que hemos desarrollado a lo largo del proyecto y del cual nos hemos ayudado de la herramiennta SonarCloud que analiza el código de nuestro repositorio de GitHub para decirnos cual es nuestro porcentaje de código cubierto por test, así como las posibles brechas de seguridad que puede tener la aplicación(muchas de estas falsos positivos).

Aunque el porcentaje pueda variar un poco al final del proyecto hemos conseguido superar un 80% de coverage para el código global de la aplicación. Requisito necesario para que la aplicación tenga suficientes test.

Test unitarios

12.2. Test de Usabilidad

Hemos realizado dos tandas con usuarios tanto en el sprint 3 como en el sprint 4 para que probaran la aplicación desplegada.

Estos usuarios eran personas jóvenes de entre 20 y 30 años de edad, bastante familiarizados con las aplicaciones web en general, por lo que la curva de aprendizaje fue bastante rápida y no supuso un gran problema.

Algunos de los problemas que encontraron los usuarios y que nos parecieron relevantes fueron:

12.2.1. Sprint 3

  • Las preguntas en difícil tardan bastante en generar(1 minuto).

  • La ventana del chat tapa su propio botón de cerrar.

  • El botón siguiente pregunta se va desplazando hacia abajo con cada click.

  • La primera vez que le das al botón de iniciar sesión no va, tienes que darle dos veces.

12.2.2. Sprint 4

  • El botón del LLM no era intuitivo para su uso, haciendo que el usuario no supiera si estaba desactivado.

  • Algunas preguntas de comida enseñaban códigos en vez de respuestas.

  • Un bug en el modo supervivencia que hacía que se repitiese la misma pregunta a partir de la 20.

12.3. Test E2E

Para la realización de test End to End hemos usado el framework de Cucumber. Los test E2E son pruebas automatizadas que validan el funcionamiento de una aplicación desde el punto de vista del usuario final. Su objetivo es comprobar que todos los componentes del sistema como el front, back, base de datos y demás, funcionen juntos como se espera.

Nosotros hemos implementado 3 features a los test, siendo estas:

  • Game:Simulará al jugador jugando juegos en distintas dificultades e interactuando con el LLM mientras juega.

  • Login-form:Simulará el formulario de registro y los posibles errores que puede cometer el usuario al meter datos incorrectos o no estar registrado.

  • Register-form:Simulará el formulario de identificación de usuario y los posibles errores que puede cometer el usuario al meter datos incorrectos.

12.4. Test de carga

Para realizar los test de carga hemos usado la herramienta Gatling, usando el lenguaje scala para crear los distintos programas y haciendo uso de la funcionalidad de recorder de Gatling para "grabar" los movimientos de un usuario por la aplicación y luego adaptarlos a los test de carga.

Hemos probado los test de carga con la aplicación deplegada, ya que si lo hicieramos en local, se tendrían en cuenta los componentes de nuestro sistema. Además se ha creado una función en los programas que aleatoriza la creación de usuarios, siendo casi imposible que dos usuarios tengan el mismo nombre, correo u contraseña(aunque esta última podría ser igual).

Los pasos que hemos grabado han sido los siguientes: Identificar un nuevo usuario en la aplicación, después hacer login, jugar a un juego en dificultad fácil de 5 preguntas, pedirle una pista al LLM entre medias y por último, guardar la puntuación del juego y mirar el historial. Hemos realizado dos pruebas, una para probar que la aplicación puede aguantar un nivel moderado de usuarios concurrentes y otra exhaustiva para poder ver los cuellos de botella de la aplicación y el margen de mejora.

12.4.1. 120 usuarios en 60 segundos

Podemos ver que en este test que casi todas las peticiones se realizan en un tiempo razonable, habiendo bastante pocas peticiones que tarden bastante, con esto podemos comprobar que la aplicación es estable con un número adecuado de usuarios que no debería darnos problema a la hora de entregar el proyecto al solicitante.

Carga 1
Carga 2

12.4.2. 1800 usuarios en 60 segundos

Aquí podemos ya ver bastantes errores graves, un cuarto de las peticiones fallan ante tal cantidad de usuarios.

El problema principal está en que el backend, se satura de usuarios y deja de funcionar. Haciendo que peticiones como AddUser o Login dejen de funcionar, pero otros servicios como la petición al LLM o la generación de preguntas con WikiData aguantan bastante bien. También cabe destacar el 100% de error a la hora de la entrega de la css de la aplicación, lo que genera que ningún usuario pueda ver la aplicación con normalidad.

El problema creemos que está en la potencia de nuestra máquina virtual, la cual tendríamos que cambiar por una más potente, con mejor memoria y rendimiento para que el backend pudiera aguantar más carga de usuarios.

Carga 3
Carga 4

12.5. Monitorización

También hemos realizado monitorización de la aplicación usando las herramientas de Prometheus y Grafana para observar el comportamiento en tiempo real de la aplicación y asegurarnos de que funcione correctamente, detectando problemas rápidamente y mejorando su rendimiento.

Monitorizar una aplicación nos sirve para:

  • Garantizar buena disponibilidad.

  • Mejorar el rendimiento.

  • Detectar errores de forma temprana.

  • Controlar el recorrido de los usuarios.

  • Generar alertas en caso de fallo.

Al final, el objetivo es anticiparse a los problemas y mejorar continuamente la calidad y eficiencia de la aplicación.

En las gráficas obtenidas, hemos analizado tres métricas clave:

  • Tasa de Solicitudes por Minuto (Rate): Esta métrica muestra la cantidad de solicitudes procesadas por minuto. Una tasa constante indica estabilidad en el sistema, mientras que picos o caídas pueden reflejar eventos específicos, como un aumento en los usuarios concurrentes o problemas en el backend.

  • Peticiones fallidas por Minuto (Errors): Representa la cantidad de solicitudes fallidas. Un aumento en los errores puede indicar saturación del backend, problemas de conectividad con otros servicios o errores en la lógica de negocio.

  • Duración de las Solicitudes (Duration): Muestra el tiempo promedio que tarda el sistema en procesar una solicitud. Un aumento en esta métrica puede ser un signo de saturación o problemas de rendimiento en el backend. Picos en la duración podrían coincidir con un aumento en la carga o errores en otros servicios.

Monitorización

En esta imagen podemos observar:

  • Una fluctuación en el número de peticiones . Esto tiene sentido ya que el número de peticiones no es un valor fijo, sino que depende del afluente de usuarios y sus acciones en la aplicación. En esta imagen, el número de peticiones ronda entre las 44 y 54 por minuto.

  • Un importante aumento en el número de peticiones fallidas . Esto es síntoma de errores en algún punto de la aplicación. Aunque en la imagen se observa que inicialmente hay un número importante de errores (±8), este número se reduce posteriormente hasta llegar a 2 errores, pero aumenta drásticamente hacia el final del gráfico.

  • Estabilidad en el tiempo de respuestas . Podemos ver que las tres gráficas mantienen una gran estabilidad con poca variación en el tiempo de respuesta. Como se observa en la gráfica, la mediana (B-series, línea verde) se mantiene prácticamente constante a lo largo del tiempo, lo que indica que la mayoría de las solicitudes son procesadas de forma consistente.

La monitorización es una gran herramienta para observar el rendimiento de la aplicación en tiempo real y poder identificar errores y corregirlos. En nuestro caso, debido a una situación ajena a nuestro control (falta de tiempo por un fallo en la red eléctrica de la región), no hemos podido realizar mejoras para paliar los problemas encontrados.

13. Glosario

Term Definition

Base de Datos

Sistema para almacenar, gestionar y recuperar datos de manera eficiente. Es un conjunto de datos conectados entre sí, que están estructurados de tal forma que se pueden consultar, actualizar y manipular fácilmente.

LLM

Modelo de Lenguaje Grande. Es un tipo de modelo de inteligencia artificial entrenado con una gran cantidad de datos textuales. Estos modelos están diseñados para entender, generar y manipular texto en lenguaje natural como si estuvieran conversando de manera coherente en respuesta a diferentes entradas.

Usabilidad

Facilidad con la que los usuarios pueden interactuar con una aplicación o sistema para lograr sus objetivos de manera eficiente, efectiva y satisfactoria.

GitHub

GitHub es una plataforma de desarrollo colaborativo para alojar proyectos utilizando el sistema de control de versiones Git.

Microservicios

Enfoque arquitectónico y organizativo para el desarrollo de software donde el software está compuesto por pequeños servicios independientes que se comunican a través de API bien definidas.

API

Conjunto de reglas o protocolos que permite a las aplicaciones informáticas comunicarse entre sí para intercambiar datos, características y funcionalidades.

JavaScript

Lenguaje de programación que los desarrolladores utilizan para hacer páginas web interactivas.

TypeScript

Lenguaje de programación que añade funcionalidad adicional a JavaScript.

Docker

Plataforma de contenedorización que nos permite desarrollar y ejecutar la aplicación en contenedores. Facilita la gestión de dependencias y despliegues, asegurando una buena consistencia entre entornos de desarrollo, prueba y producción.

Arc42

Plantilla para la documentación y diseño arquitectónico del software de nuestra aplicación. Nos proporciona una estructura estandarizada que ayuda a describir la arquitectura de la aplicación de manera clara y fácil de comprender.

PlantUML

Herramienta utilizada para crear diagramas a partir de texto, que permite generar diagramas de secuencia, de clases…​