scieee AI-readable full text Open interactive document viewer

Migración de aplicación Android con Google Play Games a API REST

García Diéguez, Juan

Abstract

Grado en Ingeniería Informática

Full text

Escuela de Ingeniería Informática TRABAJO FIN DE GRADO Grado en Ingeniería Informática Mención en Ingeniería de Software Migración de aplicación Android con Google Play Games a API REST Autor: Juan García Diéguez Escuela de Ingeniería Informática TRABAJO FIN DE GRADO Grado en Ingeniería Informática Mención en Ingeniería de Software Migración de aplicación Android con Google Play Games a API REST Autor: Juan García Diéguez Tutores: Cristian Tejedor García Mario Corrales Astorgano A mi familia. Gracias a vosotros pude comenzar esta etapa y cerrarla de la mejor manera posible. Agradecimientos Varias personas han ayudado a que este proyecto saliera adelante. En primer lugar, tengo que agradecer el esfuerzo y dedicación continua a mis tutores, Cristian Tejedor García y Mario Corrales Astorgano. Gracias a sus continuas ayudas y revisiones, tanto del código de la aplicación como del documento el proyecto ha podido seguir un camino adecuado hasta su finalización. También es necesario dar las gracias a mi familia y amigos, por el apoyo y ánimos de todos estos meses de trabajo. Resumen Debido al cierre de servicios multijugador de la API de Google Play Games en marzo de 2020, muchas aplicaciones que usaban este servicio quedaron inutilizables. Una de estas aplicaciones era Clash of Pronunciations (CoP), una aplicación Android multijugador para la práctica de la pronunciación en diferentes idiomas. Su principal idea es favorecer este aprendizaje de una manera divertida y entretenida, incluyendo desafíos en partidas de juego multijugador y escalando puestos en un ranking. Durante el curso 2019-2020 se implementó de cero una API en otro Trabajo Fin de Grado para reemplazar las funcionalidades de Google Play Games integradas en CoP. A lo largo de este proyecto se adapta el código de CoP para utilizar las llamadas de la nueva API y se actualiza el código de la aplicación Android a la última versión disponible para garantizar su correcto funcionamiento en los dispositivos actuales siguiendo la normativa de Android. Índice de figuras 1.1. Trabajos y actualizaciones de CoP a lo largo del tiempo . . . . . . . . . . . . . . . . . . . 2 1.2. Vistas de la interfaz de TipTopTalk! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.3. Interfaz de CoP para el login, registro y modificación del perfil . . . . . . . . . . . . . . . . 5 1.4. Interfaz de CoP de la pantalla de crear partida multijugador, partidas pendientes y entrenamiento ............................................. 5 1.5. Interfaz de CoP del menú principal, lista de logros y ranking . . . . . . . . . . . . . . . . . 6 1.6. Interfaz de CoP de los entrenamientos Exposición, Discriminación y Pronunciación . . . . 7 1.7. Interfaz de CoP de los dos modos de juego de las partidas multijugador. A la izquierda una ronda de Discriminación y a la derecha Pronunciación . . . . . . . . . . . . . . . . . 8 1.8. Esquema de una aplicación API REST. Fuente [12] . . . . . . . . . . . . . . . . . . . . . . 10 1.9. Vistas de la interfaz de Duolingo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.10.Arquitectura de Android. Fuente: Android developers [16] . . . . . . . . . . . . . . . . . . 13 1.11.LogodeJava........................................... 14 1.12.LogodeAndroidStudio ..................................... 15 1.13.LogodeNode.js ......................................... 15 1.14.LogodeMySQL ......................................... 16 1.15.LogodePostman......................................... 16 1.16.LogodeVisualStudioCode................................... 17 1.17.Ciclo de la metodología iterativa [29] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.1. Distribución del número de semanas de desarrollo en cada iteración. . . . . . . . . . . . 23 2.2. Distribución del número de horas de desarrollo en cada iteración . . . . . . . . . . . . . . 23 2.3. Diferentes configuraciones de máquinas virtuales ofrecidas por DigitalOcean. Fuente: DigitalOcean[49]......................................... 30 2.4. Comparación del número de semanas de desarrollo en cada iteración estimadas y reales 33 2.5. Comparación del número de horas de desarrollo en cada iteración estimadas y reales . . 33 3.1. Mock-up de las vistas de la aplicación de prueba . . . . . . . . . . . . . . . . . . . . . . . 38 3.2. Vistas de todas las llamadas y del login de la aplicación de pruebas . . . . . . . . . . . . 40 3.3. Vistas de la pantalla de resultado de las llamadas de login (izquierda) y opponents(derecha) 41 3.4. Flujo de las llamadas a la API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 3.5. Resultado del análisis del proyecto mediante las herramientas de inspección de código deAndroidStudio ........................................ 48 4.1.ModelodedominiodeCoP ................................... 58 V ÍNDICE DE FIGURAS 4.2. Diagrama de la historia de usuario del login (HU01) . . . . . . . . . . . . . . . . . . . . . 62 4.3. Diagrama de la historia de datos de usuario (HU02) . . . . . . . . . . . . . . . . . . . . . 63 4.4. Diagrama de la historia de ranking de usuarios (HU03) . . . . . . . . . . . . . . . . . . . . 64 4.5. Diagrama de la historia de registro de un usuario (HU04) . . . . . . . . . . . . . . . . . . 65 4.6. Diagrama de la historia de usuario de listar partidas (HU05) . . . . . . . . . . . . . . . . . 66 4.7. Diagrama de la historia de usuario de crear partidas (HU06) . . . . . . . . . . . . . . . . 67 4.8. Diagrama de la historia de usuario de información de partida (HU07) . . . . . . . . . . . . 68 4.9. Diagrama de la historia de usuario de ver logros (HU08) . . . . . . . . . . . . . . . . . . . 69 4.10.Diagrama de la historia de usuario de modificar el perfil (HU09) . . . . . . . . . . . . . . . 70 4.11.Diagrama de la llamada refreshToken de la API . . . . . . . . . . . . . . . . . . . . . . . . 71 4.12.Diagrama extra de la historia de usuario de crear partidas (HU06) . . . . . . . . . . . . . 72 4.13.Diagrama extra de la historia de usuario de crear partidas (HU6) y de la historia de usuario de ver la información de una partida (HU07) . . . . . . . . . . . . . . . . . . . . . . . . . . 73 4.14.Diagrama extra de la historia de usuario de crear partidas (HU06) y de la historia de usuario de ver la información de una partida (HU07) . . . . . . . . . . . . . . . . . . . . . 74 4.15.Diagrama extra de la historia de usuario de ver logros (HU08) . . . . . . . . . . . . . . . . 75 4.16.EstructuradeCoP ........................................ 76 4.17.ArquitecturadeCoP ....................................... 78 4.18.Arquitectura de una aplicación Android. Fuente: Android developers [58] . . . . . . . . . . 78 4.19.Estructura del Patrón Observador. Fuente: wikipedia [60] . . . . . . . . . . . . . . . . . . 79 4.20.Estructura del Patrón Singleton. Fuente: wikipedia [61] . . . . . . . . . . . . . . . . . . . . 80 4.21.Estructura del Patrón Fachada. Fuente: wikipedia [62] . . . . . . . . . . . . . . . . . . . . 80 4.22.Diagrama de paquetes de Clash of Pronunciations . . . . . . . . . . . . . . . . . . . . . . 81 4.23.Diagrama de clases del paquete activity.ui . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 4.24.Diagrama de clases del resto de paquetes . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 4.25.Diagrama relacional de la base de datos. Fuente [6] . . . . . . . . . . . . . . . . . . . . . 84 4.26.Diagramadedespliegue..................................... 85 5.1. Pirámide de pruebas en una aplicación Android. Fuente [63] . . . . . . . . . . . . . . . . 88 5.2. Ejemplo de test de las llamadas de la API . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 B.1.VistadellogindeCoP......................................102 B.2. Vista del registro de un usuario de CoP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 B.3. Vista de la lista de partidas de un usuario de CoP . . . . . . . . . . . . . . . . . . . . . . 104 B.4. Vista de la información de una partida de un usuario de CoP. De izquierda a derecha, partida en la que aún no se ha jugado el turno, partida en la que se ha jugado el turno y falta por jugar algún usuario y partida finalizada en la que el usuario ha resultado ganador 107 B.5. Vista de la lista de logros desbloqueados de un usuario de CoP . . . . . . . . . . . . . . 108 B.6. Vista de modificación de los datos del perfil de un usuario de CoP . . . . . . . . . . . . . 109 F.1. Login,registroymenú......................................131 F.2. Modificación del perfil, lista de logros e historial de partidas . . . . . . . . . . . . . . . . . 132 F.3. Ranking, escoger oponentes y vista final de una partida multijugador . . . . . . . . . . . . 133 F.4. Lista de partidas, información de una partida y lista de pares de palabras del entrenamiento134 VI ÍNDICE DE FIGURAS F.5. Vista final de un entrenamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 VII Índice de tablas 2.1. Riesgos durante el desarrollo del proyecto. ID: Identificador del riesgo. . . . . . . . . . . . 25 2.2. Plan de acción de los riesgos del proyecto. ID: Identificador del riesgo. . . . . . . . . . . . 26 2.3. Ordenador utilizado para llevar a cabo el desarrollo . . . . . . . . . . . . . . . . . . . . . . 28 2.4. Móvil utilizado en el desarrollo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.5. Máquina virtual usada para desplegar el servidor con la API durante el desarrollo . . . . 29 2.6. Costes de la realización de proyecto, sin incluir el salario de un desarrollador junior. . . . 31 2.7. Costes de la realización de proyecto, incluyendo el salario de un desarrollador junior. . . 31 3.1. Requisitos funcionales de la aplicación de pruebas . . . . . . . . . . . . . . . . . . . . . . 37 3.2. Requisitos funcionales de CoP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 3.3. Requisitos no funcionales de la aplicación CoP . . . . . . . . . . . . . . . . . . . . . . . . 46 3.4. Requisitos de información de la aplicación CoP . . . . . . . . . . . . . . . . . . . . . . . . 47 3.5. Informe de las clases que deben ser editadas . . . . . . . . . . . . . . . . . . . . . . . . . 49 4.1.HistoriadeusuarioHU01 .................................... 53 4.2.HistoriadeusuarioHU02 .................................... 54 4.3.HistoriadeusuarioHU03 .................................... 54 4.4.HistoriadeusuarioHU04 .................................... 54 4.5.HistoriadeusuarioHU05 .................................... 55 4.6.HistoriadeusuarioHU06 .................................... 55 4.7.HistoriadeusuarioHU07 .................................... 55 4.8.HistoriadeusuarioHU08 .................................... 56 4.9.HistoriadeusuarioHU09 .................................... 56 4.10.EntidadParticipant........................................ 59 4.11.EntidadChallenge ........................................ 59 4.12.EntidadWordData ........................................ 60 4.13.ResultTurn ............................................ 61 4.14.Evolución del código fuente de la aplicación cliente . . . . . . . . . . . . . . . . . . . . . . 86 4.15.Evolución del código fuente de la API del servidor . . . . . . . . . . . . . . . . . . . . . . 86 5.1. Plantilla utilizada para los test de usabilidad . . . . . . . . . . . . . . . . . . . . . . . . . . 90 C.1.Tarea1.Usuario1 ........................................111 C.2.Tarea1.Usuario1 ........................................112 C.3.Tarea1.Usuario1 ........................................112 IX ÍNDICE DE TABLAS C.4.Tarea1.Usuario1 ........................................112 C.5.Tarea1.Usuario1 ........................................113 C.6.Tarea1.Usuario1 ........................................113 C.7.Tarea1.Usuario1 ........................................113 C.8.Tarea1.Usuario2 ........................................114 C.9.Tarea1.Usuario2 ........................................114 C.10.Tarea1.Usuario2 ........................................114 C.11.Tarea1.Usuario2 ........................................115 C.12.Tarea1.Usuario2 ........................................115 C.13.Tarea1.Usuario2 ........................................115 C.14.Tarea1.Usuario2 ........................................116 C.15.Tarea2.Usuario1 ........................................116 C.16.Tarea2.Usuario1 ........................................117 C.17.Tarea2.Usuario2 ........................................117 C.18.Tarea2.Usuario2 ........................................118 E.1.PruebaP_I2_1..........................................125 E.2.PruebaP_I2_2..........................................125 E.3.PruebaP_I2_3..........................................125 E.4.PruebaP_I2_4..........................................126 E.5.PruebaP_I2_5..........................................126 E.6.PruebaP_I2_6..........................................126 E.7.PruebaP_I2_7..........................................126 E.8.PruebaP_I2_8..........................................127 E.9.PruebaP_I2_9..........................................127 E.10.PruebaP_I2_10 .........................................127 E.11.PruebaP_I2_11 .........................................127 E.12.PruebaP_I2_12 .........................................128 E.13.PruebaP_I2_13 .........................................128 E.14.PruebaP_I2_14 .........................................128 E.15.PruebaP_I2_15 .........................................128 E.16.PruebaP_I2_16 .........................................129 E.17.PruebaP_I2_17 .........................................129 E.18.PruebaP_I2_18 .........................................129 E.19.PruebaP_I2_19 .........................................129 X Capítulo 1 Introducción 1.1. Contexto En el año 2016, Cristian Tejedor García, tutor de este TFG, y alumno del Máster en Ingeniería Informática en ese momento, junto con sus tutores David Escudero Mancebo y César González Ferreras decidieron realizar un TFM [1] que fomentara el entrenamiento de la pronunciación extranjera mediante el uso de una nueva aplicación fundamentada en la gamificación (del término ingés gamification) de la pronunciación y discriminación de palabras en diferentes idiomas. Con esta idea en mente se creó TipTopTalk! [1]. Durante el curso 2016-2017, se decidió dar continuidad al proyecto añadiendo un componente muy importante para mejorar la gamificación del juego. En concreto, a mediados de 2017 se añadió la modalidad multijugador a la aplicación, lo que permitía crear partidas en las que se competía con otros usuarios reales con similares puntuaciones, lo que daba a la aplicación de aprendizaje de idiomas un punto más de diversión y entretenimiento. Para poder crear esa nueva modalidad de juego se optó por el uso de la API de Google Play Games [2], que permitía crear partidas, emparejamientos, mantenía la base de datos de usuarios y creaba rankings en función de las puntuaciones obtenidas. Además de estas labores, es importante destacar el cambio de nombre que sufrió la aplicación, pasando de TipTopTalk! al actual Clash of Pronunciations (CoP) [3]. A continuación, los tutores llevaron a cabo un trabajo de actualización y adaptación del código de CoP que permitió utilizar la aplicación en uno de los experimentos de investigación de la tesis de Cristian Tejedor [4], en el que participaron usuarios reales y se reportaron mejoras de pronunciación extranjera y de motivación de los jugadores [5]. El problema surgió casi tres años después (2020) cuando Google decidió dejar de mantener la API y la aplicación perdió la funcionalidad online que tanto había mejorado la gamificación. Como consecuencia de lo anterior, en el curso 2019-2020 se llevó a cabo otro TFG [6] en el que se implementó una API en Node.js con 14 llamadas o endpoints que permitiría volver a dar continuidad a la aplicación CoP sin depender de Google Play Games. Solo quedaba un paso más a realizar para que CoP volviera a estar disponible para su uso y era el de migrar todas las antiguas llamadas y código que usaba la API de Google Play Games a la nueva API creada y actualizar todo el código obsoleto que se 1 1.2. Motivación había quedado atrasado [7]. En ese punto es donde nos encontramos y en lo que se basa este TFG. En la Figura 1.1 podemos ver de forma resumida la evolución del código fuente desde su inicio hasta la actualidad, para poner en contexto al lector, tal y como se ha explicado anteriormente. Figura 1.1: Trabajos y actualizaciones de CoP a lo largo del tiempo 1.2. Motivación Los continuos cambios y avances en la tecnología, y concretamente en Android, hacen que sea totalmente necesario el mantenimiento y puesta al día de las aplicaciones ya creadas. En concreto, Google obliga a los desarrolladores a actualizar el código de compilación de las aplicaciones a la última versión. Esto conlleva cambios en la compatibilidad hacia atrás del código, obteniendo partes desfasadas (deprecated) y otras totalmente nuevas que deben adaptarse tanto a las versiones anteriores como a las nuevas [8]. Actualmente (principios de 2021) la versión de compilación de Android es la 11 (API LEVEL 30). La primera fue lanzada en el año 2008, por lo que cada año cambia. A esto hay que sumarle el hecho de que CoP no es funcional a fecha de empezar este TFG, inicio de 2021, debido a la eliminación de la API de Google Play Games, como ya hemos comentado en el apartado 1.1. La motivación es, por tanto, recuperar la aplicación CoP y hacerla funcional de nuevo mediante la migración de todas las llamadas [7] creadas en el Trabajo Fin de Grado de Andrés de la Maza Valles [6] junto a actualizar y realizar un mantenimiento de todos los problemas que puedan aparecer en la aplicación como consecuencia de su actualización a la última versión de Android. 2 Introducción 1.3. Estado de la cuestión 1.3.1. TipTopTalk! Como se ha comentado en la sección 1.1, esta fue la aplicación original y de la que parte CoP. Fue desarrollada por Cristian Tejedor García [1] a finales del curso 2015-2016 y cuyo fin principal era el de aportar diversión a la práctica de la pronunciación en diferentes idiomas, haciendo del proceso de aprendizaje un proceso entretenido y nada tedioso. Es una aplicación móvil para dispositivos Android que integra la posibilidad de mejorar la pronunciación en varios idiomas entre los que encontramos el español, inglés y chino. Presenta diferentes juegos de pronunciación, discriminación y exposición que otorgan puntos y logros y los usuarios ven representada esa puntuación en un ranking, favoreciendo la competitividad de los mismos y, por tanto, el entrenamiento en el idioma escogido. En todo momento se guarda información acerca de la actividad de los usuarios con la aplicación mediante ficheros de log. En las siguientes imágenes podemos ver la interfaz de usuario que presentaba TipTopTalk! (ver Figura 1.2). Figura 1.2: Vistas de la interfaz de TipTopTalk! Como puede verse en la Figura 1.2, la interfaz es casi idéntica a la que encontraremos en nuestra aplicación (CoP) ya que TipTopTalk! fue la semilla del proyecto de CoP y de la que partió nuestra aplicación unos años después. 1.3.2. Clash of Pronunciations CoP arrancó con el desarrollo del Trabajo Fin de Grado de Rafael Sillero Navajas [9]. La parte principal de su código fuente está basado en la antigua TipTopTalk! y durante ese proyecto se añade parte de la funcionalidad que tiene ahora. Junto con los desarrollos llevados a cabo durante ese proyecto 3 1.3. Estado de la cuestión Figura 1.8: Esquema de una aplicación API REST. Fuente [12] En cuanto a las API’s, aunque esto se puede extrapolar a cualquier otra petición a través de internet, es necesario que se realicen en hilos secundarios de la aplicación, ya que ejecutarlos en el hilo principal, hilo que maneja la interfaz de usuario, resultaría en problemas de bloqueos de la interfaz. 1.3.5. Trabajo Fin de Grado de Andrés de la Maza Valles Es el proyecto que finalmente implementó 14 nuevas llamadas API en el lado del servidor [6], que son las que será necesario migrar en el lado del cliente durante este proyecto para que la aplicación vuelva a ser funcional completamente. Las llamadas creadas son login, y registro de usuarios, así como modificación de sus datos, refrescar token, que crea un nuevo token para poder identificar al usuario en las llamadas, obtener los datos del usuario, obtener el ranking de los jugadores, listar las partidas pendientes, ver información de las partidas, obtener oponentes para una partida, crear partida, iniciar y finalizar la partida, añadir logros y ver lista de logros. Cabe destacar que para la identificación de usuarios se utilizó JWT. Json Web Token (JWT) [13] es un estándar abierto que define una forma para transmitir información segura entre dos partes mediante un objeto JSON. Esta información es segura y confiable ya que está firmada digitalmente y esto se puede hacer de dos formas posibles que son la firma utilizando un secreto (esta es la firma que se utiliza en este proyecto) o utilizando un par de claves públicas o privadas. En este proyecto se utiliza como manera de mantener la sesión de un usuario en el sistema pasando el número de identificación de este entre las llamadas del cliente y el servidor. 1.3.6. Alternativas a Google Play Games Como alternativa al cierre de Google Play Games, y solo en lo referente a la gestión de usuarios y datos, disponemos de Firebase. Firebase es un conjunto de herramientas que proporcionan una serie de servicios como la gestión de usuarios y gestión de datos como base de datos NoSQL, autenticación de usuarios y almacenamiento de ficheros, junto con una enorme cantidad de herramientas más. Los datos se almacenan en formato JSON y se sincronizan en tiempo real con cada cliente conecta10 Introducción do. Cuando se compila una aplicación multiplataforma todos sus clientes comparten una instancia de Firebase y reciben actualizaciones automáticamente con los datos más recientes [14]. Por esta razón, puede ser usado por Android, web o iOS. En vez de utilizar Firebase, se optó por crear una API propia para poder configurar el servidor según las necesidades específicas de este aplicación. En palabras de Andrés de la Maza Valles en su TFG [6] ”configurarlo sin depender de programas externos y que además se adecue a los requisitos del proyecto. Esto aporta ventajas como una libre configuración de los requisitos y la gestión propia de los datos”. Además de esto, también aporta la posibilidad de cambios en el futuro de la funcionalidad, así como el evitar el pago por los servicios. 1.3.7. Duolingo La aplicación de aprendizaje de idiomas más descargada de la Play Store, con más de 100 millones de descargas [15]. Utiliza la gamificación como elemento principal para favorecer el aprendizaje de una manera atractiva y divertida para los usuarios. Para ello permite avanzar en el juego al completar unidades restando vidas con las respuestas incorrectas, otorgando puntos con las correctas y se subiendo de nivel como en un juego. Además, es una aplicación gratuita que contiene la posibilidad de pagar por lecciones o eliminación de anuncios mediante el uso de una cuenta premium. En la Figura 1.9 podemos observar la interfaz de la aplicación. A diferencia de Clash of Pronunciations, Duolingo se basa más en el aprendizaje de un idioma de manera general y no exclusivamente en la pronunciación de las palabras como sí hace CoP. Figura 1.9: Vistas de la interfaz de Duolingo 11 1.3. Estado de la cuestión 1.3.8. Entorno y herramientas tecnológicas En este apartado se exponen las tecnologías utilizadas para desarrollar este proyecto así como las principales características de cada una de ellas. De manera resumida para este TFG se ha utilizado un entorno para desarrollo Android bajo el lenguaje de programación Java (Android Studio) para la parte cliente. Además, se han hecho llamadas a la API RESTful (ver sección 1.3.4) desarrollada en el TFG de Andrés de la Maza Valles, implementada en Node y Mysql en los que se han debido hacer pequeñas modificaciones en el código cuando se encontraron bugs o se pretendía aumentar la funcionalidad. Para probar estos cambios se ha usado Postman. Por último, para el despliegue del servidor y el almacenamiento de datos se han utilizado máquinas virtuales a las que se ha accedido mediante Visual Studio Code y su extensión Remote-SSH para la visualización y acceso de ficheros. Android 11 Según la propia Google ”Android es una pila de software de código abierto basado en Linux creada para una variedad amplia de dispositivos y factores de forma” [16]. Fue diseñado para dispositivos móviles con pantalla táctil. Proporciona su propio entorno sobre el que construir aplicaciones. En la Figura 1.10 podemos ver la arquitectura de Android. En ella podemos apreciar como en la base de la figura encontramos el kernel de Linux que otorga funcionalidades como la generación de subprocesos y la administración de memoria de bajo nivel. Por encima del kernel encontramos la capa de abstracción de hardware (HAL). Esta brinda interfaces estándares que exponen las capacidades de hardware del dispositivo al marco de trabajo de la API de Java de nivel más alto. Si seguimos subiendo en la figura encontramos el Android Runtime y las bibliotecas C/C++ nativas. Finalmente encontramos el marco de trabajo de la API de Java, que es todo el conjunto de funciones de Android que están disponibles y por encima de este encontramos las aplicaciones del sistema, que son aquellas que vienen instaladas de fábrica. En este mismo nivel se sitúan las aplicaciones que podemos descargar de la Play Store como CoP. Inicialmente fue desarrollado por Android Inc., pero en 2005 fue adquirido por Google. El código fuente principal de Android se conoce como Android Open Source Project (AOSP). Android es el sistema operativo móvil más utilizado del mundo, con una cuota de mercado superior al 86 % el año 2020 [17]. 12 Figura 1.10: Arquitectura de Android. Fuente: Android developers [16] 1.3. Estado de la cuestión Java 8 Java (ver Figura 1.11) es un lenguaje de programación cuya principal característica es que es orientado a objetos. Es el lenguaje usado para el desarrollo de las aplicaciones Android desde el comienzo del sistema operativo, aunque en la actualidad y desde hace varios años, Android ya no tiene preferencia por este lenguaje, si no por Kotlin [18], un lenguaje más moderno y sobre el que se construyen ya las principales aplicaciones de Android en todo el mundo [19]. A pesar de esto, Java sigue estando presente en gran cantidad de aplicaciones Android ya que en la mayor cantidad de casos no es viable la migración del código de un lenguaje a otro. Aunque se pueden usar ambos lenguajes de manera conjunta en un mismo proyecto [20], en CoP se decidió mantener Java para no complicar más los trabajos de la migración y porque además, Java es el lenguaje que más hemos usado a lo largo del Grado de Ingeniería Informática, por lo que evitamos la curva inicial de aprendizaje tanto para este proyecto como para futuras revisiones. Figura 1.11: Logo de Java Android Studio Android Studio (ver Figura 1.12) [21] es el IDE oficial de Android que se creó exclusivamente a fin de acelerar el desarrollo y compilación de las aplicaciones Android. Por tanto, Android Studio es el entorno de desarrollo integrado (IDE) oficial para el desarrollo de aplicaciones para Android y está basado en IntelliJ IDEA [22]. Además de tener un potente editor de código y las herramientas para desarrolladores de IntelliJ, Android Studio ofrece otras funcionalidades añadidas como un sistema de compilación flexible basado en Gradle, un emulador de dispositivos Android, herramientas para identificar problemas de rendimiento, usabilidad y compatibilidad con versiones antiguas, entre otras muchas. 14 Figura 1.12: Logo de Android Studio Google TTS y STT Google Text-to-speech (TTS) [23] es la herramienta utilizada para la conversión de texto a voz en la aplicación. El servicio utiliza un lenguaje muy natural gracias a la inteligencia artificial de Google. Además, este servicio está disponible en más de 40 idiomas. En CoP esta herramienta es utilizada en las modalidades multijugador, discriminación y pronunciación para que el dispositivo lea las palabras en voz alta cuando pulsamos un botón de ayuda o al iniciar cada ronda de una partida. Google Speech-to-Text (STT o ASR en inglés, Automatic Speech recognition)[24] es el caso contrario a TTS. Es una API de reconocimiento de voz que recibe un json con un formato dado y un audio. Mediante la inteligencia artificial de Google se interpreta este audio y se genera una respuesta que contiene una lista de palabras y la probabilidad de que cada una de ellas haya sido la palabra pronunciada. Además, en la versión de pago Google permite almacenar los audios y gracias a ello, podemos guardarlos en nuestro propio servidor de ECA-SIMM para su análisis posterior. Node Node.js (ver Figura 1.13) es un entorno de ejecución para JavaScript orientado a eventos asíncronos y está diseñado para crear aplicaciones de red escalables [25]. Está construido con el motor de JavaScript V8 de Chrome. En él casi ninguna función realiza I/O directamente, por lo que el proceso nunca se bloquea y por esa razón es muy propicio desarrollar sistemas escalables. HTTP es un elemento destacado en Node.js, diseñado teniendo en cuenta la transmisión de operaciones con streaming y baja latencia. Esto hace que Node.js sea muy adecuado para la base de una bilbioteca o un framework web. Figura 1.13: Logo de Node.js 1.3. Estado de la cuestión MySQL Como base de datos utilizamos MySQL (ver Figura 1.14) [26]. MySQL es un base de datos de tipo relacional. Una base de datos relacional almacena datos en tablas separadas. Las estructuras de la base de datos están organizadas en archivos físicos optimizados para aumentar su velocidad. El modelo lógico, con objetos como bases de datos, tablas, vistas, filas y columnas, ofrece un entorno de programación flexible. A diferencia de las bases de datos no relacionales, estas se centran en la velocidad y el rendimiento de las consultas, lo que favorece que el servidor responda más rápido las peticiones de las aplicaciones cliente. Figura 1.14: Logo de MySQL Postman Postman [27] (ver Figura 1.15) es una herramienta muy útil para el desarrollo de API’s, ya que permite ejecutar las llamadas a un servidor editando la petición HTTP al completo y recuperando los datos devuelve el servidor. Postman actúa como cliente creando diferentes llamadas API que se pueden almacenar para volver a usar y mostrando el resultado de estas consultas. Durante este proyecto se ha usado para realizar comprobaciones rápidas del servidor y almacenar consultas que han generado error para repetirlas hasta encontrar dicho problema y solucionarlo. Figura 1.15: Logo de Postman 16 Introducción Visual Studio Code Como herramienta para poder editar el código de la API hemos usado Visual Studio Code [28] (ver Figura 1.16). Además, gracias al uso del plugin Remote-SSH podemos crear una sesión SSH para editar los archivos del servidor alojados en la máquina virtual. Figura 1.16: Logo de Visual Studio Code 1.4. Objetivos El objetivo principal del proyecto es actualizar su código fuente para que vuelva a estar activo. Para ello se deberá migrar todas las antiguas llamadas a la API de Google Play Games a la nueva API REST creada en el Trabajo Fin de Grado de Andrés de la Maza Valles [6] volviendo a dar vida a la aplicación, que a día de hoy no es funcional. Además, habrá que actualizar el código fuente de Android para que sea compatible con la última versión hasta la fecha (junio de 2021). De manera más particular, los objetivos serán los siguientes: Migrar todas las llamadas a la nueva API REST. Actualizar la versión de Android desde la API 25 a la API 30. Corregir todos los errores o problemas que surjan durante la migración y la actualización de la versión. 1.5. Metodología Dadas las características del proyecto, del hecho de ser un solo desarrollador y partiendo de la base de que los requisitos están fijados desde el inicio y no van a recibir apenas variaciones se ha optado por una metodología iterativa e incremental. Esta permite un cierto grado de modificación de los requisitos iniciales pero no se basa en la idea de que estos son totalmente cambiables como es en las metodologías ágiles. Las metodologías ágiles se realizan en entornos de grupos de trabajo con varios trabajadores y por esta razón no parece relevante para un solo trabajador. Gracias a la metodología iterativa, en cada iteración se podrá presentar al cliente cierta funcionalidad implementada y no esperar hasta el final para presentar todo como es lo propio de las metodologías en cascada. Se puede comprobar, por tanto, que el proyecto sigue el camino indicado y realizar pequeñas correcciones de lo presentado en cada reunión con los clientes antes de continuar con las nuevas 17 1.6. Estructura de la memoria funcionalidades. Además, el hecho de entregar el proyecto por partes permite eliminar el posible goldplating (añadir funcionalidad que no ha sido requerida) y entregar solo lo planteado en los requisitos. En la siguiente figura (ver Figura 1.17) podemos ver los pasos que requiere una metodología iterativa. Además, en el Capítulo 3 se definirán las diferentes iteraciones que se van a llevar a cabo en el proyecto. Figura 1.17: Ciclo de la metodología iterativa [29] 1.6. Estructura de la memoria La presente memoria está dividida en los siguientes capítulos: Introducción: se presenta el proyecto de una forma general, tratando su contexto, motivación, estado actual de la aplicación, objetivos y metodología a seguir. Planificación: análisis, descripción y estimación del trabajo que se realizará, en cuántas iteraciones y bajo qué costes y riesgos. Descripción de la iteraciones: describe el trabajo real realizado en cada iteración y hasta finalizar el proyecto. Estado de la cuestión: describe todo el análisis y diseño de la aplicación, agrupando todos los diagramas y figuras realizados. Pruebas: agrupa el conjunto de pruebas realizadas en el proyecto. Conclusiones: conocimientos y conclusiones obtenidas del proyecto realizado así como una lista de trabajos futuros que podrían realizarse para mejorar las funcionalidades que ofrece la aplicación. 18 Introducción Apéndices: distintos documentos adicionales como los acrónimos, un manual de despliegue completo sobre el despliegue del servidor y su base de datos, el despliegue CoP en el cliente, el manual de uso de CoP, el detalle de la funcionalidad implementada, los datos recabados en el test de usabilidad y el contenido entregado en el TFG. Bibliografía: conjunto de referencias utilizadas a la hora de desarrollar el proyecto. 19 2.1. Planificación inicial ID Riesgo Exposición (tanto por uno) Plan de reducción del riesgo Plan de mitigación del riesgo 1 Suspender la asignatura Sistemas Empotrados en la convocatoria ordinaria 0.21 Se llevará al día la asignatura para evitar suspenderla Se pospondrá la entrega del proyecto para la convocatoria extraordinaria 2 Suspender la asignatura Sistemas Empotrados en la convocatoria extraordinaria 0.12 Se dedicará la mayor cantidad de horas posibles desde la convocatoria ordinaria a la extraordinaria para aprobar la asignatura Se pospondrá la entrega del proyecto a mitad del primer cuatrimestre del siguiente curso 3 Enfermedad 0.25 - Se usarán horas de los fines de semana para recuperar el retraso 4Contagio por Covid-19 0.35 Cumplir las medidas de prevención anunciadas por los organismos públicos de sanidad Se usarán horas de los fines de semana para recuperar el retraso 5 Falta de experiencia en el desarrollo Android 5Haber cursado la asignatura de Sistemas Móviles Usar la documentación oficial de Android ante cualquier duda y usar horas de los fines de semana en caso de retrasos 6 Problemas en el despliegue de la aplicación de la API 1.2 Seguir los manuales de despliegue del TFG anterior y leer documentación sobre aplicaciones Node.js junto con Nginx y PM2 Se usarán horas de los fines de semana para recuperar el retraso 7Planificación incorrecta 12 Ser conservador a la hora de crear los plazos de entrega Se usarán horas de los fines de semana y de los días posteriores a la fecha de finalización con el fin de mantener la entrega final del proyecto antes del final de la primera convocatoria 8 Pérdida de datos a lo largo del desarrollo 0.4 Usar autoguardado junto con el uso de la nube para almacenar copias del documento, así como uso de git y gitlab para mantener copias del código tanto en local como en remoto Usar copias del último día de trabajo 9 El ordenador de trabajo sufre algún problema 0.04 Mantener el ordenador actualizado y guardarlo siempre en lugar adecuado. Pedir un ordenador prestado y recuperar el trabajo del día anterior almacenado en la nube Tabla 2.2: Plan de acción de los riesgos del proyecto. ID: Identificador del riesgo. 26 Planificación 2.2. Entorno tecnológico 2.2.1. Herramientas utilizadas A continuación, se describen las herramientas utilizadas a lo largo del desarrollo del proyecto junto con las funciones que han aportado cada una de ellas. Android SDK API 30 [31]: Suite proporcionada por Google para el desarrollo de aplicaciones para la plataforma móvil Android. Android Studio 4.1.1 [32]: Entorno de desarrollo Android para lenguaje Java o Kotlin. Astah [33]: Creación de diagramas UML. Balsamiq Wireframes [30]: Creación de mock-ups para las vistas de la aplicación de pruebas. Excel 365 [34]: Herramienta software con la que se han creado tablas y figuras para este proyecto. Git 2.25.1 [35]: Control de versiones del código del proyecto. Gitlab (Versión Web) [36]: Repositorio remoto para almacenar todo el código fuente y datos del proyecto. Google Drive (Versión Web) [37]: Almacenamiento de ficheros en la nube relacionados con la memoria. Java 8 [38]: Lenguaje utilizado para el desarrollo en Android. MySQL 8.0.23-0ubuntu0.20.04.1 [26]: Gestor de bases de datos relacionales y usado en el servidor para soportar nuestra base de datos. Nginx 1.18.0 (Ubuntu) [39]: Usado como proxy inverso que permite recoger las peticiones http procedentes del puerto 80 (en nuestra máquina virtual este puerto es el 65232) y mandárselas al servidor Node que tiene la API y que escucha en un puerto local 3001 (no accesible desde fuera). Node 10.19.0 [40]: Entorno de ejecución en tiempo real de JavaScript usado para construir la API. npm 6.14.4 [41]: Es el Node Package Manager y ayuda en la gestión de las dependencias y módulos de la API con Node así como en su ejecución. Overleaf (versión web)[42]: Sitio web usado para escribir documentos en LaTeX. phpMyAdmin [43]: Herramienta gratuita de software utilizada para poder acceder a la base de datos de manera gráfica a través del navegador. PM2 4.5.1 [44]: Usado para mantener el servidor corriendo continuamente. Si el servidor falla y se cierra PM2 volverá a iniciarle. 27 2.2. Entorno tecnológico Postman 8.0.2 [27]: Entorno para el desarrollo de APIs que permite realizar pruebas contra el servidor y almacenar todas las pruebas para volver a usarlas. Safari 14.0.3 [45]: Navegador usado para acceder a overleaf y escribir el documento así como buscar información. Telegram 7.4 [46]: Comunicación con los tutores del proyecto. Visual Studio Code versión: 1.53.0 [47]: Edición de ficheros de texto. 2.2.2. Entorno de desarrollo Respecto al entorno utilizado, podemos ver en las siguientes Tablas 2.3, 2.4 y 2.5 los datos hardware y software asociados a cada dispositivo utilizado para poder llevar a cabo el proyecto. Ordenador MacBook Pro 15 2019 Hardware Procesador Intel Core i7-9850H Memoria 16 GB 2400 MHz DDR4 Disco duro 512 GB Tarjeta gráfica Radeon Pro 555X Software Sistema operativo macOS 11.2 Arquitectura del sistema 64 bits Tabla 2.3: Ordenador utilizado para llevar a cabo el desarrollo Móvil OnePlus 8 Hardware Procesador Qualcomm Snapdragon 865 Memoria 8GB Disco duro 128 GB Tarjeta gráfica Adreno 650 Software Sistema operativo Android 11 Arquitectura del sistema 64 bits Tabla 2.4: Móvil utilizado en el desarrollo 28 Máquina virtual Hardware Procesador 4 cores Memoria 4GB Disco duro 20 GB Software Sistema operativo Ubuntu 20.04.1 LTS Arquitectura del sistema 64 bits Tabla 2.5: Máquina virtual usada para desplegar el servidor con la API durante el desarrollo 2.3. Estimación de costes En el presente apartado se detalla la estimación inicial de costes del proyecto, tanto humanos como técnicos o de servicios. Todos los importes del hardware usado se contabilizan con IVA, así como el salario del desarrollador es bruto. Salario del trabajador En el caso de este proyecto, el trabajador, Juan García Diéguez, no ha estado contratado por la Universidad de Valladolid por lo que el salario se considerará 0, pero para poder realizar una estimación realista de los costes que este proyecto supondrían, se va llevar a cabo un segundo presupuesto incluyendo el coste medio del salario de un desarrollador junior. Teniendo en cuenta un salario medio de 20.000C brutos anuales [48], o lo que es lo mismo, un salario de 10,26C/h. Espacio de trabajo El proyecto se ha llevado a cabo en el lugar de residencia del desarrollador. A pesar de esto, en la universidad están disponibles diferentes laboratorios o lugares de trabajo en los que podría realizarse, por lo que, al desconocer el coste real del espacio, se va a recurrir a estimarlo comparándolo con las opciones que hay en Valladolid sobre el co-working y el alquiler de un puesto similar. Material físico El material utilizado para la elaboración del proyecto tiene asociado el coste cuando este fue comprado divido por el número de años que se estima tendrá su vida útil. Entre dichas herramientas encontramos obviamente el ordenador de trabajo junto con el móvil usado para probar la aplicación. El ordenador supone un coste para el proyecto de 162,5C teniendo en cuenta que su precio fue de 2600C y que se prevé un tiempo de vida de 8 años pero el trabajo se estima terminado en aproximadamente 56 meses. Respecto al móvil, este costó 530C y prevé una vida de 4 años, por lo que es coste para este trabajo es de 66,25C teniendo en cuenta de nuevo, que el trabajo completo durará aproximadamente 6 meses. Servidor Cloud La máquina virtual puesta a disposición del alumno para llevar a cabo el despliegue del servidor 2.3. Estimación de costes del proyecto supone un coste que es muy difícil contabilizar, por lo que se optará por contabilizar el coste asociado al alquiler de un servidor cloud en el que soportarla. El proveedor elegido escogido es DigitalOcean y dentro de todos sus planes se ha escogido el plan Basic Droplets [49], que son máquinas virtuales con capacidad de mantener el servidor igual que lo hace la máquina virtual prestada por la universidad. En Figura 2.3 se pueden ver las diferentes configuraciones ofrecidas, siendo escogida la tercera, por ser la que tiene especificaciones más similares a la máquina virtual usada. El coste es de 15$ al mes, lo que suponen 90$ durante todo el proyecto, que transformados a euros con el cambio actual, 1C = 1,21$ a 5-2-2021, son 74,18C. Figura 2.3: Diferentes configuraciones de máquinas virtuales ofrecidas por DigitalOcean. Fuente: DigitalOcean [49] Servicios Los servicios básicos utilizados para poder desarrollar el proyecto son luz e internet. Internet supone 50C/mes para la tarifa estándar de O2 [50], lo que serían 300C durante toda la duración del proyecto. En cuanto a la luz, según tarifaluzhora.es [51], un uso de ordenador de 6h al día y 180h/mes supone 1,8kWh. Como nuestro uso será aproximadamente de 60h mensuales a lo largo de 6 meses estimamos un gasto de 3kWh, que con un precio de 0.1270C/kWh por parte de endesa [51] supone unos coste final para todo el proyecto de 0,381C. Cómputo total Como se puede apreciar de la tabla 2.6, el precio total de la realización del proyecto asciende a 1023,31C, lo cual es muy inferior en los visto en la tabla 2.7, que sería el coste real de realizar este proyecto bajo la contratación de un desarrollador junior. 30 Material Precio Unitario Unidades Subtotal Espacio de trabajo 200C/mes 3 meses 600C Ordenador 162,5C 1 162,5C OnePlus 8 66,25C 1 66,25C Servidor cloud 12,36C/mes 6 74,18C Internet 50C/mes 6 300C Luz gastada por el ordenador 0.1270C/kWh 3 0,381C Total - - 1203,31C Tabla 2.6: Costes de la realización de proyecto, sin incluir el salario de un desarrollador junior. Material Precio Unitario Unidades Subtotal Salario de desarrollador 10,26C/hora 330 horas 3.385,8C Espacio de trabajo 200C/mes 3 meses 600C Ordenador 162,5C 1 162,5C OnePlus 8 66,25C 1 66,25C Servidor cloud 12,36C/mes 6 74,18C Internet 50C/mes 6 300C Luz gastada por el ordenador 0.1270C/kWh 3 0,381C Total - - 4589,11C Tabla 2.7: Costes de la realización de proyecto, incluyendo el salario de un desarrollador junior. 2.4. Planificación final Esta última sección de la planificación se realiza una vez terminado el proyecto al completo. En ella vamos a comparar los datos de la planificación inicial con los datos finales obtenidos, tanto en horas de trabajo, como en reuniones o seguimiento de las iteraciones. Lo primero que debemos comentar es que la estimación de horas de trabajo quedó corta, ya que inicialmente se estimaron 330h y al finalizar el proyecto, las horas totales han sido 396h. Un parte importante de este exceso de horas viene dado por los problemas encontrados en la API desarrollada en el TFG de Andrés de la Maza [6]. Este riesgo no se tuvo en cuenta a la hora de estimar los riesgos y por tanto, tampoco tenía asociado un plan de mitigación. El hecho de que no se considerara como riesgo se debe a que el TFG de Andrés había sido probado. Por suerte, en la planificación inicial sí se tuvo en cuenta el riesgo de una mala planificación (ver en la Tabla 2.1 el riesgo ID-7), que tenía como plan de mitigación usar horas extra tanto de los fines de semana (ver Tabla 2.2 riesgo ID-7), como de los días posteriores al 11 de junio. Además de los retrasos provocados por este problema, ha habido otra serie de discrepancias entre lo establecido inicialmente y lo realizado al final. El cambio más importante es la unión de la iteración 3 y 4 (ver sección 2.1.1), ya que durante el desarrollo se llegó a la conclusión de que sería más sencillo realizar ambos trabajos a la vez. De esta manera la aplicación fue evolucionando a medida que se añadían llamadas y para cada nueva llamada, se corregían y actualizaban los problemas que surgieran en ese momento. 2.4. Planificación final Finalmente, el número de iteraciones llevadas a cabo fue de 4. La primera y segunda iteración planificadas fueron iguales a las llevadas a cabo y en tiempo prácticamente iguales a los establecido. En la primera de ellas se realizó el despliegue de la API en una máquina virtual y en la segunda se creó la aplicación de pruebas. Como ya hemos dicho, la iteración 3 y 4 se fusionaron en una sola en la que se completó la migración y actualización de la aplicación al completo. Durante esta iteración también se corrigieron los problemas encontrados en el servidor. Aunque el tiempo trabajado ha sido de 190h y el estimado era de 180h (60h + 120h) con los problemas encontrados en el servidor no se pudo avanzar tanto como se deseaba el documento del proyecto. Esto fue lo que generó los problemas de tiempo ya comentados. Por último, la quinta iteración estimada inicialmente fue nombrada como la cuarta iteración. En su transcurso, cada semana se llevaron a cabo reuniones con los tutores y se presentaron diferentes avances. En la primera semana de ellas se avanzó el documento únicamente mientras los tutores corregían la aplicación. En la siguiente (semana 2 de la cuarta iteración) se corrigieron todos los problemas encontrados en la aplicación por parte de los tutores. En la tercera semana se acabó de escribir el documento y se corrigieron a la par los problemas que los tutores encontraron. Por último, durante la última semana se corrigieron los últimos errores o cambios requeridos por los tutores en una segunda revisión tanto en la aplicación como en el documento. Durante todas estas iteraciones se han llevado a cabo un total de 13 reuniones con los tutores. Siempre se llevó a cabo una reunión al inicio de cada iteración, además, en la iteración 2 se efectuaron 2 reuniones con una separación de 3 semanas. La tercera iteración fue la que más reuniones tuvo, ya que en ellas se fueron presentando los diferentes avances y problemas encontrados en la aplicación. En esta tercera iteración el número de reuniones total fue de 6. Por último, a lo largo de la cuarta y última iteración las reuniones se sucedieron semanalmente dando un total de 4 reuniones más. A la par que las reuniones, se ha usado Telegram de manera más ostensible para plantear dudas o dar correcciones por parte de los tutores. Estudiando el desarrollo del proyecto se puede deducir que las horas de trabajo totales superaron a las horas estimadas aunque no en todas la iteraciones, como ya se ha dicho. En las siguientes figuras (ver Figura 2.4 y Figura 2.5) podemos ver la distribución de total de horas en las iteraciones y la distribución de horas acumuladas. Como se ve las semanas de desarrollo tuvieron que alargarse en 2 y las horas superaron por más de un 20% las horas estimadas inicialmente. En total las horas trabajas fueron 396h, esto es 66h más de las 330h planteadas inicialmente. 32 Figura 2.4: Comparación del número de semanas de desarrollo en cada iteración estimadas y reales Figura 2.5: Comparación del número de horas de desarrollo en cada iteración estimadas y reales 2.4. Planificación final 34 Capítulo 3 Descripción de las iteraciones En este capítulo se expone todo el trabajo realizado durante las diferentes iteraciones a lo largo del desarrollo del proyecto. Entre otras cosas, se van a comentar los requisitos del proyecto, las actualizaciones que ha sufrido la aplicación, el diseño de todas las nuevas pantallas necesarias en la aplicación y los diferentes problemas encontrados y solucionados a lo largo del desarrollo, principalmente en el servidor. 3.1. Iteración 1 Para poder comenzar el proyecto de manera adecuada, el alumno antes de empezar revisó la tecnología a usar, siendo esta principalmente Android 11 (API 30) programado con Java y llamadas a la API. Gracias a cursar las asignaturas Desarrollo Basado en Componentes y Servicios y Sistemas Móviles estos dos aspectos han quedado bien preparados. En el comienzo oficial del proyecto, el día 25 de enero de 2021, se llevó a cabo la reunión de inicio del trabajo. En ella se expusieron los requisitos que los clientes, en este caso los tutores, querían llevar a cabo, cuáles eran los primeros pasos que dar y cómo se iría desarrollando la tarea a lo largo tiempo. A continuación, se expondrán los trabajos realizados durante la iteración, así como las tecnologías utilizadas. 3.1.1. Trabajo realizado En primer lugar, se diseñó y escribió la planificación del presente proyecto (ver Sección 2.1.1 del Capítulo 2). Con toda la planificación desarrollada, se comenzó con el despliegue de la API creada en el TFG de Andrés de la Maza Valles [6]. Durante la mayor parte del tiempo de la iteración se estuvo llevando a cabo el despliegue del servidor en la máquina virtual cedida por la universidad. Para ello, fue necesaria el uso de una serie de herramientas software cuya instalación está descrita en el Apéndice D (Manual desarrollado durante 35 3.2. Iteración 2 3.2.4. Flujo de las llamadas Para poder ejecutar las llamadas API en la aplicación de pruebas y posteriormente en CoP, y tener un resultado correcto es necesario seguir un orden adecuado. Se ha realizado un diagrama de flujo de las llamadas que será usado tanto para la aplicación de pruebas como para la aplicación final de CoP y que podemos ver en la Figura 3.4. Figura 3.4: Flujo de las llamadas a la API Como puede verse, lo primero que se debe hacer para realizar alguna prueba es o bien registrar un nuevo usuario, o realizar login con algún usuario ya creado o directamente usar refreshToken en caso de que ya se haya iniciado la sesión anteriormente. A continuación, se pueden lanzar varias llamadas distintas sin importar el orden, como son userData, modify, ranking, addAchievement, showAchievements y opponents. En el caso de querer crear una partida nueva, es necesario antes buscar oponentes con opponents, y luego crear la partida con createChallenge. Una vez creada se puede tanto ver la información con infoChallege, como jugar con startMatch y finalizar con finishMatch. Además de poder ejecutar todas las llamadas de manera aislada, se ha creado también una opción para jugar una partida completa, de manera que se pueda ver el resultado final de la misma y comprobar si el resultado ha sido el esperado o no. Para ello la prueba pide un login inicial del usuario que creará la partida, y una vez iniciada la sesión y, por tanto, generado el token, la aplicación busca oponentes, crea un partida y juega y finaliza el turno del usuario creador. Lo siguiente que realiza es el bucle en el que recorre la lista de oponentes obtenidos y cada uno de ellos lleva a cabo su login, su juego y su finalización del turno. Al terminar el último jugador, se muestra el resultado obtenido, que debería ser ”Partida finalizada, actualización de la puntuación total” Volviendo a la lista de llamadas y pinchando el ranking se podrán ver como las puntuaciones de los jugadores de la partida han cambiado. En caso de 42 Descripción de las iteraciones aparecer algún error en el proceso, este se muestra y la prueba termina. 3.2.5. Problemas encontrados A parte de los problemas comentados en la sección anterior, el mayor problema encontrado surgió al intentar realizar todas las llamadas a la API y jugar para simular una partida completa con varios jugadores. No todas las llamadas se habían probado hasta ahora y ha sido en esta iteración donde se han encontrado ciertos errores. Tras llevar a cabo una serie de pruebas comprobamos que la API no escribía las palabras en la base de datos. Como la llamada createChallenge no funcionaba correctamente, provocaba fallos en las siguientes llamadas. Fue necesaria la edición de dos queries que realizan los insert a la base de datos. Editando los campos de fechas la inserción de las palabras a su tabla comenzó a funcionar y la llamada pasó a estar correcta. Para poder comprobar que todo estaba bien se intentó crear un partida completa de nuevo pero volvió a aparecer un error. En esta caso el error solo surgía cuando el último jugador trataba de acabar su turno (la llamada de la API finishMatch) y, por tanto, acabar la partida. Realizando una serie de comprobaciones para poder corregir el error se encontró un fallo en el else encargado de finalizar la partida (cuando el último jugador finaliza su turno). Se estaba intentado acceder a una lista con un valor indefinido. Fijando ese valor a 0 el error se corrigió y la partida terminó actualizando los valores de las puntuaciones en el ranking. El último error encontrado en el servidor apareció al intentar probar todo en la máquina virtual, ya que en local ya había funcionado. Al crear las tablas en la base de datos de acuerdo al manual de instalación (Apéndice D), algunas tablas fallaban al crearse y la creación de todas ellas se detenía. La corrección de este error fue escribir todas las referencias a tablas de la base de datos de todos los archivos en formato ”CamelCase”. Esto quiere decir que los nombres de las tablas tienen la primera letra en mayúscula y si el nombre está compuesto de varias, cada una de ellas empezará por mayúscula también. En cuanto a errores en la aplicación Android, surgió un problema a la hora de mandar los datos al servidor. El error se daba en el formato de codificación de los caracteres y apareció al intentar usar palabras con ñ. Estas palabras no se escribían en la base de datos, porque el formato de envío no era el correcto y, por tanto, a la hora de recuperarlas para usarlas en una partida, esta fallaba. La corrección consistió en obtener los bytes del mensaje antes de enviarlo con la codificación UTF-8. 3.2.6. Pruebas realizadas Para poder comprobar que los errores surgidos han sido subsanados y que la aplicación funciona de manera correcta, lo cual permitirá pasar a la migración de las llamadas en la aplicación real, se han realizado una serie de pruebas que podemos ver en el Apéndice E. Algunas de estas pruebas ya habían sido probadas en el TFG de Clash of Pronunciations de Andrés de la Maza Valles [6], pero 43 3.3. Iteración 3 es necesario rehacerlas, ya que se habían hecho desde Postman y en una máquina local. En nuestro caso, ya estamos probando en un escenario prácticamente real, ya que tenemos la API desplegada en un servidor, junto con una serie de software que la hace más robusta como es PM2, que en caso de caídas, reinicia el servidor, o Nginx que se usa como proxy inverso y, además, la aplicación que realiza las llamadas es una aplicación de Android, que simula ser la aplicación CoP real. 3.3. Iteración 3 La tercera iteración, al igual que las otras, comenzó con una reunión con los tutores para establecer el orden de los trabajos, en función de la planificación ya establecida. En ella se presentó la aplicación de pruebas ya finalizada y se le dio el visto bueno. Además, se presentó la aplicación CoP mediante una explicación de su código y de los paquetes que a priori, se debían cambiar durante la migración de las llamadas. Además, se expusieron los requisitos del proyecto. 3.3.1. Trabajos previos En primer lugar, después de la reunión con los tutores se llevaron a cabo trabajos de corrección de la iteración previa, tanto a nivel de documento, como a nivel de programación. En lo que hace referencia al proyecto, se editó el script de datos con el que se insertaban en la base de datos los datos de prueba. Dicho script se dividió en dos para aislar los datos estrictamente necesarios en una base de datos en producción, de los datos de usuarios falsos usados durante el periodo en desarrollo de la aplicación. Junto con esto, se editó el manual de despliegue para dejar patente estos cambios. Por último, se añadió un archivo README.md en el git de la aplicación para probar las llamadas, en el que se explica el propósito de la misma. Una vez hecho esto, se pasó a la descarga del proyecto de CoP en la máquina local para comenzar con la labores de programación, siendo necesario un estudio y realización de un informe que permita ordenar y medir la importancia de los cambios. 3.3.2. Requisitos funcionales Los requisitos funcionales de la aplicación se corresponden con los requisitos funcionales definidos para la aplicación de pruebas en la Sección 3.2.1 a excepción del RF15, que no aplica a la aplicación real y que será sustituido por un nuevo requisito funcional que podemos ver en la Tabla 3.2. 44 Descripción de las iteraciones ID Nombre Descripción Prioridad RF01 Crear llamada login El sistema debe realizar una llamada login con los datos de la vista y mostrar la respuesta del servidor Extrema RF02 Crear llamada refreshToken El sistema debe realizar una llamada refreshToken con el refreshToken almacenado y mostrar la respuesta del servidor Extrema RF03 Crear llamada userData El sistema debe realizar una llamada userData con el token almacenado y mostrar la respuesta del servidor Extrema RF04 Crear llamada ranking El sistema debe realizar una llamada ranking con el token almacenado y mostrar la respuesta del servidor Extrema RF05 Crear llamada register El sistema debe realizar una llamada register con los datos de la vista y mostrar la respuesta del servidor Alta RF06 Crear llamada listChallenges El sistema debe realizar una llamada listChallenges con el token almacenado y mostrar la respuesta del servidor Alta RF07 Crear llamada opponents El sistema debe realizar una llamada opponents con el token almacenado y mostrar la respuesta del servidor Alta RF08 Crear llamada createChallenge El sistema debe realizar una llamada createChallenge con el token almacenado y las palabras y oponentes almacenados y mostrar la respuesta del servidor Alta RF09 Crear llamada startMatch El sistema debe realizar una llamada startMatch con el token almacenado y mostrar la respuesta del servidor Alta RF10 Crear llamada finishMatch El sistema debe realizar una llamada finishMatch con el token almacenado y mostrar la respuesta del servidor Alta RF11 Crear llamada infoChallenge El sistema debe realizar una llamada infoChallenge con el token almacenado y el id de un challenge y mostrar la respuesta del servidor Media RF12 Crear llamada addAchievement El sistema debe realizar una llamada addAchievement con el token almacenado y el id de un logro y mostrar la respuesta del servidor Baja RF13 Crear llamada showAchievements El sistema debe realizar una llamada showAchievements con el token almacenado y mostrar la respuesta del servidor Baja RF14 Crear llamada modify El sistema debe realizar una llamada modify con el token almacenado y los datos recuperados de la vista y mostrar la respuesta del servidor Baja RF15 Corrección de logs El sistema debe enviar logs de las partidas al servidor de ECASIMM (https://eca-simm.uva.es/) Alta Tabla 3.2: Requisitos funcionales de CoP 45 3.3.3. Requisitos no funcionales Los requisitos no funcionales de la aplicación hacen referencia a las características técnicas que el sistema debe cumplir. En la Tabla 3.3 se muestran los requisitos no funcionales del sistema ordenados de nuevo por prioridad. ID Nombre Descripción Prioridad RNF01 Sistema Android El sistema debe poder ejecutarse en un sistema Android Extrema RNF02 Versión mínima de sistema El sistema debe migrarse a una versión mínima de la API 26 de Android Extrema RNF03 Versión de compilación El sistema debe compilarse con la versión más actual de Android. Siendo esta Android 11 (API 30) Extrema RNF04 Corregir código obsoleto (deprecated) El sistema debe ser migrado al completo a la versión de Android escogida en el punto anterior, corrigiendo cualquier problema asociado Alta RNF05 Corrección de permisos en la app El sistema debe permitir almacenar en el dispositivo audios en formato amr y logs en formato json Alta RNF06 Eliminar código de la antigua API de Google Play Games El sistema debe quedar limpio de código antiguo referente a Google Play Games Alta RNF07 Multi-idioma El sistema debe ser mostrado al menos en 2 idiomas (español e inglés) Alta RNF08 Manual La aplicación contara con un manual de usuario bien estructurado Medio RNF09 Codificación La aplicación deberá utilizar la codificación de caracteres UTF-8 Alta RNF10 Responsivo La aplicación devolverá un resultado en menos de 1’5 segundos o en su defecto mostrará pantallas de carga. Alta Tabla 3.3: Requisitos no funcionales de la aplicación CoP 3.3.4. Requisitos de información Los requisitos de información detallan la información que se debe guardar en el sistema. En la Tabla 3.4 se muestran los requisitos de información que deben ser añadidos como consecuencia de la migración y eliminación de la API de Google Play Games. ID Nombre Descripción Prioridad RI01 Datos de usuario El sistema debe almacenar el nick, email, contraseña, imagen de perfil, puntuación, logros y partidas de cada usuario Extrema RI02 Datos de partidas El sistema debe almacenar las rondas, oponentes, puntuaciones de cada oponente, palabras y orden de cada ronda y el turno de cada partida Extrema RI03 Grabaciones El sistema debe almacenar las grabaciones Extrema RI04 Logs de las partidas El sistema debe almacenar ficheros json con el resultado de cada ronda de las partidas, de cada reconocimiento correcto o erróneo, de la elección de la palabra en rondas de Discriminación y de cada puntuación de cada usuario junto con el ganador final Alta Tabla 3.4: Requisitos de información de la aplicación CoP 3.3.5. Funcionalidad implementada Debido a que la aplicación ha sufrido un salto de versión desde la versión 25 del SDK (correspondiente a Android 7.1) hasta la última versión disponible a día 3/2/2021 (Android 11 o versión 30 del SDK), lo primero que ha sido necesario realizar ha sido un refactor para migrar todo el proyecto de la biblioteca android.support a la nueva biblioteca androidX. A continuación, se ha llevado a cabo un análisis del estado de proyecto completo, para encontrar todos los problemas asociados, principalmente, a bibliotecas obsoletas (entre otra, la ya mencionada anteriormente AsyncTask). El resultado de este análisis se puede observar en la siguiente Figura 3.5. En esta tabla podemos ver todos los cambios que se deben realizar solo referidos a mantenimientos de la aplicación y actualización de la misma y la ejecución de las llamadas desde alguna de esas clases. Además, se deberá modificar toda la lógica que se vea involucrada aunque por el momento se desconoce cuáles serán esas clases y se irán comprobando a medida que se avance en el desarrollo. Figura 3.5: Resultado del análisis del proyecto mediante las herramientas de inspección de código de Android Studio Centrándonos en los problemas más importantes, vemos que tenemos más de 100 errores asociados al uso de métodos, clases o bibliotecas obsoletas. Para poder diferenciar cuáles de los errores son más importantes y cuáles no tanto y organizar el trabajo a lo largo del tiempo, se ha realizado un informe. Este detalla el orden en el que deben ser corregidas las clases junto con otra serie de parámetros. Los parámetros usados para elaborar ese orden son el número de problemas encontrados, la llamada a la API a la que hacen referencia, si es que hacen referencia a alguna, y el nivel de importancia de dicha clase. El orden de ejecución de los trabajos de migración se puede ver en la Tabla 3.5. Durante esta iteración se actualizaron todas las clases y ficheros relacionados como .xml, .json etc., de la Tabla 3.5. Además, se actualizó y migró el código de las clases que tienen relación con las llamadas API y se implementaron todas las llamadas necesarias. También se tuvieron que crear varias vistas desde cero ya que antes se usaban vistas que ofrecía la API de Google Play Games, como el login, registro, lista de partida, información de cada partida, modificación del perfil y logros. Junto con los cambios en CoP también fue necesario llevar a cabo cambios y correcciones en la API debido a que a lo largo de las iteraciones se fueron encontrando problemas y bugs en las diferentes llamadas. Descripción de las iteraciones Orden Llamada API Nombre de la clase Warnings Paquete Importancia 1 - RoundedImageView 1 ImageUtils Extrema 2 - SplashActivity 2 Activity Extrema 3 Login Login 1 Server Extrema 4 RefreshToken - - - Extrema 5 UserData UserDataRetriever 1 Server Extrema 6 - MenuActivity 18 Server Extrema 7 Ranking LeaderboardDataRetreiver 1 Server Extrema 8 Ranking LeaderboardHelper 4 ImageUtils Extrema 9 Register - - - Alta 10 ListChallenges UserDataRetriever 1 Server Alta 11 Opponents InviteesDataRetriever 1 Server Alta 12 CreateChallenge StartMatch CreateGameDataProvider 1 Server Alta 13 - MultiPlayerRoomActivity 5 Activity Alta 14 - MultiPlayerHandler 26 Game Alta 15 - Synthesis 1 Sound Alta 16 - PairsExposureActivity 10 Activity Alta 17 - SpeechAPIHandler 10 SpeechAPI Alta 18 - PostAudioTask 1 SpeechAPI Alta 19 FinishMatch EndedGameDataProvider 8 Server Alta 20 FinishMatch EndedGameDataRetriever 1 Server Alta 21 InfoChallenge - - - Media 22 - PermissionDialog 1 Permissions Media 23 - PermissionManager 1 Permissions Media 24 - SystemPermissionDialog 1 Permissions Media 25 AddAchievement ShowAchievements AchievementHelper 6 Game Baja 26 Modify - - - Baja 27 - NotificationHandler 8 Notifications Muy baja 28 - NotificationsReceiver 1 Notifications Muy baja 29 - TasksDataProvider 1 Dashboard Muy baja 30 - TasksDataRetreiver 1 Dashboard Muy baja 31 - ListsDataRetriever 1 Dashboard Muy baja 32 - BaseGameUtils 3 Game Muy baja Tabla 3.5: Informe de las clases que deben ser editadas 49 Para poder ejecutar los trabajos de manera correcta durante toda la iteración, fue necesario la realización de varias reuniones a lo largo de esta. En ellas se presentaba el trabajo realizado y se exponía el trabajo futuro hasta la siguiente reunión. Además, antes de realizar cada reunión se realizaban pruebas de la funcionalidad implementada desde la propia aplicación, para verificar el correcto funcionamiento de la misma. Para más información de los trabajos ejecutados se ha elaborado un apéndice en el que se detallan en profundidad todos los problemas encontrados durante la implementación de la funcionalidad (Apéndice B). 3.3.6. Pruebas realizadas Este apartado es solo un resumen de las prueba ejecutadas durante el proyecto, para ver toda la información referente a las pruebas ir al apartado de Pruebas (capítulo 5) más adelante en este documento. A medida que se iban añadiendo llamadas y corrigiendo clase obsoletas (deprecated) se fueron realizando pruebas tanto con la aplicación de pruebas creada al inicio como con la aplicación de CoP. La aplicación de pruebas permitía comprobar si las llamadas funcionaban bien desde un entorno Android y sin la necesidad de tratar con la interfaz de usuario de CoP, que hasta estar terminada podía generar algún tipo de problema. De esta manera se podían aislar errores en las llamadas y ejecutarlo de manera sencilla simplemente cambiando el contenido del json que se enviaba al servidor en cada llamada. A su vez, a medida que avanzaba la implementación de las llamadas en CoP y su acople dentro del código antiguo, se iban probando las funcionalidades añadidas. Evidentemente los primeros casos probados correspondieron a las llamadas de login, userData y refreshToken y los últimos, ejecutar varias partidas completas y ver las puntuaciones y logros obtenidos en partidas multijugador entre el desarrollador del TFG y los tutores. 3.4. Iteración 4 3.4.1. Trabajos realizados De nuevo la iteración comenzó con una reunión con los tutores en la que se expusieron las labores ejecutadas durante toda la iteración anterior, la presentación de la aplicación final y los siguientes pasos antes de concluir el trabajo. La aplicación se entregó a los tutores para que comprobaran las funcionalidades añadidas y crearan una lista de fallos o bugs a corregir durante esta iteración. Mientras los tutores llevaban a cabo esta corrección se pasó a avanzar la memoria del proyecto durante la primera semana de la iteración. Al comenzar la segunda semana de la iteración se llevó a cabo una nueva reunión. Los tutores presentaron un informe con 40 cambios o fallos ordenados por prioridad y que debían ser solventados Descripción de las iteraciones a lo largo de la semana. Mientras se trabajaba de nuevo en la aplicación, los tutores corrigieron todo el documento que se había completado hasta ese momento generando un nuevo informe con cambios y correcciones que realizar. Al inicio de la tercera semana se organizó una reunión para comprobar el avance del proyecto. Se entregó la nueva aplicación para una última revisión y se comentaron los cambios necesarios en el documento. A lo largo de esta semana la labores del alumno, por tanto, fueron acabar y corregir el documento mientras los tutores realizaban la última corrección de la aplicación. Por último, en la última semana de trabajo se llevó a cabo una última reunión en la que se entregó el documento para realizarse una última corrección de 25 cambios o fallos encontrados. A lo largo de esta semana se corrigieron tanto dichos fallos en la aplicación como los del manuscrito y se realizaron pequeños ajustes en las vistas de la aplicación. 3.4.2. Productos finales Al final del TFG se ha obtenido una aplicación (cop.apk) basada en Android 11 (API 30) lista para ser subida a la Play Store. Además de la aplicación, el código fuente de la aplicación de pruebas, de la app CoP y del servidor de CoP se encuentran en tres repositorios privados del grupo ECA-SIMM. En cuanto al servidor, podemos encontrarlo desplegado junto a la base de datos en una máquina virtual proporcionada por la Escuela de Ingeniería Informática de la Universidad de Valladolid. Por último, todo el TFG ha sido documentado en este manuscrito. 51 Figura 4.1: Modelo de dominio de CoP Nombre Participant Descripción Modela un participante de un partida. Contiene todos los datos necesarios que se reciben o envían en las llamadas de opponents, createChallenge o infoChallenge Atributos nick: contiene el nombre de usuario, que permite iniciar sesión y que es único para cada usuario email: contiene el email del usuario y que es único entre todos los usuarios image: contiene la url de la imagen de perfil de un usuario score: contiene la suma de las puntaciones extra y base phoneticLevel: contiene el valor de nivel fonético del usuario ranking: contiene la posición en el ranking del usuario Tabla 4.10: Entidad Participant Nombre Challenge Descripción Modela una partida. Contiene todos los datos necesarios que se reciben o envían en las llamadas de listChallenges, createChallenge, startMatch, finishMatch o infoChallenge Atributos id: contiene el identificador único de un Challenge difficulty: contiene la dificultad de una partida. Actualmente todas las partidas son dificultad media isMultiplayer: boolean que a true indica que la partida es multijugador. Si es false será un entrenamiento currentTurn: contiene el turno del usuario gameMode: contiene el tipo de juego updatedAt: contiene la última fecha de actualización del Challenge Tabla 4.11: Entidad Challenge 4.1. Diagramas de análisis Nombre WordData Descripción Modela una palabra. Contiene todos los datos necesarios que se reciben o envían en las llamadas de createChallenge o infoChallenge Atributos name: contiene el nombre de la palabra en CamelCase. Este nombre es su identificador counterWord: contiene un byte que identifica el contador de la palabra. Al principio iniciado a COUNTER_WORD_NOT_SET para que no se muestren mensajes hasta que no se haya jugado al menos una vez con ella url: contiene la url de la palabra y permite mostrar su imagen. Actualmente no se usa, pero se mantiene para posibles añadidos futuros transcription: contiene la transcripción de la palabra para mostrar como debe ser pronunciada numberPlays: contiene el número de intento que puede tener una palabra wrong: boolean que indica si la palabra se ha dado por incorrecta definitivamente wrongCounter: contiene el número de fallos en un turno que ha tenido cada palabra order: contiene el orden que las palabras han tenido en la partida del creador y que permite mantenerlo en las partidas de los oponentes Tabla 4.12: Entidad WordData 60 Estado final de la aplicación Nombre ResultTurn Descripción Modela el resultado de un Parcitipant en un Challenge concreto. Además, permite identificar cada relación Participant Challenge ya que un Participant puede tener muchos Challenges y un Challenge puede tener muchos Participants Atributos id: contiene su identificador base: contiene la puntuación base del usuario o -1 si aún no tiene puntuación extra: contiene la puntuación extra del usuario o -1 si aún no tiene puntuación turn: contiene el turno que se le ha asignado al usuario time: contiene el tiempo empleado por el usuario en jugar un Challenge rightWords: contiene el número de palabras correctas de un Participant en un Challenge wrongWords: contiene el número de palabras incorrectas de un Participant en un Challenge Tabla 4.13: ResultTurn 61 4.1. Diagramas de análisis 4.1.3. Diagramas de actividad En la presente sección se exponen todos los diagramas de actividad de las historias de usuario definidas anteriormente. Se detallan tanto las interacciones del usuario real con la aplicación como las acciones que realiza el frontend de la aplicación y las llamadas ejecutadas a la API del servidor. Login de un usuario (HU01) Figura 4.2: Diagrama de la historia de usuario del login (HU01) 62 Datos de usuario (HU02) Figura 4.3: Diagrama de la historia de datos de usuario (HU02) Ranking de usuarios (HU03) Figura 4.4: Diagrama de la historia de ranking de usuarios (HU03) Registro de un nuevo usuario (HU04) Figura 4.5: Diagrama de la historia de registro de un usuario (HU04) Lista de partidas (HU05) Figura 4.6: Diagrama de la historia de usuario de listar partidas (HU05) Crear partida (HU06) Como se puede ver a continuación (ver Figura 4.7), la historia de usuario crear partida está compuesta de varias acciones y en cada una de ellas se ejecuta una llamada de la API diferente. La primera acción para poder crear una partida es escoger los oponentes de esta para lo que se ejecuta la llamada de opponents (ver Figura 4.12). A continuación, si el usuario sigue el proceso tendrá que aceptar los oponentes y comenzará la partida. Antes de que la partida comience en el dispositivo se ejecutará la llamada a la API de createChallenge (ver Figura 4.7) y startMatch (ver Figura 4.13). Una vez que el usuario ha terminado la partida o la ha cerrado sin acabar se ejecutará la llamada de finishMatch (ver Figura 4.14). Figura 4.7: Diagrama de la historia de usuario de crear partidas (HU06) 4.1. Diagramas de análisis Figura 4.14: Diagrama extra de la historia de usuario de crear partidas (HU06) y de la historia de usuario de ver la información de una partida (HU07) 74 Estado final de la aplicación Figura 4.15: Diagrama extra de la historia de usuario de ver logros (HU08) 75 4.2. Estructura del proyecto 4.2. Estructura del proyecto En la Figura 4.16 podemos ver la estructura de la aplicación CoP. Es necesario destacar que esta no es la estructura de ficheros real, ya que estamos utilizando la vista de Android (por defecto en Android Studio) que facilita ver todas las carpetas y recursos del proyecto. Figura 4.16: Estructura de CoP En la figura podemos identificar en primer lugar la carpeta ”manifests”. En ella se encuentra el Manifest. En este fichero se describen los permisos a utilizar en la aplicación así como las Activities que la aplicación contenga. A continuación encontramos la carpeta java. En esta carpeta están contenidos todos los paquetes de CoP. Los primeros paquetes que encontramos son el de permisos (”permissions”) y el paquete ”clashofpronunciations”. Dentro de este último es donde encontramos la mayoría de paquetes de CoP que serán explicados en los siguientes apartados. Además de estos, podemos ver el paquete de test en el que se encuentran las clases con los test realizados. Una vez vistos los paquetes principales de la aplicación se van a explicar las carpetas de recursos de Android. Como se puede en la Figura 4.16 todos los recursos del proyecto se encuentran bajo la carpeta ”res”. En ella encontramos varios directorios de recursos diferentes: El primer directorio es el de ”anim” que contiene las animaciones que tenga el proyecto. A continuación vemos el directorio ”color”, que contiene los xml de colores que definamos. El directorio ”drawable” almacena diferentes formas o elementos visuales que luego pueden añadirse a las vistas. 76 Estado final de la aplicación El directorio ”font” almacena las diferentes fuentes de texto que contenga nuestro proyecto. El directorio ”layout” contiene todos los xml de todas las vistas de la aplicación. Estos xml son cargados desde las Activities en su creación para dar lugar a la vista. El directorio ”raw” contiene los ficheros de audio. El directorio ”values” almacena varios directorios más entre los que hay que destacar el directorio ”string” que guarda todas los textos del proyecto y sus traducciones y el directorio ”styles” que almacena configuraciones de estilos que luego pueden ser usados en las diferentes vistas para editar el estilo de un botón o de cualquier otro elemento. El directorio ”xml” contiene un fichero con datos de dominios de red. 4.3. Diagramas de diseño A lo largo de esta sección se presentarán los patrones y técnicas de diseño utilizadas durante el proceso de migración y actualización de la aplicación. Además, se expondrán los paquetes nuevos o actualizados, las clases de cada paquete que han sido modificadas o creadas de cero, el diagrama de la base de datos y finalmente un diagrama de despliegue de la aplicación. 4.3.1. Arquitectura y patrones de diseño Antes de comenzar es necesario resaltar que durante el proceso de migración y actualización solo nos hemos centrado en la arquitectura de las nuevas clases a implementar, manteniendo el diseño anterior del resto de clases (ver en [9] y [1]). Arquitectura de la aplicación La aplicación se encuentra distribuida en 3 capas (ver Figura 4.17), siendo la primera la capa de presentación, en la que encontramos el patrón MVVM. La segunda es la capa de negocio, que mantiene la mayoría de paquetes de la aplicación y es donde se ejecuta la lógica de los casos de uso. La última capa será la de servicios y en ella encontramos los paquetes que se encargar de la escritura de ficheros y de realizar llamadas http. Este tipo de arquitectura es el recomendado por Android como podemos ver en la Figura 4.18. 77 Figura 4.17: Arquitectura de CoP Figura 4.18: Arquitectura de una aplicación Android. Fuente: Android developers [58] Patrón de presentación MVVM y clase LiveData Como diseño de las nuevas vistas se ha propuesto el patrón de presentación MVVM (Model View ViewModel). Este es el patrón recomendado por Android en la actualidad [58]. Este patrón permite aislar la lógica que se encarga de la vista únicamente en una clase (Activities en nuestro caso) y mantener el estado de los datos mostrados en la vista en el ViewModel junto con el resto de la lógica. Por tanto, cada pantalla de la aplicación debería tener su Activity y su ViewModel y además, poder acceder a los Estado final de la aplicación datos del modelo. Cuando el ViewModel ejecuta diferentes acciones en segundo plano, como realizar una llamada a una API o una consulta en una base de datos, este almacena los cambios en variables propias de tipo MutableLiveData [59]. Los ViewModel deben tener métodos que retornen variables LiveData (como MutableLiveData pero sin que pueda ser modificada). Estas variables LiveData puedes ser observadas desde las vistas. De esta manera, una Activity observa las diferentes variables LiveData de su ViewModel. El ViewModel ejecuta diferentes acciones en segundo plano y cuando recupera su información la almacena en los diferentes MutableLiveData que mantiene. El MutableLiveData notificará a todos los observadores (recordamos que la Activity está observando estas variables) que ha habido un cambio de estado y la Activity será capaz de responder a este evento realizando algún tipo de acción en la vista. Patrón Observador El patrón observador permite que un objeto A se suscriba a otro B, de manera que cuando el objeto B sufre algún cambio en su estado, este notifica a los objetos que se han suscrito a él que ha habido cambios. De esta manera, el objeto A puede reaccionar a estos cambios (ver Figura 4.19). En al actualidad la mayoría de interfaces de usuario de frameworks modernos hacen uso de este patrón. En Android permite no bloquear el hilo principal para que este pueda seguir realizando acciones o escuchando eventos de usuario mientras se ejecutan acciones en segundo plano y reaccionar a estas una vez se han llevado a cabo. Figura 4.19: Estructura del Patrón Observador. Fuente: wikipedia [60] Como se ha comentado en el apartado anterior, este patrón se ha usado en CoP para observar las diferentes acciones que ejecuta el ViewModel y actuar una vez se notifican los cambios. 79 4.3. Diagramas de diseño Patrón Singleton El Patrón Singleton permite mantener una única instancia de un objeto en memoria. Para llevarlo a cabo el patrón almacena su propio estado como atributo y mantiene privado su constructor. De esta manera, si otro objeto B desea hacer uso del objeto Singleton, dicho objeto Singleton creará la instancia o devolverá la creada anteriormente (ver Figura 4.20). En CoP este patrón ha sido utilizado para mantener el estado del usuario registrado una vez se ha recuperado su información. Figura 4.20: Estructura del Patrón Singleton. Fuente: wikipedia [61] Patrón Fachada El Patrón Fachada permite acceder a un paquete con varias clases a través de una única clase y así centralizar todas las llamadas entre paquetes en un único lugar. En CoP este patrón se ha usado en el nuevo paquete creado para ejecutar las llamadas al servidor. Ese paquete (Request) contiene todas las acciones necesarias para ejecutar las diferentes llamadas y se encarga de acceder al resto de clases (que contienen funciones para obtener los datos) (ver Figura 4.21). Figura 4.21: Estructura del Patrón Fachada. Fuente: wikipedia [62] 80 Estado final de la aplicación 4.3.2. Diagrama de paquetes En la Figura 4.22 se muestra la distribución de las clases en los paquetes de la aplicación. Es necesario destacar que aquí se muestran todos los paquetes que contiene la aplicación pero no todos ellos han sido actualizados. Los paquete que han recibido modificaciones se encuentran en color verde y los paquetes que se han creado de cero el color azul. Figura 4.22: Diagrama de paquetes de Clash of Pronunciations El paquete activity contiene todas las clases de tipo Activity de la CoP y además, contiene el nuevo paquete creado (ui) en el que se incluyen las nuevas Activities creadas y sus ViewModels siguiendo el patrón MVVM. Además de activity, tenemos el paquete model, que almacena todas las clases del modelo. Y los paquetes pertenecientes a la lógica de negocio. Dentro de esta lógica de negocio encontramos los paquetes design, que contiene clases encargadas de la funcionalidad de ciertos elementos visuales; game contiene clases que ayudan a ciertas acciones como obtener datos de los logros dado un id; speechapi contiene las clases encargadas del reconocimiento; dashboard se encarga de recibir tareas desde un dashboard web para mostrarlas en la app y que los usuarios puedan realizarlas (relacionado con unas prácticas en empresa); imageutils contiene clases encargadas de la vista usada para mostrar la imagen del perfil; notification es el paquete encargado de las notificaciones; sound es el paquete que contiene las clases que permiten reproducir o reconocer la voz; other que contiene clases encargadas de la valoración de la aplicación; finalmente el paquete request contiene las clases relacionadas con 81 4.3. Diagramas de diseño los casos de uso de las llamadas a la API, así como las clases que contienen las funciones de cada llamada. En request se crean los mensajes a enviar a la API a través de las clases del modelo y se leen y tranforman las respuestas de la API para obtener las clases del model necesarias para las vistas. El siguiente paquete es file, que contiene las clases encargadas de leer o crear ficheros. El paquete log y upload contienen las clases que crean los logs y las clases encargadas de subir los ficheros al servidor de ECA-SIMM. El paquete api es el que contiene los ficheros para realizar conexiones http usadas en las llamadas a la API. 4.3.3. Diagrama de clases En la Figura 4.23 y Figura 4.24 se muestran las diferentes clases que encontramos en cada paquete. Como podemos ver, al igual que en el apartado anterior, las clases en color verde han sido modificadas o editadas durante el desarrollo y las clases en azul han sido creadas de cero. Figura 4.23: Diagrama de clases del paquete activity.ui 82 Estado final de la aplicación Figura 4.24: Diagrama de clases del resto de paquetes Dentro del paquete activity.ui encontramos los diferentes paquetes de cada nueva vista implementada. Además podemos ver las Activities que ya existían y que han sido modificadas. Hay que resaltar que las Activities son las clases que contienen la lógica exclusivamente encargada de la vista. Los ViewModel almacenan el estado de los datos representados para evitar su pérdida si hay que rehacer la vista (como al pasar al rotar el dispositivo móvil). Por último, las clases que contienen la palabra ”Adapter” en su nombre se encargan de definir la información que se muestra en los listados que sus Activities contienen. El paquete ”model” solo contiene clases del modelo. A destacar la clase LoggedInUser que, usando el patrón Singleton, mantiene los datos del usuario en memoria. El último paquete que es necesario explicar más en profundidad es el paquete ”request”. Este presenta una clase principal (”CreateCall”), que se encarga de aglutinar todas las llamadas de la API. Desde fuera del paquete solo se accede a esta clase principal y es ella la que se encarga de llamar al resto de clases del paquete. El resto de clases son funciones que forman objetos json para enviar datos a la API o bien recuperan la información de las respuestas obtenidas. Este paquete se comunica con el paquete ”api” de la capa de persistencia/API para realizar las conexiones http. 4.3.4. Diagrama de la base de datos En la ejecución de este proyecto no se ha creado una base de datos ya que no ha sido necesaria porque los datos son almacenados por la API en el servidor. A pesar de esto, sí que se han tenido que crear scripts para insertar datos en la base de datos y se ha tenido que desplegar y crear un manual 83 5.3. Test de usabilidad 5.3. Test de usabilidad Para poder comprobar que la aplicación es fácil de utilizar y sencilla en aprender, se ha definido un test de usabilidad. En él vamos a proponer a dos usuarios reales realizar dos acciones de la aplicación. Una la consideramos más compleja de ejecutar y la otra más sencilla. Durante ese proceso estaremos observando las acciones que realizan estos usuarios y anotaremos en una tabla las métricas utilizadas (ver Tabla 5.1). Tarea Tarea 1 ¿Completado? Sí Valoración 10 Descripción Descripción de la tarea a realizar Métricas tiempo dedicado a realizar la tarea en segundos: toques para completar la acción (necesarios X): errores: Observaciones Posibles situaciones o comentarios realizados por los usuarios del test Tabla 5.1: Plantilla utilizada para los test de usabilidad Los atributos de usabilidad que vamos a medir son la eficiencia, la eficacia y la satisfacción. La eficiencia será correcta si el usuario consigue terminar la tarea sin ayudas, la eficacia si el usuario consigue realizar la tarea sin toques innecesarios y en tiempo moderado y la satisfacción se medirá con las preguntas finales. Las dos tareas que deben realizar los usuario serán: Arrancar la aplicación y registrarse en ella, crear una partida con 4 oponentes y jugarla. Una vez terminada volver al menú principal y acceder a la información de esta. Arrancar la aplicación y mostrar el ranking de usuarios. Después mostrar la lista de logros. Obtenidas las tareas, debemos crear los escenarios que son presentados a los usuarios para que conozcan el contexto de la aplicación y comprendan las tareas que tienen que realizar. Lo escenarios son: Imagina que te has bajado la aplicación y quieres jugar tu primera partida multijugador, por turnos, frente a 4 jugadores más. En primer lugar, deberás registrarte en la aplicación introduciendo tus datos. Tras esto ya podrás acceder a la aplicación y jugar partidas. Crea y juega una partida multijugador con 4 oponentes. Una vez has jugado la partida, quieres ver los resultados que has obtenido tú y ver si algún jugador más ya ha jugado. 90 Pruebas Imagina que llevas con la aplicación descargada en tu dispositivo varios días y ya has jugado partidas y conseguido logros. Esta vez quieres acceder a la aplicación y ver el ranking con todos los usuarios. Después quieres ver tu lista de logros. Al finalizar las tareas se realizarán las siguientes preguntas a los usuarios con el fin de recuperar la máxima información posible. De esta manera se podrán proponer cambios en la interfaz de usuario para mejor la experiencia y usabilidad de la aplicación. Las preguntas serán: ¿La interfaz le ha parecido intuitiva? ¿En algún momento no ha sabido que hacer? ¿Los tamaños de letras e iconos le parecen adecuados? ¿Desea añadir algún comentario más? Los usuarios escogidos corresponden a dos grupos muy diferentes, uno de ellos tiene 24 años y una habilidad gran habilidad con la tecnología (en el uso diario de aplicaciones y el móvil) propia de este sector de la población. El otro usuario tiene una edad de 60 años y aunque no parte de cero con la tecnología, su habilidad es mucho más limitada. No consideramos un tercer grupo que no tenga habilidad con la tecnología porque consideramos que la aplicación se oriente a este tipo de personas. Para llegar a proponerse trabajar un idioma con una aplicación móvil y descargarla desde la Play Store es necesario partir de un cierto grado de experiencia. Antes de comenzar con el test se explicó a los dos usuarios en qué consiste CoP y las acciones que deberían realizar en cada tarea de manera detallada. Hecho esto, se comenzó con el test. En el Apéndice C se muestran las tablas con los datos obtenidos en cada apartado de cada tarea. Como puede verse los resultados muestran que la interfaz es intuitiva y fácil de aprender. A pesar de ser el primer contacto de los usuarios con la aplicación, los resultados obtenidos en pulsaciones de la pantalla son muy similares a toques mínimos y el tiempo de cada subtarea es relativamente bajo. Además, todas las tareas fueron completadas y sin errores. Como se han completado todas las tareas si problemas la eficiencia se considera máxima. Respecto de la eficacia, el tiempo, los toques en pantalla y inexistencia de errores permite afirmar que esta también es muy alta. Por último, la satisfacción de los usuarios, que medimos de acuerdo a las respuestas de las preguntas, podemos afirmar que también es muy alta, y que sería necesario un estudio mayor para conocer si de verdad es necesario añadir nombres en los iconos o crear un tutorial inicial de acuerdo a los comentarios. 5.3.1. Conclusiones obtenidas en los test de usabilidad Como era de esperar antes de realizar el test, el usuario más joven y con mayor manejo tecnológico realizó la mayoría de acciones en un tiempo más corto y sin errores. A pesar de esto hay que destacar que el usuario menos experimentado tampoco encontró problemas para realizar las tareas de manera correcta. 91 5.3. Test de usabilidad Al finalizar el test de usabilidad se pueden extraer varias conclusiones de acuerdo a los comentarios y observaciones de los usuarios: Al arrancar la aplicación por primera vez el usuario puede estar un poco perdido. Sería conveniente añadir un tutorial inicial mostrando todos los botones de la aplicación y explicando las diferentes modalidades de juegos. Es necesario realizar un estudio mayor antes de editar la interfaz. Los botones de ranking e historial de partidas no han sido del todo intuitivos en uno de los dos casos. De nuevo, realizar un tutorial inicial solventaría este problema. 92 Capítulo 6 Conclusiones En este capítulo se exponen las diferentes ideas que se han ido recopilando a lo largo de la realización del proyecto. Además se arroja luz a posibles implementaciones y mejoras futuras del mismo. Primero, en este TFG se ha modificado la aplicación móvil CoP basada en la tecnología de Android 11 (API 30), Java 8, TTS y STT y que se comunica con un servidor web que basado en Node.js y que utiliza las herramientas Nginx, PM2 y MySQL como base de datos. Gracias a esta migración, se ha conseguido volver a hacer funcional la aplicación que anteriormente usaba la API de Google Play Games y que llevaba casi tres años parada como consecuencia del no mantenimiento de dicha API y del código fuente de Android. Debemos destacar que el código fuente de CoP ha evolucionado a lo largo de cinco años (desde 2016) y está directamente relacionado con otros dos TFGs [9, 6], un TFM [1] y una tesis doctoral [4]. Durante el proceso de migración se han descubierto nuevas herramientas, ya sean Nginx y PM2 para el despliegue del servidor web a lo largo de la primera iteración del proyecto. También el uso de sequelize en la base de datos y el propio entorno de ejecución de JavaScript (Node.js), que ha sido necesario entender para poder corregir los diferentes problemas encontrados. En la segunda y tercera iteración, en las que se han desarrollado las aplicaciones de pruebas de las llamadas y la migración de las llamadas de CoP, se ha podido conocer en profundidad el framework de Android, y se ha comprendido la necesidad de mantener una arquitectura compleja en una aplicación, ya que, como consecuencia de las iteraciones que la aplicación ha ido sufriendo con el paso del tiempo, desde su desarrollo original, varias clases se han convertido en clases poco manejables y demasiado complejas. Respecto al código de la aplicación Android, aunque final de este capítulo se detallarán posibles mejores y trabajos futuros para la misma, se ha echado en falta una arquitectura inicial bien definida y separar la lógica de las clases que se encargan de las vistas de la interfaz móvil (Activities). Esto no estaba bien definido cuando la aplicación vio la luz hace más de 5 años y se ha quedado un poco atrasado. A pesar de esto, en las nuevas vistas que se han creado sí se ha usado un patrón de presentación MVVM (la recomendación actual de Google para Android) y además, se ha usado un paquete extra dedicado únicamente a las llamadas al servidor y las funciones relacionadas con estas llamadas. En cuanto a la planificación, se ha podido constatar la dificultad de realizar una buena planificación, a 93 6.1. Trabajo futuro pesar de estar relativamente cerca en horas reales sobre las planificadas. Además, se ha comprobado la necesidad de una planificación precisa. Partiendo de ella, cumpliendo los objetivos por iteraciones y dejando algunos días de margen, se puede llegar a la fecha de entrega de manera correcta y sin enormes esfuerzo finales. Junto con la planificación, es necesario destacar la metodología utilizada. Gracias al método iterativo se ha podido mostrar el progreso a lo largo de las iteraciones y incluso dentro de ellas. De esta manera los tutores han podido corregir conceptos erróneos o dar nuevas ideas sin tener que tirar todo el trabajo realizado. El hecho de comprobar el progreso en las iteraciones con las fechas y tiempo planificado permite conocer si hay retrasos y cómo de grandes son. Por otro lado, las pruebas realizadas han permitido obtener retroalimentación sobre el sistema. Los posibles usuarios reales ofrecen sus puntos de vista en los test de usabilidad y se proponen o sugieren mejoras con sus comentarios. En nuestro caso, los usuarios han reportado que un pequeño tutorial introductorio al iniciar la aplicación por primera vez podría ayudar a comprender antes la interfaz y con ello la aplicación en su conjunto. Otro posible cambio, sería añadir nombres a los botones de ranking, historial y logros para facilitar su interpretación. Respecto a los test unitarios, a pesar de que no se ha podido cubrir gran cantidad de código se ofrecen varios ejemplos de cómo poder testar el resto de llamadas a la API de manera automática. Finalmente, en lo personal, el trabajo ha sido muy interesante, ya que me ha permitido recuperar un juego, que estaba parado y volver a hacerlo funcionar, actualizándolo a la última versión de Android. Además, he sido capaz de planificar un proyecto a cuatro/cinco meses vista y que las estimaciones fueron relativamente realistas, por supuesto, con la ayuda de los tutores. Desde el punto de vista del sistema operativo (Android), el TFG me ha permitido aprender a crear aplicaciones Android con Java, a realizar tareas en segundo plano así como reaccionar a los resultados obtenidos en esas llamadas. Respecto del mantenimiento de aplicaciones, queda como manifiesto la necesidad de actualizar el código fuente de la aplicación más a menudo. Si esto no se hace, aparecen, como fue nuestro caso, un gran cantidad de problemas asociados debido a la eliminación o cambio de muchas bibliotecas. Es necesario resaltar la necesidad de una arquitectura bien definida que permite diferenciar los módulos de la aplicación por capas y extraer la lógica de negocio de toda las vistas. Por último, en cuanto a las tecnologías utilizadas y con mi experiencia en las prácticas de empresa utilizando Kotlin se hace necesario el cambio a este lenguaje para programar. El uso de las ya nombradas corrutinas permiten ejecutar código en segundo plano de una manera mucho más sencilla y testarlo mediante métodos propios de estas. Por esta razón sugeriría una actualización del código Java a Kotlin junto con la definición de una arquitectura mejor definida [58] antes de seguir aumentando las funcionalidades de la aplicación. 6.1. Trabajo futuro Como ya se ha ido recogiendo a lo largo de proyecto, se han propuesto posibles líneas de trabajo futuro a realizar para mejorar la aplicación. En este último apartado se agrupan todos ellas por orden de prioridad: Paginar las llamadas que devuelven listas en la API, para evitar posibles problemas en los dis94 Conclusiones positivos. De esta manera se devolverá como respuesta una lista limitada en tamaño y, en caso de querer recuperarse los siguientes elementos de la lista, será necesario realizar otra nueva consulta desde la aplicación. Limitar el número de intentos de acceso por login con una misma IP. El servidor deberá bloquear esa IP para prevenir frente a ataques de denegación de servicios. Crear una llamada en la API para cancelar partidas. De esta manera se podrá crear un botón en la información de cada partida para cancelarla si no se desea jugar. Añadir nuevos ficheros con palabras a la aplicación, con diferentes idiomas e incrementar el número de palabras por ronda, con el fin de variar la dificultad de las partidas. Actualmente esta dificultad está fijada en media, lo que significa que solo se usan las 3 primeras palabras de la lista obtenida del reconocedor. Variando este número de palabras o el número de intentos podemos crear nuevas dificultades. Creación de una comprobación en segundo plano en el servidor que elimine las partidas pendientes tras un periodo de tiempo dado. De esta manera se eliminarán de la base de datos partidas sin terminar. Definir y migrar la aplicación a arquitectura definida por capas y con patrón de presentación MVVM. A la vez que se ejecuta el punto anterior, sería conveniente migrar la aplicación de Java a Kotlin, ya que Android desde hace varios años se ha convertido en Kotlin-first [18]. Añadir fecha de nacimiento a rango de edad para poder segmentar a los usuarios. Parametrización de subida de ficheros (audio y logs) al servidor deseado. Añadir la posibilidad de seguir a usuarios y ver su ranking, su perfil, o sus partidas jugadas. De esta manera se podrá ver la mejora de esos jugadores y así incitar al usuario a mejorar también. Recuperar el modo de juego de 1 jugador, modalidad de juego que funcionaba antiguamente, que permite jugar de manera indefinida partidas similares a las de multijugador pero contra la máquina y que también otorga puntos. 95 Apéndices 97 Apéndice A Acrónimos API: Application Programming Interface. CoP: Clash of Pronunciations. COVID-19: Coronavirus-Disease-19. CPU: Central processing unit. ECA-SIMM: Grupo de investigación de entornos de computación avanzada y sistemas de interacción multimodal. GB: Gigabyte. IP: Internet Protocol. IVA: Impuesto sobre el Valor Añadido. JSON: JavaScript Object Notation. JWT: Json Web Token. MVVM: Model-View-ViewModel. RAM: Random access memory. REST: REpresentational State Transfer. SDK: Software Development Kit. SSH: Secure SHell. STT (TTS): Speech-to-text. TFG: Trabajo Fin de Grado. TFM: Trabajo Fin de Máster. TTS: Text-to-speech. 99 demasiados problemas y se pudo implementar de manera rápida. Cabe destacar que a diferencia de lo que antes ocurría, aquí fue necesario recuperar la lista de palabras por pares y transformarla en dos listas con el tamaños igual al número de rondas en la que cada índice contenía la palabra del mismo par. Esto es necesario ya que el servidor debe almacenar estas palabras para poder mandarlas en la llamada infoChallenge y que los oponentes puedan jugar la misma partida. Las llamadas de startMatch y finishMatch no supusieron ningún tipo de problema, ya que son dos llamadas muy sencillas que solo requieren obtener el id de la partida y, en el caso de finalizar partida, la puntuación base obtenida, por lo que pudieron crearse en poco tiempo ambas. Los siguientes pasos a realizar antes de llegar a la siguiente reunión con los tutores del TFG fueron la corrección de errores en la aplicación así como la actualización de ciertas clases que se usaban para subir los ficheros de audio de las partidas y los datos de estas en un json al servidor de ECA-SIMM. El problema aparece en Android 11, ya que en la versión más moderna de la actualidad de Android ya no se puede acceder a cualquier ruta escogida de la memoria, porque lo que los ficheros generaban errores al intentar guardarse. Según [70] es necesario pedir a Android la ruta mediante el método getExternalFilesDir(Environment.DIRECTORY_MUSIC) y que este te retorne la ruta en la que alojar los diferentes archivos creados. Tras estos arreglos, al jugar una partida de entrenamiento los logs ya se mandan al servidor de ECA-SIMM y en el caso de los entrenamientos de pronunciación, también los audio grabados durante la práctica. En la siguiente reunión se planteó la implementación de las cuatro llamadas restantes y la corrección de todas las clases restantes para las siguientes dos semanas. La llamada más complicada durante este periodo sería la llamada de infoChallenge, que debe recuperar los datos de una partida concreta y generar la partida tal y como si la hubiera creado el creador mediante createChallenge. Para ello, antes de comenzar con la implementación se crearon, como siempre, los diagramas de cada una de las cuatro llamadas restantes. La sección 4.1.3 contiene los cuatro diagramas correspondientes a las cuatro últimas llamadas al servidor. A tener en cuenta que, como se puede ver en la Figura 4.8, la llamada se realiza en dos lugares, tanto al pulsar sobre uno de los elementos de la lista de partidas, para mostrar toda la información de esa partida, y desde el final de una partida, para poder recuperar las puntuaciones de todos los usuarios y. mostrarlas antes de volver al menú principal. Fue necesario crear una vista nueva para mostrar toda esta información ya que antes las partidas dependían de la antigua API de Google Play Games y no existe tal pantalla (ver Figura B.4). 106 Figura B.4: Vista de la información de una partida de un usuario de CoP. De izquierda a derecha, partida en la que aún no se ha jugado el turno, partida en la que se ha jugado el turno y falta por jugar algún usuario y partida finalizada en la que el usuario ha resultado ganador Con la llamada de infoChallenge completa, se pudieron probar varias partidas de manera completa, encontrando de nuevo un problema con las palabras que llegaban en junto con el resto de información. El problema era que la palabra ”Stomp” no se guardaba en la base de datos del servidor al crear la partida, y por lo tanto, tampoco se devolvía al pedir la información de la partida. Comprobando los logs y los datos de la base de datos se puede observar que ya existía una palabra guardada que era ”stomp”. La base de datos la consideraba igual y no la guardaba, pero acto seguido se recuperan todas esas palabras de la base de datos y Node no la recupera porque la aplicación web sí distingue entre mayúsculas y minúsculas. Para evitar este y futuros problemas se decidió enviar todas las palabras desde la aplicación móvil con la primera letra de la palabra en mayúscula y las siguientes en minúscula. Respecto del resto de llamadas, añadir logro y ver los logros desbloqueados no supusieron ningún problema, pero se llegó a la conclusión de que estas comprobaciones se deberían haber creado en el servidor y que fuera este el que comprobara si se cumplían las condiciones necesarias para añadir un nuevo logro a un usuario o no. Como esto requeriría editar las llamadas y añadir bastante código se añadirá como trabajo futuro más adelante en este documento. Para comprobarlo se ejecuta en el menú de la aplicación una serie de condiciones y cada vez que se accede a él se realizan una serie de comprobaciones y si se cumplen los requisitos se ejecutan las llamadas para añadir un nuevo logro. El servidor se encarga de añadir ese logro o no dependiendo de si ya se ha añadido anteriormente. En cuanto a la vista de logros ha sido necesario crearla (ver Figura B.5 junto con un la vista de un item de logro. Este item se usa como elemento del listado de logros. Figura B.5: Vista de la lista de logros desbloqueados de un usuario de CoP Por último, se añadió la llamada modify, que permite modificar los datos de un usuario. Para poder acceder a esta nueva pantalla se ha añadido un botón a la foto de perfil del usuario y pulsado se accede a una vista similar a la del registro, que permite reescribir los campos que se quieren editar. Esta vista ha sido reutilizada de la pantalla del registro y se han editado u bloqueado los campos que no pueden ser editados como el nombre del usuarios (ver Figura B.6). 108 Figura B.6: Vista de modificación de los datos del perfil de un usuario de CoP 110 Apéndice C Resultados del test de usabilidad A continuación, se muestran los resultados obtenidos por los 2 usuarios en en las 2 tareas del test de usabilidad. C.1. Tarea 1. Usuario 1 En la Tabla C.1, Tabla C.2, Tabla C.3, Tabla C.4, Tabla C.5, Tabla C.6 y Tabla C.7 se muestran los resultados del usuario 1 al realizar la tarea 1 explicada en el apartado anterior. Subtarea Registro en la aplicación ¿Completado? Sí Valoración 10 Descripción El usuario debe acceder a la aplicación y registrarse en ella introduciendo sus datos de usuario Métricas tiempo dedicado a realizar la Subtarea en segundos: 30s toques para completar la acción (necesarios 7): 7 errores: 0 Observaciones - Tabla C.1: Tarea 1. Usuario 1 Cuando el usuario terminó la tarea se pasó a realizar las preguntas. Las respuestas obtenidas fueron: ¿La interfaz le ha parecido intuitiva? Sí ¿En algún momento no ha sabido que hacer? No ¿Los tamaños de letras e iconos le parecen adecuados? Sí ¿Desea añadir algún comentario más? No 111 C.1. Tarea 1. Usuario 1 Subtarea Acceder a la pantalla de oponentes ¿Completado? Sí Valoración 10 Descripción El usuario debe pulsar en el botón Juega para ver la lista de oponentes que escoger Métricas tiempo dedicado a realizar la Subtarea en segundos: 5s toques para completar la acción (necesarios 1): 1 errores: 0 Observaciones - Tabla C.2: Tarea 1. Usuario 1 Subtarea Seleccionar y aceptar los oponentes seleccionados ¿Completado? Sí Valoración 10 Descripción El usuario debe seleccionar 4 oponentes y aceptar la lista de oponentes para pasar a la siguiente pantalla Métricas tiempo dedicado a realizar la Subtarea en segundos: 5s toques para completar la acción (necesarios 5): 5 errores: 0 Observaciones - Tabla C.3: Tarea 1. Usuario 1 Subtarea Crear partida por turnos ¿Completado? Sí Valoración 10 Descripción El usuario debe seleccionar una partida por turnos e iniciar la partida Métricas tiempo dedicado a realizar la Subtarea en segundos: 7s toques para completar la acción (necesarios 2): 2 errores: 0 Observaciones - Tabla C.4: Tarea 1. Usuario 1 112 Resultados del test de usabilidad Subtarea Jugar partida ¿Completado? Sí Valoración 10 Descripción El usuario debe jugar la partida creada hasta que esta finalice Métricas tiempo dedicado a realizar la Subtarea en segundos: 125s toques para completar la acción (pueden variar en función de las intentos): 15 errores: 2 Observaciones - Tabla C.5: Tarea 1. Usuario 1 Subtarea Volver al menú ¿Completado? Sí Valoración 10 Descripción El usuario debe volver al menú principal una vez haya finalizado la partida Métricas tiempo dedicado a realizar la Subtarea en segundos: 3s toques para completar la acción (necesarios 1): 1 errores: 0 Observaciones - Tabla C.6: Tarea 1. Usuario 1 Subtarea Ver resultados ¿Completado? Sí Valoración 10 Descripción El usuario debe acceder a las partidas pendientes y ver la última partida que jugó Métricas tiempo dedicado a realizar la Subtarea en segundos: 2s toques para completar la acción (necesarios 2): 2 errores: 0 Observaciones - Tabla C.7: Tarea 1. Usuario 1 C.2. Tarea 1. Usuario 2 En la Tabla C.8, Tabla C.9, Tabla C.10, Tabla C.11, Tabla C.12, Tabla C.13 y Tabla C.14 se muestran los resultados del usuario 2 al realizar la tarea 1 explicada en el apartado anterior. 113 C.2. Tarea 1. Usuario 2 Subtarea Registro en la aplicación ¿Completado? Sí Valoración 10 Descripción El usuario debe acceder a la aplicación y registrarse en ella introduciendo sus datos de usuario Métricas tiempo dedicado a realizar la Subtarea en segundos: 50s toques para completar la acción (necesarios 7): 9 errores: 0 (los toques extra fueron para borrar datos incorrectos) Observaciones - Tabla C.8: Tarea 1. Usuario 2 Subtarea Acceder a la pantalla de oponentes ¿Completado? Sí Valoración 10 Descripción El usuario debe pulsar en el botón Juega para ver la lista de oponentes que escoger Métricas tiempo dedicado a realizar la Subtarea en segundos: 8s toques para completar la acción (necesarios 1): 1 errores: 0 Observaciones - Tabla C.9: Tarea 1. Usuario 2 Subtarea Seleccionar y aceptar los oponentes seleccionados ¿Completado? Sí Valoración 10 Descripción El usuario debe seleccionar 4 oponentes y aceptar la lista de oponentes para pasar a la siguiente pantalla Métricas tiempo dedicado a realizar la Subtarea en segundos: 9s toques para completar la acción (necesarios 5): 6 errores: 0 Observaciones - Tabla C.10: Tarea 1. Usuario 2 Cuando el usuario terminó la tarea se pasó a realizar las preguntas. Las respuestas obtenidas fueron: 114 Resultados del test de usabilidad Subtarea Crear partida por turnos ¿Completado? Sí Valoración 10 Descripción El usuario debe seleccionar una partida por turnos e iniciar la partida Métricas tiempo dedicado a realizar la Subtarea en segundos: 8s toques para completar la acción (necesarios 2): 2 errores: 0 Observaciones - Tabla C.11: Tarea 1. Usuario 2 Subtarea Jugar partida ¿Completado? Sí Valoración 10 Descripción El usuario debe jugar la partida creada hasta que esta finalice Métricas tiempo dedicado a realizar la Subtarea en segundos: 189s toques para completar la acción (pueden variar en función de las intentos): 21 errores: 3 Observaciones - Tabla C.12: Tarea 1. Usuario 2 Subtarea Volver al menú ¿Completado? Sí Valoración 10 Descripción El usuario debe volver al menú principal una vez haya finalizado la partida Métricas tiempo dedicado a realizar la Subtarea en segundos: 5s toques para completar la acción (necesarios 1): 1 errores: 0 Observaciones - Tabla C.13: Tarea 1. Usuario 2 ¿La interfaz le ha parecido intuitiva? Sí 115 D.1. Despliegue del servidor 17. Comprobar que todo está bien con ”sudo nginx -t”. 18. Reiniciar Nginx con ”sudo systemctl restart nginx”. 19. Ejecutar ”sudo nano /etc/nginx/sites-available/default”. 20. Sustituir el ”location” anterior por: 1location / { 2proxy_pass http :// localhost :3001; 3proxy_http_version 1.1; 4proxy_set_header Upgrade $http_upgrade ; 5proxy_set_header Connection ’upgrade ’; 6proxy_set_header Host $host; 7proxy_cache_bypass $http_upgrade ; 8} Donde 3001 es el puerto en el que escucha la aplicación y que ha sido configurado en cop/cop/- bin/www. Instalación y configuración de PM2 1. Situarse en el directorio cop/cop del proyecto. 2. Instalar PM2 mediante ”sudo npm install pm2@latest -g”. 3. Iniciar la aplicación mediante ”pm2 start bin/www”. 4. Ejecutar ”pm2 startup systemd”. 5. Usar el último comando que se ha mostrado en pantalla como respuesta a la ejecución del comando anterior. Este debe ser ”sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u usuario –hp /home/usuario” cambiando ”usuario” por el nombre del usuario propio de cada máquina. 6. Guardar cambios con ”pm2 save”. 7. Iniciar el servicio con ”sudo systemctl start pm2-usuario”. 8. Reiniciar si existe algún fallo con ”sudo reboot”. 9. Comprobar el estado del servicio con ”systemctl status pm2-usuario”. 10. A tener en cuenta. Podemos reiniciar la aplicación con ”pm2 restart app_name_or_id” cada vez que se realice un cambio en sus ficheros. 11. Reiniciar Nginx con ”sudo systemctl restart nginx”. 12. Nuestra aplicación ya se encuentra corriendo. 122 Manual de despliegue Para aclarar posibles dudas sobre los diferentes puertos usados cabe destacar que un ordenador recibe peticiones http por el puerto 80. Como nuestra máquina es virtual, su puerto 80 es en realidad el puerto 65232, por lo tanto, si deseamos comunicarnos con ella necesitamos usar el puerto 65232. Una vez Nginx recibe esa información, la mandará a nuestra aplicación, que está escuchando en el puerto 3001 (dicho puerto no es accesible desde fuera). Una vez está todo configurado, podemos realizar llamadas a la API a través de la aplicación o de programas como Postman. Una posible llamada sería ”http://157.88.124.247:65232/register”. Instalación y configuración de phpMyAdmin Para la realización de este manual se ha utilizado la ayuda de [72]. 1. Abrir una terminal y usar el siguiente comando "sudo apt update". 2. Instalar phpMyAmdin mediante ”sudo apt install phpmyadmin”. 3. En la instalación no seleccionar ni apache2 ni ligthtpd. Estamos usando Nginx pero no existe ninguna opción por lo que lo dejamos vacío y le damos a ”ok”. 4. En cuanto a la configuración de la base de datos con dbconfig-common diremos "Yes". 5. Por último, solo hay que introducir una contraseña para el usuario phpmyadmin. No debe ser sencilla, ya que esto va a quedar expuesto a la red. 6. Como vamos a seguir usando el usuario root para acceder a la base de datos debemos cambiar su contraseña por otra mediante .ALTER USER ’root’@’localhost’ IDENTIFIED BY ’New-PasswordHere’;". A continuación, ejecutar "FLUSH PRIVILEGES;". 7. Editar la contraseña almacenada en el archivo cop/cop/config/config.json para que sea la misma que acabamos de poner para el usuario root de mysql. 8. Ejecutar "sudo vim /etc/nginx/snippets/phpmyadmin.conf". 9. Copiar el siguiente contenido al archivo abierto. 1location / phpmyadmin { 2root / usr / share /; 3index index .php index . html index . htm ; 4location ~ ^/ phpmyadmin /(.+\. php)$ { 5try_files $uri =404; 6root / usr / share /; 7fa stcgi_pass unix :/ run / php / php7 .2 - fpm . sock ; 8fastcgi_index index . php ; 9fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name ; 10 include / etc / nginx / fastcgi_params ; 11 } 12 13 location ~* ^/ phpmyadmin /(.+\.( jpg| jpeg |gif | css | png | js | ico | html | xml | txt ))$ { 14 root / usr / share /; 15 } 16 } 123 D.2. Despliegue del cliente 10. Salir y guardar el fichero creado. 11. Ejecutar "sudo vim /etc/nginx/sites-available/default 2 copiar la siguiente línea encima del location ïnclude snippets/phpmyadmin.conf;". D.2. Despliegue del cliente Antes de instalar la aplicación necesitamos un dispositivo Android con versión Android 8 (API 26) o superior y disponer de acceso a internet. Si cumplimos estos requisitos solo deberemos descargar la aplicación (CoP.apk) a la memoria de nuestro dispositivo. Una vez hecho esto buscaremos en la memoria de nuestro dispositivo (generalmente la aplicación se encontrará en ”descargas”) y pulsaremos sobre nuestra aplicación. Al ser una aplicación externa a la Play Store nos pedirá permisos para poder instalar dichas aplicaciones. Concedemos los permisos e instalamos la aplicación. Hecho esto la aplicación estará lista para iniciarla en nuestro dispositivo. 124 Apéndice E Pruebas realizadas en la aplicación de prueba de llamadas P_I2_1 Comprobar conexión con la API Precondición Tener conexión a internet Descripción Realizar una llamada cualquiera a la API (register por ejemplo) y obtener algún tipo de resultado de vuelta Resultado esperado Tras el registro, se espera un mensaje en formato json desde la API que indique si se ha podido registrar el usuario Resultado Correcto Tabla E.1: Prueba P_I2_1 P_I2_2 Register Precondición Tener conexión a internet Descripción Registrar un nuevo usuario en la API y comprobar resultado correcto Resultado esperado Tras el registro, se espera un json de la API que indica que ha sido correcto Resultado Correcto Tabla E.2: Prueba P_I2_2 P_I2_3 Login Precondición Haber resgistrado al usuario anteriormente Descripción Iniciar sesión con un usuario registrado y recibir mensaje json de confirmación Resultado esperado Tras el login, se espera un json de la API que indica que ’Los tokens han sido actualizados’ Resultado Correcto Tabla E.3: Prueba P_I2_3 125 P_I2_4 RefreshToken Precondición Haber iniciado sesión con el usuario Descripción Realizar llamada refreshToken para generar token nuevo Resultado esperado Tras la llamada, se espera un json de la API que indica que ’Operación realizada con éxito’ y que contiene el nuevo Token Resultado Correcto Tabla E.4: Prueba P_I2_4 P_I2_5 ListChallenges Precondición Haber iniciado sesión con el usuario Descripción Realizar llamada listChallenges para obtener todos los challenges de un usuario Resultado esperado Tras la llamada, se espera un json de la API que indica que ’Operación realizada con éxito’ y una lista con todos los challenge Resultado Correcto Tabla E.5: Prueba P_I2_5 P_I2_6 UserData Precondición Haber iniciado sesión con el usuario Descripción Realizar llamada userData para obtener todos los datos del usuario que ha iniciado sesión anteriormente Resultado esperado Tras la llamada, se espera un json de la API que indica que ’Operación realizada con éxito’ y que contiene la información del usuario Resultado Correcto Tabla E.6: Prueba P_I2_6 P_I2_7 Modify y userData Precondición Haber iniciado sesión con el usuario Descripción Realizar llamada modify para editar los datos del usuario que ha iniciado sesión anteriormente Resultado esperado Tras la llamada, se espera un json de la API que indica que ’Operación realizada con éxito’. Pinchando en la llamda userData podremos ver los datos del usuario tras haber sido editados Resultado Correcto Tabla E.7: Prueba P_I2_7 Pruebas realizadas en la aplicación de prueba de llamadas P_I2_8 Ranking Precondición Haber iniciado sesión con el usuario Descripción Realizar llamada ranking para ver el ranking de jugadores en función de su puntuación total Resultado esperado Tras la llamada, se espera un json de la API que indica que ’Operación realizada con éxito’ y una lista con todos los nicks de los jugadores y sus puntuaciones Resultado Correcto Tabla E.8: Prueba P_I2_8 P_I2_9 AddAchievement Precondición Haber iniciado sesión con el usuario Descripción Realizar llamada addAchievement añadir un logro al usuario Resultado esperado Tras la llamada, se espera un json de la API que indica que ’Operación realizada con éxito’ Resultado Correcto Tabla E.9: Prueba P_I2_9 P_I2_10 ShowAchievement Precondición Haber iniciado sesión con el usuario Descripción Realizar llamada showAchievement para ver los logros del usuario Resultado esperado Tras la llamada, se espera un json de la API que indica que ’Operación realizada con éxito’ y una lista que contiene los logros obtenidos por el usuario Resultado Correcto Tabla E.10: Prueba P_I2_10 P_I2_11 Opponents Precondición Haber iniciado sesión con el usuario Descripción Realizar llamada opponents para obtener los oponentes necesarios para crear una partida Resultado esperado Tras la llamada, se espera un json de la API que indica que ’Operación realizada con éxito’ y una lista que contiene oponentes Resultado Correcto Tabla E.11: Prueba P_I2_11 127 P_I2_12 CreateChallenge Precondición Haber buscado oponentes Descripción Realizar llamada createChallenge para una nueva partida Resultado esperado Tras la llamada, se espera un json de la API que indica que ’Operación realizada con éxito’ y un id que contiene el identificador de la partida creada Resultado Correcto Tabla E.12: Prueba P_I2_12 P_I2_13 InfoChallenge Precondición Haber creado una partida nueva Descripción Realizar llamada infoChallenge para ver los detalles de la última partida creada Resultado esperado Tras la llamada, se espera un json de la API que indica que ’Operación realizada con éxito’ y toda la información referente a la partida creada anteriormente Resultado Correcto Tabla E.13: Prueba P_I2_13 P_I2_14 StartMatch Precondición Haber creado una partida nueva Descripción Realizar llamada startMatch para jugar el turno en la partida creada anteriormente Resultado esperado Tras la llamada, se espera un json de la API que indica que ’Operación realizada con éxito’ y que contiene el campo ’Play’: true Resultado Correcto Tabla E.14: Prueba P_I2_14 P_I2_15 FinishMatch Precondición Haber jugado el turno de la partida mediante la llamada startMatch Descripción Realizar llamada finishMatch para finalizar el turno jugado en la partida creada anteriormente Resultado esperado Tras la llamada, se espera un json de la API que indica que ’Operación realizada con éxito’ y que contiene el campo ’Play’: true junto con el mensaje ’Puntuación base actualizada’ Resultado Correcto Tabla E.15: Prueba P_I2_15 128 Pruebas realizadas en la aplicación de prueba de llamadas P_I2_16 Jugar partida completa Precondición Tener conexión a internet Descripción Jugar una partida completa mediante la prueba creada en la aplicación Resultado esperado Tras la ejecutar la prueba, se espera un json de la API que indica que ’Operación realizada con éxito’ y que contiene el campo ’Play’: true junto con el mensaje ’Partida finalizada, actualización de la puntuación total’. Comprobar que el ranking ha sido editado y los jugadores han ganado puntos Resultado Correcto Tabla E.16: Prueba P_I2_16 P_I2_17 UserData sin login Precondición Tener conexión a internet Descripción Ejecutar la llamada userData sin haber iniciado sesión con un usuario Resultado esperado Tras la ejecutar la prueba, se espera un json de la API que indica que ’No se ha encontrado ningún token’ Resultado Correcto Tabla E.17: Prueba P_I2_17 P_I2_18 Opponents sin login Precondición Tener conexión a internet Descripción Ejecutar la llamada opponents sin haber iniciado sesión con un usuario Resultado esperado Tras la ejecutar la prueba, se espera un json de la API que indica que ’No se ha encontrado ningún token’ Resultado Correcto Tabla E.18: Prueba P_I2_18 P_I2_19 CreateChallenge sin login Precondición Tener conexión a internet Descripción Ejecutar la llamada createChallenge sin haber iniciado sesión con un usuario Resultado esperado Tras la ejecutar la prueba, se espera un json de la API que indica que ’No se puede crear partida sin oponentes’ Resultado Correcto Tabla E.19: Prueba P_I2_19 129 130 Apéndice F Manual de uso El primer paso tras iniciar la aplicación es iniciar sesión en la aplicación (ver Figura F.1). Si se tiene una cuenta ya creada solo habrá que añadir el nick y contraseña de usuario. Si no se ha creado aún una cuenta será necesario registrarse. Para ello habrá que pulsar sobre el botón ”Regístrate” e introducir los datos que se nos pide (nick, mail, contraseña y seleccionar una imagen de perfil) (ver Figura F.1). En ambos casos, una vez la sesión se ha iniciado, se nos pedirá que aceptemos los términos de servicio y accederemos al menú. Para poder realizar acciones se nos pedirá que aceptemos los permisos que se requieren (audio y almacenamiento). Figura F.1: Login, registro y menú Una vez en el menú de la aplicación (ver Figura F.1) podemos acceder a la mayoría de su funcionalidad. Podemos modificar el perfil si pulsamos en la imagen de perfil podremos modificar nuestro mail, 131