scieee AI-readable full text Open interactive document viewer

Desarrollo de una aplicación educativa multiplataforma para el entrenamiento de la pronunciación de idiomas

Gamazo Ferrero, Antonio

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 Desarrollo de una aplicación educativa multiplataforma para el entrenamiento de la pronunciación de idiomas Autor: Antonio Gamazo Ferrero Escuela de Ingeniería Informática TRABAJO FIN DE GRADO Grado en Ingeniería Informática Mención en Ingeniería de Software Desarrollo de una aplicación educativa multiplataforma para el entrenamiento de la pronunciación de idiomas Autor: Antonio Gamazo Ferrero Tutores: Cristian Tejedor García Mario Corrales Astorgano A mi familia que me ha apoyado siempre. Agradecimientos A mis tutores, Cristian Tejedor García y Mario Corrales Astorgano, por su ayuda y dedicación durante todo el desarrollo del proyecto. A mis compañeros de carrera, con los que he compartido tantas horas de estudio y trabajos, sin ellos no habría sido lo mismo. Por último, a mi familia, que me ha apoyado en este trayecto y en todos. Gracias. Resumen En la última década hemos visto como los teléfonos móviles han pasado a ser el centro de nuestras vidas. Las aplicaciones móviles nos facilitan todo tipo utilidades en nuestros dispositivos, como las aplicaciones educativas orientadas al aprendizaje de diferentes habilidades. También, en los últimos años se ha hecho popular el uso de sistemas de sistemas de entrenamiento de la pronunciación (computerassisted pronunciation training, CAPT), con herramientas que incluyen síntesis de voz (text-to-speech, TTS) o reconocimiento del habla (automatic speech recognition, ASR). Gracias a la gran evolución en materia de inteligencia artificial y aprendizaje automático, estos sistemas son cada vez más precisos. Este proyecto, es una versión evolucionada de dos proyectos anteriores, TipTopTalk! y Clash of Pronunciations, dos aplicaciones móviles para el entrenamiento de la pronunciación extranjera. Éstas se basan en el uso de pares mínimos en ejercicios de entrenamiento diseñados por expertos en fonética. El objetivo principal de este proyecto es unir los conceptos y métodos de entrenamiento de los dos proyectos anteriores en una aplicación multiplataforma (móvil, web y escritorio) educativa, que permita expandir su funcionalidad de manera sencilla, independientemente de las particularidades de cada plataforma. Índice de figuras 1.1. Apariencia de la aplicación TipTopTalk! . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.2. Apariencia de la aplicación Clash of Pronunciations. . . . . . . . . . . . . . . . . . . . . . 4 1.3. Apariencia de la aplicación Duolingo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.4. Apariencia de la aplicación Babbel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.5.LogodeNode.js.......................................... 6 1.6.LogodeNPM. .......................................... 6 1.7.LogodeExpress.js. ....................................... 7 1.8.LogodeReactNative....................................... 7 1.9. Proceso de compilación de una aplicación React Native. . . . . . . . . . . . . . . . . . . . 8 1.10.LogodeRedux........................................... 8 1.11.ArquitecturaFLUX[26]...................................... 9 1.12.LogodeExpo. .......................................... 10 1.13.LogodeMongoDB......................................... 10 1.14.Equivalencia de términos de una base de datos SQL y MongoDB . . . . . . . . . . . . . . 10 1.15.LogodeSwagger. ........................................ 11 1.16.LogodePostman. ........................................ 11 1.17.Esquema de un desarrollo iterativo e incremental [35] . . . . . . . . . . . . . . . . . . . . 13 2.1. Distribución de las iteraciones según sus semanas de desarrollo. . . . . . . . . . . . . . . 16 2.2. Comparación de la estimación original con la duración real. . . . . . . . . . . . . . . . . . 27 3.1.ReactNativeVSIonic....................................... 34 3.2. Pantalla de inicio de sesión. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3.3. Pantalla de selección de lenguaje. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3.4. Pantalla de selección de sonido. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 3.5.Pantallademenúprincipal. ................................... 37 3.6. Pantalla de modo de juego exposición. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 3.7. Pantalla de modo de juego Percepción. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 3.8. Pantalla de modo de juego pronunciación. . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3.9. Pantalla de modo de juego mixto. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3.10.Pantalla de modo de juego Memoria. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 3.11.Pantalla de modo de juego Puzzle. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 3.12.Pantalla de modo de juego Teoría. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.13.Pantalla de puntuación final de una partida. . . . . . . . . . . . . . . . . . . . . . . . . . . 41 V ÍNDICE DE FIGURAS 3.14.Pantalla de historial de puntuaciones. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 3.15.Pantalladeopciones. ...................................... 42 3.16.Pantalladeregistro. ....................................... 43 3.17.Pantalla de selección de dificultad. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 4.1.Diagramadedominio. ...................................... 55 4.2. Diagrama de actividad de HU01. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 4.3. Diagrama de actividad de HU02. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 4.4. Diagrama de actividad de HU03. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 4.5. Diagrama de actividad de HU04. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 4.6. Diagrama de actividad de HU05. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 4.7. Diagrama de actividad de HU06. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 4.8. Diagrama de actividad de HU07. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 4.9. Diagrama de actividad de HU08. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 4.10.Diagrama de actividad de HU09. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 4.11.Diagrama de actividad de HU10. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 4.12.Diagrama de actividad de HU11. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 4.13.Diagrama de actividad de HU12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 4.14.Diagrama de actividad de HU13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 4.15.Diagrama de actividad modo de juego Exposición. . . . . . . . . . . . . . . . . . . . . . . 77 4.16.Diagrama de actividad modo de juego Percepción. . . . . . . . . . . . . . . . . . . . . . . 78 4.17.Diagrama de actividad modo de juego Pronunciación. . . . . . . . . . . . . . . . . . . . . 79 4.18.Diagrama de actividad modo de juego Mixto. . . . . . . . . . . . . . . . . . . . . . . . . . 80 4.19.Diagrama de actividad modo de juego Memoria. . . . . . . . . . . . . . . . . . . . . . . . 81 4.20.Diagrama de actividad modo de juego Puzzle. . . . . . . . . . . . . . . . . . . . . . . . . 82 4.21.Diagrama de actividad modo de juego Teoría. . . . . . . . . . . . . . . . . . . . . . . . . . 83 4.22.Estructura un proyecto Node. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 4.23.Estructura un proyecto Expo React-Native. . . . . . . . . . . . . . . . . . . . . . . . . . . 86 4.24.Diagrama de modelos de datos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 4.25.Diagramadepaquetes. ..................................... 89 4.26.Diagramadedespliegue. .................................... 91 5.1. Pantallas de login y registro. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 5.2. Pantallas del modo de juego mixto. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 B.1.Paso1. ..............................................129 B.2.Paso2. ..............................................130 B.3.Paso3. ..............................................130 B.4.Paso4. ..............................................130 B.5.Paso5. ..............................................131 B.6.Paso6. ..............................................131 B.7.Paso7. ..............................................131 B.8.Paso8. ..............................................132 B.9.Paso9. ..............................................132 VI ÍNDICE DE FIGURAS C.1. Estructura API /masters/languages. ..............................134 C.2. Estructura API /masters/countries. ...............................134 C.3. Estructura API /users. ......................................135 C.4. Estructura API /users/login....................................136 C.5. Estructura API /users/token....................................137 C.6. Estructura API /users/me.....................................137 C.7. Estructura API /users/logout. ..................................138 C.8. Estructura API /users/logoutall..................................138 C.9. Estructura API /users/log.....................................139 C.10.Estructura API /languages/{idLanguges}/sounds/{idSound}..................140 C.11.Estructura API /languages. ...................................141 C.12.Estructura API /languages/{idLanguges}/sounds........................142 C.13.Estructura API /languages/{idLanguges}/sounds/{idSound}/memory.............143 C.14.Estructura API /languages/{idLanguges}/sounds/{idSound}/puzzle..............144 C.15.Estructura API /languages/{idSound}/link/{languages}.....................145 C.16.Estructura API /sounds. .....................................146 VII Índice de tablas 2.1. Ordenador utilizado en desarrollo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.2. Monitor utilizado en desarrollo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.3. Smartphone utilizado en desarrollo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.4. iPad utilizado en desarrollo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.5. Servidor utilizado para despliegue. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.6.Tabladeriesgos.......................................... 21 2.7. Tabla de planes de acción para los riesgos. . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.8. Tabla de estimación de costes aplicados al espacio de trabajo. . . . . . . . . . . . . . . . 23 2.9. Tabla de estimación de costes del hardware. . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.10.Tabla de estimación de costes de software y servicios. . . . . . . . . . . . . . . . . . . . . 25 2.11.Tabla de estimación de costes totales. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 3.1. Tabla de requisitos funcionales. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 3.2. Tabla de requisitos no funcionales. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.3. Tabla de requisitos de información. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 4.1.HistoriadeusuarioHU01..................................... 50 4.2.HistoriadeusuarioHU02..................................... 50 4.3.HistoriadeusuarioHU03..................................... 50 4.4.HistoriadeusuarioHU04..................................... 51 4.5.HistoriadeusuarioHU05..................................... 51 4.6.HistoriadeusuarioHU06..................................... 51 4.7.HistoriadeusuarioHU07..................................... 52 4.8.HistoriadeusuarioHU08..................................... 52 4.9.HistoriadeusuarioHU09..................................... 52 4.10.HistoriadeusuarioHU10..................................... 53 4.11.HistoriadeusuarioHU11..................................... 53 4.12.HistoriadeusuarioHU012. ................................... 53 4.13.HistoriadeusuarioHU13..................................... 54 4.14.EntidadWord............................................ 55 4.15.EntidadUser............................................ 56 4.16.EntidadGame. .......................................... 56 4.17.EntidadRecord. ......................................... 56 4.18.EntidadResult........................................... 57 IX ÍNDICE DE TABLAS 4.19.EntidadDailyLog.......................................... 57 4.20.EntidadLanguage......................................... 57 4.21.EntidadTask............................................ 58 4.22.EntidadTTS. ........................................... 58 4.23.EntidadASR............................................ 58 4.24.EntidadFeedback......................................... 59 4.25.EntidadExposure. ........................................ 59 4.26.EntidadPerception. ....................................... 59 4.27.EntidadPronunciation....................................... 59 4.28.EntidadMixed. .......................................... 60 4.29.EntidadPuzzle........................................... 60 4.30.EntidadMemory.......................................... 60 4.31.EntidadTheory........................................... 60 4.32.EntidadAudio. .......................................... 61 4.33.EntidadVideo. .......................................... 61 5.1.PruebaCP01............................................ 93 5.2.PruebaCP02............................................ 94 5.3.PruebaCP03............................................ 94 5.4.PruebaCP04............................................ 94 5.5.PruebaCP05............................................ 94 5.6.PruebaCP06............................................ 95 5.7.PruebaCP07............................................ 95 5.8.PruebaCP08............................................ 95 5.9.PruebaCP09............................................ 96 5.10.PruebaCP10............................................ 96 5.11.PruebaCP11............................................ 97 5.12.PruebaC12. ........................................... 97 5.13.PruebaCP13............................................ 97 5.14.PruebaCP14............................................ 97 5.15.PruebaCP15............................................ 98 5.16.PruebaCP16............................................ 98 5.17.PruebaCP17............................................ 98 5.18.PruebaCP18............................................ 99 5.19.PruebaCP19............................................ 99 5.20.Plantilla utilizada para los test de usabilidad. . . . . . . . . . . . . . . . . . . . . . . . . . 100 5.21.Perfilesdeusuario.........................................100 X Capítulo 1 Introducción 1.1. Contexto En un mundo en el que cada vez los dispositivos móviles han pasado a estar presentes en prácticamente todos los ámbitos de nuestro día a día, parece razonable, que cualquier tipo de aplicación que se quiera desarrollar tenga presencia en este ecosistema. Concretamente, en el apartado de juegos, las plataformas móviles ya superan en facturación a otras como PC o consolas [1]. Además, con las nuevas generaciones inmersas en una nueva era digital, las aplicaciones educativas para dispositivos móviles también están en auge [2]. Este proyecto surge de la propuesta de Trabajo Fin de Grado (TFG) publicada en la web de ofertas de TFG [3] de la Escuela de Ingeniería Informática de Valladolid por Cristian Tejedor García, "Desarrollo de aplicación multiplataforma para juego serio multijugador". El objetivo de ésta es construir una aplicación multiplataforma con la que se pueda practicar la pronunciación a la hora de aprender un idioma extranjero. Este trabajo es una propuesta evolucionada de la aplicación TipTopTalk! del Trabajo Fin de Máster (TFM) de Cristian Tejedor García [4] y de Clash of Pronunciations del TFG de Rafael Sillero Navajas [5]. Ambas siguen la premisa de ser, mediante el uso de sistemas de reconocimiento automático del habla (Automatic Speech Recognition, ASR) y sintetizado de la voz (Text-To-Speech, TTS), un juego serio que, gracias a la gamificación [6] y a los sistemas mencionados anteriormente, faciliten la tarea de aprender y practicar la pronunciación de un idioma extranjero. 1.2. Motivación Los cambios constantes en la tecnología de desarrollo de software de aplicaciones móviles implican un mantenimiento constante de las aplicaciones desarrolladas. En el caso de las aplicaciones TipTopTalk! y Clash of Pronunciations, las restricciones y cambios de Google Play Games durante los últimos cinco años han implicado una reducción de la funcionalidad original implementada por falta de recursos 1 1.3. Estado de la cuestión y mantenimiento. El principal motivo por el que se propone este proyecto es aprovechar las ventajas de un desarrollo multiplataforma para fabricar una aplicación, que con el mismo código, sea utilizable en distintos tipos de plataformas, móvil, web y escritorio. Para equipos de desarrollo pequeños es un problema el tener que desarrollar de forma nativa para diferentes entornos, dado que supone mucho esfuerzo tener un desarrollador especializado en cada ámbito. También resulta complicado encontrar alguien con conocimientos suficientes para que se encargue de todos los desarrollos, y si fuera el caso, le llevaría demasiado tiempo. Lo que se busca con el desarrollo multiplataforma es ahorrar tiempo y costes, de manera que con un desarrollador con conocimientos en JavaScript, HTML y CSS, se pueda abarcar un desarrollar para, al menos, las plataformas más utilizadas a día de hoy. Por otra parte, se busca estudiar las posibilidades que ofrece el desarrollo multiplataforma, ya que, si bien es verdad que es una herramienta muy útil, es sabido que tiene ciertas limitaciones. Por lo tanto, otra motivación para ejecutar este proyecto es descubrir estas limitaciones o carencias que pueda tener el desarrollo de aplicaciones con tecnologías multiplataforma. 1.3. Estado de la cuestión 1.3.1. TipTopTalk! Como se ha comentado en la introducción, esta aplicación fue desarrollada por Cristian Tejedor García [4] durante los años 2015 y 2016, y tiene el objetivo de facilitar y hacer más interesante la práctica de pronunciación de un idioma extranjero. Es una aplicación Android para dispositivos móviles y educativa que consiste en un juego serio para la mejora de la pronunciación de un idioma extranjero (inglés, español y chino, entre otros). Integra actividades de entrenamiento en un ciclo de exposición, discriminación y pronunciación. Cuando los usuarios realizan dichas actividades, obtienen puntos y trofeos, y se ven reflejados en rankings. Utilizando sistemas conversión de texto a voz y de reconocimiento de voz, se consigue que un usuario pueda escuchar cómo se pronuncia correctamente una palabra y posteriormente pronunciarla en voz alta para que el smartphone la interprete y pueda comprobar si esta es correcta. El sistema de aprendizaje consiste en la comparación mediante pares mínimos de los fonemas de dos palabras [7]. Esto es, dos palabras que sólo difieren en un fonema, que es el que se quiere practicar, por ejemplo, cede ysede. Mediante la escucha, la grabación y la repetición se consigue llegar a diferenciarlos. 2 Introducción Figura 1.1: Apariencia de la aplicación TipTopTalk! 1.3.2. Clash of Pronunciations Aplicación móvil Android desarrollada por Rafael Sillero Navajas como TFG [5], con el objetivo de añadir la funcionalidad multijugador y otros aspectos sociales mediante el uso de la plataforma Google Play Services a TipTopTalk!. Cuando esta plataforma dejó de dar servicio de tipo multijugador se encontró la necesidad de crear una backend que la sustituyera. Éste corrió a cargo de Andrés de la Maza Valles en su TFG en verano del 2020 [8]. Como se puede ver en la figura 1.2, hay disponibles cuatro modos de práctica, los cuales también son incluidos en este proyecto, junto a nuevos modos. 1.3.3. Duolingo La aplicación de práctica y aprendizaje de idiomas más usada, con más de 100 millones de descargas en Google Play [9].Su funcionalidad básica es gratuita, siendo posible ser ampliada mediante subscripción de pago. Usa elementos de gamificación para hacerla más atractiva. Por ejemplo, se pierden vidas cuando hay una respuesta incorrecta y también se utiliza un sistema de niveles, que a parte de marcar el nivel del jugador, sirven para aumentar las ganas de autosuperación del mismo. Como se puede apreciar en la figura 1.3, consta de una interfaz muy minimalista y accesible para todo tipo de públicos. Esta se centra más en el aprendizaje de un idioma a modo general, que en la pronunciación en particular. No dispone de demasiados ejercicios para practicar la pronunciación y que den una retroalimentación sobre esta. 3 1.3. Estado de la cuestión 1.3.5.6. Expo Figura 1.12: Logo de Expo. Expo [27] es un framework que añade una capa sobre las API de React Native para facilitar el desarrollo de aplicaciones nativas, proporcionando métodos para acceder a características nativas del sistema operativo objetivo, sin necesidad de utilizar código nativo. Esto lo hace a través del Expo SDK, y nos permite características propias de aplicaciones nativas sin necesidad de utilizar Android Studio o Xcode. Por otro lado, Expo también proporciona una forma de generar los paquetes de la aplicación desde la nube para poder subirlos directamente a las tiendas correspondientes. 1.3.5.7. MongoDB Figura 1.13: Logo de MongoDB. Mongo [28] es una base de datos NoSQL, orientada a documentos. Esto significa que a diferencia de las bases de datos convencionales, la información no se almacena en tablas, sino que se guardan en estructuras BSON. Esta es una especificación similar a JSON, lo cual la hace muy interesante combinada con un servidor escrito en JavaScript. . Figura 1.14: Equivalencia de términos de una base de datos SQL y MongoDB La principal ventaja de utilizar este tipo de bases de datos es que son semi estructuradas, lo que aporta cierta libertad sobre los datos que se van a guardar. En contra tienen el rendimiento, que siendo bueno, no llega a alcanzar a las bases de datos SQL en determinados tipos de consultas, por ejemplo, 10 Introducción las que usan uniones, ya que esta operación no se puede hacer directamente y hay que ingeniárselas para poder llevarla a cabo. 1.3.5.8. Swagger Figura 1.15: Logo de Swagger. Swagger [29] es una herramienta que se utiliza para documentar las llamadas a la API, exponiendo su descripción, parámetros de entrada y estructura de las respuestas esperadas. También permite probar las llamadas directamente desde el propio Swagger, algo que resulta muy útil cuando se trabaja en equipos. Otra característica interesante es, que si el Swagger no tuviera conexión con el servidor, por ejemplo durante un despliegue, este es capaz de generar mocks para falsear las respuestas. En el apéndice C está disponible el Swagger de este proyecto. 1.3.5.9. Postman Figura 1.16: Logo de Postman. Postman [30] es una herramienta muy útil para probar las llamadas a la API. Esto es una gran ventaja durante el desarrollo ya que no hace falta tener un cliente enviando peticiones al servidor, sino que el propio Postman actúa como cliente. Permite enviar peticiones con sus cabeceras, cuerpo y otros parámetros, mediante una interfaz muy sencilla e intuitiva. En este proyecto solo se ha utilizado para probar las llamadas durante su desarrollo, pero también es capaz de hacer otras tareas como automatizar pruebas y monitorizar el rendimiento de la API. También permite tener varios espacios de trabajo para diferentes proyectos. 1.3.5.10. Google TTS y STT Google Text-to-speech [31]: la síntesis de voz consiste en que un dispositivo reproduzca un texto de forma hablada. Gracias a tecnología de IA (inteligencia artificial) de Google y a su API, que expone esta utilidad, se consiguen reproducir textos con una voz muy natural. Este servicio está disponible en más de 40 idiomas. 11 1.4. Objetivos Google Speech-to-Text [32]: este, se podría decir que es el caso contrario. Esta API permite el reconocimiento de voz para ser procesado y convertido a texto. Gracias a la IA de Google y las técnicas de machine learning, este sistema cada vez es más preciso. Este servicio no solo devuelve la palabra que ha entendido, sino que devuelve una lista de posibles palabras reconocidas (tantas como se elija en la petición) acompañadas de un número de 0 a 1, que representa la probabilidad de que esa palabra sea la que se ha pronunciado. La combinación de ambas es la base para que un usuario pueda escuchar cómo se pronuncia una palabra, tratar de repetirla y recibir una retroalimentación de forma prácticamente instantánea. 1.4. Objetivos El objetivo general de el proyecto es, mediante un frontend y un backend, desarrollar una aplicación multiplataforma y una API para implementar un juego de mejora de la pronunciación de un idioma extranjero. Este objetivo principal se puede dividir en los siguientes objetivos particulares: Objetivo 1: diseñar la interfaz multiplataforma de las diferentes pantallas. Objetivo 2: desarrollar las funcionalidades necesarias para los modos de juego de la aplicación, integrando sistemas ASR y TTS. Objetivo 3: desarrollar una API con vistas a ser ampliada en el futuro. Al ser independientes cliente y servidor, se puede modificar uno sin afectar al otro. 1.5. Metodología Por la naturaleza del proyecto y el poco conocimiento de la tecnología se ha decidido aplicar un modelo iterativo e incremental [33], que brinda cierta flexibilidad en cuanto a cambios en los requisitos. En este caso, aplicar SCRUM [34], no parece demasiado realista al disponer de un solo desarrollador. Entre las ventajas de este modelo se encuentran las siguientes: el cliente final puede ver en cada iteración de una funcionalidad acabada, de esta manera se puede ver si el proyecto va por el camino deseado o hay que realizar algún cambio; menos gold-plating (requisitos innecesarios que piden los clientes); y, por último, este modelo permite que el proyecto sea abandonado temporalmente, lo cual, teniendo en cuenta la situación del estudiante, es una gran ventaja [33]. En la figura 1.17 se puede ver un esquema de cuáles son los pasos a seguir durante un desarrollo iterativo e incremental. En el capítulo 3 se habla en detalle de las acciones llevadas a cabo en cada iteración de este proyecto. 12 Introducción . Figura 1.17: Esquema de un desarrollo iterativo e incremental [35] 1.6. Estructura de la memoria Introducción: se expone el proyecto desde una perspectiva general, hablando del contexto, metodología empleada, objetivos a conseguir, tecnologías implicadas y la estructura de la memoria. Planificación: descripción y estimación de las iteraciones con sus tiempos de entrega, estimación del coste del proyecto y descripción de riesgos y planes de acción. Descripción de las iteraciones: descripción del trabajo realizado en cada una de las iteraciones. Estado final de la aplicación: diagramas de análisis y diseño con sus correspondientes aclaraciones. Pruebas: descripción de las pruebas realizadas. Test de integración, unitarios y de usabilidad. Conclusiones y trabajo futuro: conclusiones sacadas del proceso y posibles mejoras de cara al futuro. Apéndices: distintos documentos adicionales como el manual de instalación y despliegue, la estructura de la API REST (Swagger), los acrónimos y el contenido del fichero adjunto. Bibliografía: referencias a páginas web, libros o proyectos consultados a lo largo del desarrollo. 13 Capítulo 2 Planificación 2.1. Planificación inicial Para poder compatibilizar el horario con la situación del alumno de este TFG, con éste finalizando sus estudios y realizando las prácticas en empresa, se estableció al comienzo del proyecto un trabajo de 15 horas semanales desde principios de octubre hasta mediados de marzo, lo que sumaría un total de 360 horas, superando de esta forma las 300 horas mínimas que se especifica en la normativa vigente sobre el tiempo que se debe dedicar a un trabajo de fin de grado. Durante estas 24 semanas de trabajo estimadas, se dedicarán 3 horas diarias, y se planificaron 7 iteraciones, repartidas de las siguiente forma: 1aIteración (1 semana - 15 horas) En esta primera etapa, se realizará una reunión entre cliente, los tutores del proyecto, y desarrollador para definir la funcionalidad del producto y tomar nota de los requisitos. También se definirán las tecnologías y herramientas parra llevar a cabo el desarrollo. 2aIteración (1 semana - 15 horas) En esta iteración se dedicará ha hacer pruebas con las tecnologías seleccionadas para el desarrollo. Los primeros pasos con React Native y con Express. 3aIteración (4 semanas - 60 horas) Durante este periodo se va a realizar el análisis y diseño inicial del proyecto, con sus correspondientes diagramas. También, se desarrollará un prototipo funcional simple de la aplicación. Paralelamente, se trabajará en el diseño de las pantallas de esta, mediante una herramienta de maquetación. Se pedirá retroalimentación sobre ambas cuestiones. 4aIteración (4 semanas - 60 horas) Implementación de la parte servidor del sistema. Consistirá en una serie de APIs, desarrolladas con Node.js, y una base de datos, no relacional, implementada con Mongo. Se llevarán a cabo pruebas de las APIs mediante Postman. 15 2.2. Entorno tecnológico 5aIteración (8 semanas - 120 horas) Implementación de la aplicación cliente multiplataforma. Utilizando React-Native y Expo, se realizará la app, comenzando por las pantallas de login y registro y siguiendo por cada uno de los modos de juego. 6aIteración (2 semanas - 30 horas) Una vez implementados todo y revisado por el cliente, se procede a realizar los cambios necesarios en la aplicación. 7aIteración (4 semanas - 60 horas) Comienza la redacción de la memoria. Se desplegará el servidor en una máquina del grupo ECASIMM. También se realizarán las pruebas de integración y unitarias. Figura 2.1: Distribución de las iteraciones según sus semanas de desarrollo. 2.2. Entorno tecnológico En esta sección se enumeran las herramientas utilizadas para el desarrollo, tanto el software como los equipos. 2.2.1. Herramientas utilizadas A continuación, se listan los programas y utilidades empleadas: 5kPlayer [36]: Visualización de pantalla iPad en Windows. 16 Planificación Astah [37]: Creación de diagramas UML. Bitbucket [38]: Almacenamiento de repositorios del proyecto en la nube. Expo client para Android [39]: Ejecutar aplicación en Android en modo desarrollo. Expo client para iOS [40]:Ejecutar aplicación en iOS en modo desarrollo. Git for Windows [41]: Control de versiones del código del proyecto. Google Drive [42]: Almacenamiento de ficheros en la nube relacionados con la memoria. Google STT API [32]: API para procesamiento de voz a texto (ASR). Marvel [43]: Creación de bocetos y prototipos. Mongo DB Compass Community [44]: Interfaz gráfica para MongoDB. Nginx [45]: Servidor para aplicación Node. Node.js [11]: Herramienta JavaScript para desarrollo tanto de servidor como de cliente. Unifica el lenguaje de programación (JavaScript) y el formato de los datos (JSON). Overleaf [46]: Editor LaTeX en la nube. Oracle Virtual Box [47]: Virtualización de máquinas. Postman [30]: Pruebas contra las APIs del proyecto. React Native [16]: framework que permite desarrollar con JavaScript y se compila a código nativo. Swagger [29]: Herramienta para la documentación de las API. Skype [48]: Aplicación de videollamadas para la comunicación con los tutores del proyecto. Telegram [49]: Aplicación de mensajería instantánea para la comunicación con los tutores del proyecto. Vysor [50]: Visualización de pantalla Android en Windows Visual Studio Code [51]: IDE para desarrollo tanto del backend como del frontend. Módulos relevantes npm utilizado en el backend: bcrypt [52]: librería para codificar contraseñas. express [15]: infraestructura de aplicaciones web Node.js mínima y flexible que proporciona un conjunto sólido de características para las aplicaciones de Node.js. jest [53]: marco de trabajo para pruebas de aplicaciones JavaScript. jsonwebtoken [54]: generación de JsonWebToken (JWT). 17 2.2. Entorno tecnológico mongoose [55]: modelado de objetos mongodb para Node.js. nodemon [56]: ayuda para el desarrollo de aplicaciones Node, reiniciando el proyecto cada vez que se realizan cambios. supertest [57]: herramienta de pruebas para peticiones HTTP. Módulos relevantes npm utilizado en el frontend: Axios [58]: cliente HTTP basado en promesas. Expo [27]: conjunto de herramientas y servicios construidos con React Native para facilitar el desarrollo. i18n-js [59]: internacionalización de la aplicación. ramda [60]: librería de funciones JavaScript. 2.2.2. Entorno de trabajo En las siguientes tablas se describen los equipos utilizados, tanto para el desarrollo, como para las pruebas de la aplicación. Ordenador portátil Asus X555L Hardware Procesador Intel Core i5 5200u a 2.2GHz RAM 8GB DDR3 SSD 256GB HDD 1TB GPU NVIDIA GeForce 920M con 2GB DDR3 VRAM Software Sistema operativo Windows 10 Education Arquitectura 64 bits Tabla 2.1: Ordenador utilizado en desarrollo. 18 Planificación Monitor LG 27GL850 Resolución 2560 x 1440 Tamaño 27” Ratio de aspecto 16/9 Tabla 2.2: Monitor utilizado en desarrollo. Smartphone Oneplus 7T Hardware Procesador Qualcomm Snapdragon 855 Plus RAM 8GB LPDDR4X Almacenamiento 128GB UFS 3.0 GPU Adreno 640 Pantalla 6,55” Software Sistema operativo OxygenOS basado en Android 10 Arquitectura 64 bits Tabla 2.3: Smartphone utilizado en desarrollo. Tablet iPad 2019 Hardware Procesador Apple A10 Fusion RAM 3 GB Almacenamiento 32GB Pantalla 10,2” Software Sistema operativo iOS 13 Arquitectura 64 bits Tabla 2.4: iPad utilizado en desarrollo. 19 2.5. Planificación final a esto, se vió afectada la duración de las iteraciones 4 y 5, con 2 y 1 semanas respectivamente. Cabe comentar que realmente este retraso no afectó directamente a la duración del proyecto, ya que, como se ha explicado anteriormente, la fecha de entrega se retrasaba hasta el curso siguiente. Además, cabe mencionar el periodo de confinamiento debido a la pandemia de la COVID-19. Esta situación, sumada a que el proyecto no se podría presentar, hizo que durante unos meses el tiempo dedicado al proyecto fuera en decremento, afectando a las iteraciones 4 y 5. En ningún momento se llegó a parar el desarrollo por completo pero si se dedicaban menos horas de las 15 semanales propuestas en un principio. Teniendo en cuenta todo lo comentado anteriormente, en octubre de 2020, con la vuelta a la rutina, se retoma el horario de 15 horas semanales. En este punto, el proyecto se encuentra a mitad de la iteración 5. El final de esta iteración coincide con el periodo de exámenes de convocatoria extraordinaria de fin de carrera, dos semanas en las que se para el proyecto para que el desarrollador pueda dedicarse enteramente a preparar los exámenes. Una vez el desarrollador acabó los exámenes, se retoma la iteración 6, en la que también se produce un retraso de 2 semanas debido a los diferentes bugs encontrados a la hora de probar la aplicación por parte del cliente. A parte de los bugs, el cliente también se percató de que sería útil implementar ciertas funcionalidades que no se habían tenido en cuenta, como por ejemplo la autenticación con un ”Refresh Token” o la pantalla de historial del jugador. A partir de aquí, la iteración 7 se desarrolló con normalidad. Analizando el desarrollo del proyecto, haciendo referencia al riesgo R06, se puede deducir que en un principio se hizo una planificación demasiado optimista (ver figura 2.2), subestimando el desconocimiento de las tecnologías que se iban a utilizar. Finalmente, la duración real del proyecto, en semanas de trabajo dedicadas (sin tener en cuenta el tener que presentarlo un año más tarde), ha sido de 30 semanas frente a las 24 estimadas, que se traducen en 450 horas frente a 360 estimadas. La distribución por iteraciones quedaría de la siguiente manera: 1aIteración: 1 semana - 15 horas 2aIteración: 1 semana - 15 horas 3aIteración: 5 semanas - 75 horas 4aIteración: 6 semanas - 90 horas 5aIteración: 9 semanas - 135 horas 6aIteración: 4 semanas - 60 horas 7aIteración: 4 semanas - 60 horas 26 Figura 2.2: Comparación de la estimación original con la duración real. 2.5. Planificación final 28 Capítulo 3 Descripción de las iteraciones En este capítulo se va a exponer 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, de las pruebas realizadas con las tecnologías, el prototipo implementado, el diseño de todas las pantallas de la parte frontend y, finalmente, las implementaciones primero del backend y luego del frontend. 3.1. Iteración 1 Para iniciar el proyecto, se produce una reunión del desarrollador con el cliente, en este caso, los tutores del TFG. En esta primera reunión, el cliente expone las características del proyecto de manera que se puedan identificar los diferentes requisitos y las correspondientes historias de usuario. Una vez se tiene un contexto general de la dimensión y funcionalidades del proyecto se procede a realizar una estimación de los tiempos de desarrollo para cada parte. Esta planificación se puede ver detalladamente en la sección 2.1 de la memoria. 3.1.1. Descripción de requisitos 3.1.1.1. Requisitos funcionales A continuación se describen los diferentes requisitos funcionales del proyecto. Estos requisitos describen detalladamente los servicios que se deben implementar. En la tabla 3.1 se se muestran estos requisitos con su descripción y prioridad, en una escala de ”Alta”, ”Media”, y ”Baja”. 29 3.1. Iteración 1 ID Nombre Descripción Prioridad RF01 Registro de un usuario El sistema permitirá crear nuevos usuarios Alta RF02 Identificación de un usuario El sistema permitirá que los usuarios existentes se identifiquen Alta RF03 Cerrar sesión El sistema permitirá que los usuarios cierren la sesión Alta RF04 Crear juego El sistema permitirá crear un juego nuevo Alta RF05 Crear grabación El sistema permitirá crear una grabación (para almacenarla en base de datos) Alta RF06 Crear log de partida El sistema permitirá crear un log con los datos de una partida Alta RF07 Mostrar historial El sistema permitirá mostrar el historial de un jugador Media RF08 Elegir modo de juego El sistema permitirá elegir qué modo de juego se va a jugar Alta RF09 Mostrar resumen El sistema permitirá mostrar el resumen final de una partida Media RF10 Grabar audio El sistema permitirá al usuario grabar su voz Alta RF11 Reproducción de audio El sistema permitirá al usuario reproducir un audio Alta RF12 Reproducción de vídeo El sistema permitirá al usuario reproducir un vídeo Media RF13 Mostrar idiomas El sistema mostrará al usuario que idiomas puede elegir para practicar Alta RF14 Mostrar fonema El sistema mostrará al usuario que fonemas puede elegir para practicar Alta Tabla 3.1: Tabla de requisitos funcionales. 3.1.1.2. Requisitos no funcionales En este apartado, se procede a describir los requisitos no funcionales. Estos definen propiedades emergentes del sistema o necesidades técnicas de éste. En la tabla 3.2 se muestran con una estructura similar a la utilizada para los funcionales solo que en este caso en lugar de utilizar prioridad se utiliza relevancia con una escala de ”Critica”, ”Deseable” o ”Baja”. 30 Descripción de las iteraciones ID Nombre Descripción Relevancia RNF01 Multiplataforma El sistema se podrá utilizar al menos en iOS y Android Crítica RNF02 Almacenamiento en base de datos El sistema guardará los datos de usuarios, partidas y sonidos en una base de datos MongoDB Crítica RNF03 Formato de palabras El sistema utilizará un formato JSON para la gestión de las palabras Crítico RNF04 Formato de logs El sistema utilizará un formato JSON para guardar los logs Deseable RNF05 Almacenamiento de listas de palabras Las listas de palabras se almacenarán como un archivo JSON en el servidor Crítico RNF06 Escalabilidad de listas de palabras El sistema permitirá añadir nuevas listas de palabras manualmente Crítico RNF07 Formato audio El sistema guardará los audios en un formato reproducible, .awb en Android y .wav en iOS Crítica RNF08 Notificación de errores El sistema informará al usuario en caso de que ocurra algún error Crítica RNF09 Facilidad de instalación Se debe poder instalar el sistema siguiendo el manual de instalación Deseable RNF10 Protección de datos sensibles El sistema debe encriptar las contraseñas de los usuarios Crítica RNF11 Identificación mediante token El sistema utilizará el estándar JWT para las comunicaciones con la API Crítica Tabla 3.2: Tabla de requisitos no funcionales. 3.1.1.3. Requisitos de información Por último, en la tabla 3.3 se detallan los requisitos de información. Estos indican el tipo de información que se necesita guardar en el sistema. 31 3.1. Iteración 1 ID Nombre Descripción RI01 Datos de usuario Los campos a guardar sobre los usuarios son: Identificador único Nombre Contraseña Correo electrónico País de origen Idioma materno Lista de tokens RI02 Datos de partida Los campos a guardar sobre las partidas son: Identificador único Modo de juego Fecha de la partida Puntuación Idioma que se está practicando Fonema que se está practicando RI03 Datos de las grabaciones Los campos a guardar sobre las grabaciones son: Identificador único Nombre del archivo de audio en el servidor Código de lenguaje con región Sistema operativo en el que se ha grabado Texto de la palabra que se ha grabado RI04 Datos de las listas de palabras Las listas deben ser archivos JSON, ver más abajo la estructura y con el siguiente formato de nombre: tipoLista_codigoIdioma_codigoRegion.json Ej.: consonant_en_us.json, para un sonido consonante, de habla inglesa de la región de EEUU. Tabla 3.3: Tabla de requisitos de información. 32 Descripción de las iteraciones Ejemplo de formato de una lista de palabras: [ { " id ": string , // Identificador de la lista " name ": string , // Nombre descriptivo de la lista " short_name ": string , // Nombre corto de la lista " pairs ": [{ // Pares de palabras de la lista " words ": [{ // Array con las primeras palabra de cada par " word ": string , // Primera palabra del par " trans ": string // Transcripcion fonetica de la palabra }], { " words ": [{ // Array con las segundas palabras de cada par " word ": string , // Segunda palabra del par " trans ": string // Transcripcion fonetica de la palabra }] }] } ] Estas listas de palabras estarán almacenadas en una carpeta del servidor a la que se podrán añadir nuevas listas de forma manual, y éstas serán reconocidas automáticamente por el sistema. Como cabe la posibilidad de que hayan varias listas de la misma región, de diferente tipo, de cara al usuario se tratarán como una única lista presentándole una lista unificada para cada región. Por otro lado, se guardarán los archivos JSON con los logs de las partidas. En el servidor habrá una carpeta de usuarios, en la que para cada usuario existe otra carpeta de logs. Dentro de esta se almacenarán los archivos de log por día, el cual contiene todas las partidas jugadas por el usuario ese día en concreto. La estructura de estos archivos es un array de objetos JSON. Cada elemento de este array contiene la información de cada partida, incluyendo los datos del usuario y los eventos que han ocurrido durante la partida. Su estructura se puede ver en detalle en el apartado 4.4.4. 3.2. Iteración 2 En esta segunda iteración se comienza la familiarización con las tecnologías elegidas para realizar del proyecto. Comenzando por hacer pequeños proyectos del estilo ”Hola mundo” tanto con React Native como con Express. El objetivo de estas pruebas es adquirir los conocimientos básicos para arrancar el proyecto. 3.2.1. Implementación de código básica Por un lado, para la primera toma de contacto con React Native, siguiendo los consejos de los propios desarrolladores, se ha hecho uso de la herramienta Expo, recomendada para desarrolladores sin experiencia. Siguiendo el tutorial proporcionado en la misma página de Expo [65], se puede ver de una manera simple cómo iniciar un proyecto y hacer el primer ”Hola mundo”. 33 3.2. Iteración 2 Se ha elegido React Native como tecnología de desarrollo frente a Ionic, que era otra de las propuestas, debido a la forma de compilar el código de forma nativa en contraposición a Ionic que sería más parecido a una Progressive Web Application (PWA). Además, echando un vistazo a la página npmtrends [66] se puede ver la tendencia de uso de los últimos años de ambas tecnologías: Figura 3.1: React Native VS Ionic. El hecho de que React Native tenga una mayor comunidad será de gran ayuda a la hora de resolver los diferentes problemas que vayan surgiendo a lo largo del desarrollo. Por otra parte, para el lado del servidor se ha seguido otro tutorial [67] en el que se explica desde la estructura de un proyecto Express, hasta como utilizar la autenticación con JWT, pasando por la conexión con una base de datos Mongo utilizando la librería Mongoose. Para la base de datos se ha elegido Mongo para aprovechar las ventajas que nos brinda el modelo conocido como ”MERN stack” [68], que, en resumen, proporciona compatibilidad entre las estructuras de datos ya que usa un formato similar a JSON, el cual coincide con la estructura de los objetos en JavaScript. 3.2.2. Despliegue de la tecnología: estado de la cuestión de herramientas actuales Primero, para el desarrollo de ambas partes de la aplicación se ha elegido como IDE el Visual Studio Code, perfecto para desarrollo con JavaScript gracias a sus múltiples extensiones. Una vez configurado, por una parte se crea una aplicación de React Native con el Command Line Interface (CLI) de Expo, este nos proporciona un esqueleto básico para una aplicación. Por otro lado, se crea un proyecto Express. Para la estructura de directorios de este se usa una plantilla, ya que no se dispone de un CLI que lo haga automáticamente. También se instalan otras herramientas secundarias que se utilizarán durante el desarrollo como MongoDB Compass, Postman o el cliente de Expo en los dispositivos móviles de prueba. En esta etapa también se crean los repositorio Git, uno para el servidor y otro para la aplicación. Como servicio de alojamiento se ha elegido Bitbucket, ya que es con el que el desarrollador está más 34 Descripción de las iteraciones familiarizado. 3.2.3. Pruebas de concepto El objetivo de estas pruebas ha sido realizar pequeños desarrollo en ambos proyectos para probar a nivel conceptual el uso de las diferentes técnicas que se prevé que harán falta en un futuro, por ejemplo, trabajar con el formato JSON y los objetos JavaScript. A parte de esto, se ha hecho alguna prueba contra la API Speech-to-text de Google, no solo para comprobar el funcionamiento, sino que también ha servido para ver el formato de la respuesta que genera. 3.3. Iteración 3 En esta iteración se realiza el análisis y diseño inicial de la aplicación. Para representarlo se preparan los siguientes diagramas: de casos de uso, del modelo de dominio, de actividad, modelo de datos, de paquetes y de despliegue. También, se detallan en tablas las historias de usuario. Todo esto, se puede ver con mayor detalle en el capítulo 4. Además, se ha desarrollado un prototipo que incluye la funcionalidad básica de la aplicación. Este prototipo consiste en una aplicación móvil con la que se puede grabar un audio y después por pantalla se mostrará el texto correspondiente. Entrando un poco más en detalle, el flujo del prototipo es el siguiente: primero se pulsa un botón que activa la grabación, esta se sube al servidor y se almacena. Desde el servidor se hace una llamada a la API de Google y una vez tiene la respuesta, se devuelve el valor a la aplicación móvil. El mayor problema encontrado al desarrollar este prototipo fue dar con una configuración correcta para que la API STT reconociera correctamente el audio que se mandaba. Finalmente, con la ayuda de la documentación oficial [69] y algún ejemplo encontrado en la web [70], se ha dado con una configuración compatible con iOS y Android. También, durante esta fase se han ido diseñando las pantallas con la ayuda de la herramienta de maquetado Marvel [43]. Estas pantallas están basadas en las descripciones de los modos de juego dadas por el cliente. A continuación se pueden ver las pantallas y sus descripciones. 35 3.3. Iteración 3 Historial de puntuaciones: en esta pantalla se debe mostrar las ultimas puntuaciones del usuario para el sonido elegido (ver Figura 3.14). Figura 3.14: Pantalla de historial de puntuaciones. Opciones: en esta pantalla se debe mostrar las opciones de configuración de la aplicación (ver Figura 3.15). Figura 3.15: Pantalla de opciones. 42 Descripción de las iteraciones Registro: en esta pantalla debe mostrar un formulario con los campos necesarios para el registro de un usuario. Los campos que se incluyen son: username, email, password, confirmación de password, imagen. El email y username no se puede cambiar (ver Figura 3.16). Figura 3.16: Pantalla de registro. Selección de dificultad: en esta pantalla se debe poder elegir una dificultad (ver Figura 3.17). Figura 3.17: Pantalla de selección de dificultad. 43 3.4. Iteración 4 3.4. Iteración 4 Tras presentar las pantallas al cliente, se detectaron diferentes ausencias en la interfaz, como el temporizador o el número de ronda. Estos cambios quedan anotados y se añadirán en la implementación final de la aplicación. Una vez queda aprobada la interfaz se comienza con el desarrollo de la parte de servidor del proyecto. Esta consiste en una serie de llamadas para gestionar la base de datos y la conexión a la API STT de Google. 3.4.1. Desarrollo Backend Primero, se desarrolla el código necesario para las llamadas relacionadas con la gestión del usuario, la creación, la identificación, el inicio de sesión y cierre. La identificación de usuarios contra la API se hará mediante tokens, con el estándar JWT. Cada vez que un usuario se registra se le proporciona un token con una caducidad y un refresh token, que servirá para identificarse una vez el anterior caduque. Si ambos han caducado entonces será necesario que el usuario se vuelva a identificar. De ahora en adelante, todas las llamadas se implementan con seguridad, de manera que no se puedan utilizar sin un token válido. Las siguientes llamadas que se implementan son las que tienen que ver con la subida de grabaciones. Estas se guardan en una carpeta del servidor asociadas al usuario que las ha grabado, y en la base de datos se guarda un registro con la ruta de acceso y otros datos. También, en este momento se realiza la conexión a la API STT para una de las llamadas, la cual requiere de credenciales para Google Cloud Platform. Simplemente, se crea una cuenta y se genera una clave en formato JSON que se guarda en el servidor y se envía en dicha llamada. A continuación, se crean las llamadas para generar las listas de palabras para cada modo de juego. Partiendo de las listas de palabras en formato JSON proporcionadas por el cliente, se seleccionan aleatoriamente las palabras necesarias. También se crea la llamada para poder guardar las partidas y para ver el historial. Tras una reunión con los tutores se detectan errores en alguna de las llamadas, como que no se estaba pasando el idioma de la grabación, o, el más relevante, que la respuesta del STT a veces devuelve palabras con alguna letra en mayúscula, lo que produce un error al comparar estas con las de la lista. La solución que se toma para esto es que se devuelvan todas las palabras, tanto las que devuelve el STT, como las que se extraen de las listas, con todas sus letras en minúscula. Además, se pidió una modificación para guardar el log de partidas de cada usuario por días, en lugar de un log por cada partida como se estaba haciendo hasta el momento. 3.4.2. Pruebas funcionales Durante el desarrollo de las llamadas, estas se han ido probando mediante la aplicación Postman, para tratar de minimizar todos los posibles fallos antes de la integración con el frontend. Estas pruebas consisten es realizar la llamada y comprobar que devuelve el resultado esperado. 44 Descripción de las iteraciones 3.5. Iteración 5 Esta es la iteración con más carga de trabajo de todas. El desarrollo de las pantallas ha seguido el orden equivalente a las llamadas a la API, empezando por el registro y login, y siguiendo por los diferentes modos de juego y otras pantallas, además de implementar la internacionalización para todas ellas, en español y en inglés. Esta parte además de la más larga es en la que más problemas han surgido. Los primeros problemas que surgieron en esta iteración estaban relacionados con la instalación de las librerías de npm. Al actualizar manualmente una de ellas el proyecto dejó de compilar, impidiendo la continuación del desarrollo hasta encontrar la solución. Es un problema común con npm, las librerías que se guardan en la caché, imposibilitan la instalación del paquete que interesa incluso creando el proyecto desde cero. La solución, una vez conocido el problema, es simple, limpiar la caché de npm y reinstalar los paquetes. Otro problema recurrente durante el desarrollo ha sido la asincronía de las funciones JavaScript, afectando sobretodo al componte que implementa el temporizador para los juegos, dando un comportamiento errático. Cierto es, que según se gana experiencia con el lenguaje, hace más fácil el control del flujo de las llamadas. En el siguiente fragmento de código se pueden ver los manejadores implementados para controlar el temporizador con precisión. Todas las funciones de este código que empiezan por ”set” son hooks [71] de estado de React. 1useImperativeHandle(ref, () => ({ 2reset: () => { 3setIsActive ( false ); 4setRound ( round => round - 1) ; 5}, 6pause: () => { 7setIsActive ( false ); 8}, 9unpause : () => { 10 setIsActive ( true ); 11 setCounter ( counter - 1) 12 }, 13 start: () => { 14 setIsActive ( true ); 15 setRound ( round => round - 1) ; 16 }, 17 restart : ( time) => { 18 setIsActive ( true ); 19 setCounter ( time ) 20 }, 21 }) ); Mientras se iban desarrollando las pantallas y los juegos, se han ido integrando las correspondientes llamadas a la API. El primer juego implementado por completo es el de pronunciación, ya que está formado por componentes que servirán para casi todos los otros juegos. Una vez afinados, los componentes comunes como el temporizador o la grabadora, se continua con el desarrollo del resto de 45 3.6. Iteración 6 juegos. Al finalizar esta etapa, se presenta el producto para su prueba por parte de los tutores y de esta manera puedan sugerir cambios o encontrar fallos. 3.6. Iteración 6 Esta iteración se dedica a implementar los cambios sugeridos tras las pruebas. La mayoría suponen cambios estéticos, corrección de textos o avisos de que algo ha ido mal. También se encuentran algunos fallos funcionales, sobre todo relacionados con la grabación y reproducción de audios, que en ciertas situaciones no contempladas hacían que la aplicación se detuviera. También se añaden ciertos cambios en la parte de servidor para gestionar varias listas de palabras del mismo idioma y, también, para parametrizar algunas opciones, como las rutas de guardado de archivos, la dificultad del ASR o el número de rondas para cada modo de juego. 3.7. Iteración 7 En esta última iteración, se procede al despliegue, realización de pruebas y redacción de la memoria. 3.7.1. Pruebas Se añaden algunos test unitarios en la parte de la aplicación y también algunos test de integración en el servidor. No se ha cubierto todo el código por falta de tiempo, pero quedan hechos como ejemplo para el futuro. También se llevan a cabo pruebas de usabilidad con usuario reales y se recoge la retroalimentación para posibles mejoras. Para ver en detalle las pruebas ir al capítulo 5. 3.7.2. Despliegue Se despliega el servidor en una máquina virtual de la UVa siguiendo el manual del apéndice B.1.2. También se genera la APK de la aplicación para Android, siguiendo el manual del apéndice B.2.2. 3.7.3. Redacción de la memoria Se comienza la redacción formal de la memoria, en Overleaf [72] utilizando LaTeX, recopilando las notas tomadas durante el desarrollo del proyecto. Estas notas se han ido anotando en un documento word y en comentarios dentro del código. Además, también ha sido de ayuda para la redacción de 46 Descripción de las iteraciones este el historial de commits de Bitbucket. También se añaden los distintos diagramas creados con la herramienta Astah. 47 Capítulo 4 Estado final de la aplicación 4.1. Diagramas de análisis En este capítulo se van a tratar los temas referentes al diseño de la aplicación abordando temas como las historias de usuario, diagrama de dominio, diagramas de actividad, estructura del backend, estructura del frontend, patrones de diseño y arquitectónicos, modelo de datos, diagrama de paquetes, diagrama de despliegue y estructura del log de actividad. 4.1.1. Historias de usuario En esta sección de da una descripción detallada de todas las historias de usuario del proyecto. Todas son independientes unas de otras, si bien cabe destacar que todas, excepto ”Registro” y ”Login”, tienen como prerrequisito estar identificado en el sistema. En las siguientes tablas se pueden ver los detalles de las historias de usuario con los siguientes campos: ID: identificador de la historia de usuario. Nombre: nombre descriptivo de la historia de usuario. Prioridad: nivel de prioridad en el desarrollo de la funcionalidad correspondiente a la historia de usuario. Clasificación: baja, media y alta. Riesgo: impacto sobre el proyecto si se produce un fallo en la historia de usuario. Clasificación: bajo, medio y alto. Descripción: texto descriptivo de la funcionalidad que ha de implementar la historia de usuario. Con el formato ”Como usuario, quiero...” Validación: condiciones ha cumplir para poder considerar la historia de usuario válida. 49 ID HU01 Nombre Registro de un usuario (Registrar) Prioridad Alta Riesgo Alto Descripción Como usuario, quiero poder registrarme en el sistema Validación – Quiero poder registrarme en el sistema con un nombre de usuario, contraseña, email, lenguaje materno, país de origen. – Quiero que el usuario, contraseña y email sean únicos. Tabla 4.1: Historia de usuario HU01. ID HU02 Nombre Identificación de un usuario (Identificar) Prioridad Alta Riesgo Alto Descripción Como usuario, quiero poder identificarme con mis credenciales en el sistema Validación – Quiero poder identificarme en el sistema con un nombre de usuario y una contraseña. – Quiero que mis datos se utilicen para futuras operaciones. Tabla 4.2: Historia de usuario HU02. ID HU03 Nombre Modificar datos de usuario (Modificar) Prioridad Alta Riesgo Alto Descripción Como usuario, quiero poder modificar mis datos en el sistema Validación – Quiero cambiar mis datos personales. Tabla 4.3: Historia de usuario HU03. Estado final de la aplicación ID HU04 Nombre Seleccionar idioma de la aplicación (SeleccionarIdiomaAplicacion) Prioridad Media Riesgo Bajo Descripción Como usuario, quiero poder utilizar la aplicación en diferentes idiomas Validación – Quiero seleccionar el idioma de la interfaz. Tabla 4.4: Historia de usuario HU04. ID HU05 Nombre Seleccionar idioma de la partida (SeleccionarIdiomaPartida) Prioridad Alta Riesgo Alto Descripción Como usuario, quiero poder seleccionar el idioma a practicar en las partidas Validación – Quiero seleccionar el idioma de la partida. Tabla 4.5: Historia de usuario HU05. ID HU06 Nombre Selección de fonemas a practicar (SeleccionarFonemas) Prioridad Alta Riesgo Alto Descripción Como usuario, quiero poder elegir el fonema de la lista de palabras que quiero practicar Validación – Quiero poder ver la lista de listas de palabras disponibles del idioma seleccionado. Tabla 4.6: Historia de usuario HU06. 51 4.1. Diagramas de análisis Task Descripción Modela las tareas de una partida. Responsabilidades Modelar lo que sucede durante las rondas de una partida. Atributos –time: tiempo de duración de una ronda. –round: número de ronda. Tabla 4.21: Entidad Task. TTS Descripción Modela el sintetizador de voz. Responsabilidades Sintetizar los diferentes textos. Atributos –volume: volumen de reproducción. –peach: velocidad de reproducción. Tabla 4.22: Entidad TTS. ASR Descripción Modela el reconocedor de voz. Responsabilidades Modelar la configuración para el reconocimiento de voz. Atributos –nResults: número de resultados máximos esperados del reconocimiento de voz. Tabla 4.23: Entidad ASR. 58 Estado final de la aplicación Feedback Descripción Modela los atributos de la retroalimentación. Responsabilidades Ofrecer al usuario la retroalimentación necesaria tras reconocer una palabra. Atributos –alternatives: palabras que ha entendido el reconocedor. –isCorrect: si es correcta o no la palabra que se ha reconocido. –hint: consejo para pronunciar correctamente. –gscore: puntuación dada por el reconocedor de Google, que indica la probabilidad de que la palabra reconocida sea la palabra grabada. Tabla 4.24: Entidad Feedback. Exposure Descripción Modela el modo de juego Exposición . Responsabilidades Establecer el modo de juego Exposición como dinámica actual de la partida. Tabla 4.25: Entidad Exposure. Perception Descripción Modela el modo de juego Percepción. Responsabilidades Establecer el modo de juego Percepción como dinámica actual de la partida. Tabla 4.26: Entidad Perception. Pronunciation Descripción Modela el modo de juego Pronunciación. Responsabilidades Establecer el modo de juego Pronunciación como dinámica actual de la partida. Tabla 4.27: Entidad Pronunciation. 59 4.1. Diagramas de análisis Mixed Descripción Modela el modo de juego Mixto. Responsabilidades Establecer el modo de juego Mixto como dinámica actual de la partida. Atributos –timePronunciation: tiempo de las rondas que corresponden al modo de juego Pronunciación. –timePerception: tiempo de las rondas que corresponden al modo de juego Percepción. Tabla 4.28: Entidad Mixed. Puzzle Descripción Modela el modo de juego Puzzle. Responsabilidades Establecer el modo de juego Puzzle como dinámica actual de la partida. Tabla 4.29: Entidad Puzzle. Memory Descripción Modela el modo de juego Memoria. Responsabilidades Establecer el modo de juego Memoria como dinámica actual de la partida. Tabla 4.30: Entidad Memory. Theory Descripción Modela el modo de juego Teoría. Responsabilidades Establecer el modo de juego Teoría como dinámica actual de la partida. Atributos –videoUrl: URL del vídeo correspondiente a la lista de palabras. Tabla 4.31: Entidad Theory. 60 Estado final de la aplicación Audio Descripción Modela un audio grabado Teoría. Responsabilidades Modelar los audios grabados por un usuario. Atributos –name: nombre del archivo. –duration: Duración del audio. Tabla 4.32: Entidad Audio. Video Descripción Modela un vídeo Teoría. Responsabilidades Modelar los vídeos utilizado en la aplicación. Atributos –url: URL del vídeo correspondiente. –duration: Duración del vídeo. Tabla 4.33: Entidad Video. 61 4.1. Diagramas de análisis 4.1.2.1. Relaciones entre entidades De la entidad User, salen cuatro asociaciones. Con Records, la relación sees, hace referencia a un usuario que mira el historial de partidas. La realción performs con Game, simboliza la actividad de un usuario durante una partida, esta será guardada en el log DailyLog. También con Game, está la relación pays, que significa que un usuario juega una partida y obtiene un resultado Result. La última relación de User, es con la entidad Language, para configurar un idioma en las partidas. A su vez, Language, establece el idioma del Game. Los modos de juego Exposure, Perception, Pronunciation, Mixed, Puzzle, Memory y Theory, heredan de la entidad Game, que está compuesta por entidades Task. La entidad Task, se relaciona con otra cinco entidades. Con TTS, para representar la síntesis de palabras. Con ASR, para el reconocimiento de palabras, que da una retroalimentación, Feedback. Con Audio, para la reproducción de audios grabado, y con Video, también, para reproducir vídeos. Task, es una composición de Word, las palabras para practicar, y Word, forma parte de una par con otras Word. 4.1.3. Diagramas de actividad En esta sección se presentan los diagramas de actividad para las historias de usuario descritas en el apartado 4.1.1. Se detallan las acciones realizadas en el frontend y las consiguientes operaciones llevadas a cabo por el backend. Se muestra tanto la secuencia normal como la secuencia de lo que sucede si se comete algún error en algún caso. 62 4.1.3.1. HU01 - Registar La figura 4.2 muestra el diagrama de actividad de la historia de usuario HU01. En el formulario de registro se pide que se introduzca dos veces la contraseña, una comprobación habitual para asegurar que el usuario sabe qué contraseña escribe. Por esto, se comprueba en el frontend si las dos contraseñas introducidas coinciden, si es así se envían los datos al backend, si no, se le informa al usuario de que no coinciden para que pueda rectificar. Una vez llega el formulario, se comprueba todo lo demás, como que el usuario y el correo no existan ya en el sistema y también que el correo tenga un formato válido. Si estas comprobaciones no fallan, se envía un mensaje de éxito para que el frontend se lo muestre al usuario, en caso de error, se haría lo mismo con un mensaje de error especificando cual es el dato incorrecto. Figura 4.2: Diagrama de actividad de HU01. 4.1.3.2. HU02 - Identificar La figura 4.3 muestra el diagrama de actividad de la historia de usuario HU02. Una vez el usuario introduce su nombre de usuario y contraseña, estos datos se mandan al backend para realizar la búsqueda en la base de datos. Si los datos son correctos, se guarda toda la información necesaria en el frontend y pasará a la siguiente pantalla, si no, se mostrará un mensaje de error neutro, sin información de lo que ha fallado, esto se hace por motivos de seguridad Figura 4.3: Diagrama de actividad de HU02. 4.1.3.3. HU03 - Modificar La figura 4.4 muestra el diagrama de actividad de la historia de usuario HU03. Este caso es similar al de Registrar, lo único que esta vez las comprobaciones solo se realizan con los campos habilitados para edición, que son todos menos usuario y email. Figura 4.4: Diagrama de actividad de HU03. 4.1.3.4. HU04 - SeleccionarIdiomaAplicación La figura 4.5 muestra el diagrama de actividad de la historia de usuario HU04. El usuario elige un idioma de entre los disponibles y al seleccionarlo este se queda guardado para que en futuras ocasiones que se acceda esté preseleccionado el que ha elegido. Figura 4.5: Diagrama de actividad de HU04. 4.1.3.5. HU05 - SeleccionarIdiomaPartidas La figura 4.6 muestra el diagrama de actividad de la historia de usuario HU05. Una vez el usuario está identificado en el sistema se le muestra la pantalla de selección de idioma que quiere practicar. Al seleccionar el idioma deseado se le pide al backend la lista de palabras disponibles para este. Figura 4.6: Diagrama de actividad de HU05. 4.1.3.12. HU12 - GrabarAudios La figura 4.13 muestra el diagrama de actividad de la historia de usuario HU12. El usuario graba un audio, este se guarda temporalmente en el frontend y también se envía al backend donde se guardará de forma permanente. Después de esto en algún caso puede darse que se apliquen o la historia de usuario 4.8 o 4.10. Figura 4.13: Diagrama de actividad de HU12. 4.1.3.13. HU13 - JugarPartida Figura 4.14: Diagrama de actividad de HU13. La figura 4.14 muestra el diagrama de actividad de la historia de usuario HU13. Después de que el usuario haya elegido un idioma y un fonema a practicar, debe elegir el modo de juego para hacerlo. 4.1. Diagramas de análisis Cuando selecciona el modo de juego, se envía la petición al backend para que genere la lista de pares de palabras correspondiente y la devuelva. Luego, estas palabras se irán cargando en cada pantalla de la partida hasta que no queden más rondas. Una vez acabada la partida, se le muestra al usuario un resumen de su actuación en ésta. Cuando el usuario ha acabado de ver el resumen y procede a finalizar la partida, se envía un log de la actividad y otros parámetros al backend. 76 4.2. Modelado de la interacción de los modos de juego En esta sección se muestra mediante diagramas de actividad, las interacciones del usuario y el sistema para cada modo de juego. Para ver el diseño de las pantallas mirar la sección 3.3. 4.2.1. Exposición En este modo el sintetizador empieza reproduciendo las palabras cinco veces alternativamente. El usuario puede volver a escuchar las palabras o grabarlas con su voz. Una vez grabadas puede reproducir los audios grabados. Esto puede hacerlo varias veces, hasta que el usuario quiera, luego puede pasar de ronda, en caso de que queden rondas, si no, se muestra la pantalla de fin de partida. Este modo es de práctica, no tiene puntuación. Figura 4.15: Diagrama de actividad modo de juego Exposición. 4.2.2. Percepción Este modo consiste en que el sistema muestra dos palabras y reproduce una de ellas. El usuario tiene que elegir la palabra correcta, y puede volver a escucharla pulsando el botón de reproducir. Si la palabra elegida es correcta, sumara puntos y pasa de pantalla, si no, el sistema muestra que la palabra elegida es incorrecta y pasa a la siguiente pantalla. Si es la ronda final pasará a la pantalla de fin de partida. Figura 4.16: Diagrama de actividad modo de juego Percepción. 4.2.3. Pronunciación En este modo de juego se muestran dos palabras, el usuario puede reproducirlas. Cuando graba una de ella si es correcta se bloquea, si es incorrecta puede seguir probando hasta que se le acaben los intentos, una vez se queda sin intentos se bloquea. Lo mismo para la otra palabra. Una vez las dos palabras están bloqueadas o se acaba el tiempo pasa a la siguiente ronda. Figura 4.17: Diagrama de actividad modo de juego Pronunciación. 4.2.4. Mixto Este modo de juego alterna una pantalla del modo Pronunciación (apartado 4.2.3) y una del modo Percepción (apartado 4.2.2). Figura 4.18: Diagrama de actividad modo de juego Mixto. 4.2.5. Memoria En este modo se presentan seis palabras y el sistema reproduce tres de ellas en un orden concreto. El usuario debe seleccionarlas en orden. También puede elegir volver a reproducirlas. Una vez se acaba el tiempo o elige las tres palabras, el sistema le comunica cuales son correctas y cuales no, y muestra el botón para pasar de ronda. Al final de cada ronda se suman puntos por cada palabra correcta. Figura 4.19: Diagrama de actividad modo de juego Memoria. 4.2.6. Puzzle En este modo se muestran seis palabras y un fonema. El usuario debe seleccionar las palabras que contienen este fonema. Una vez se acaba el tiempo o elige corregir, el sistema le comunica cuales son correctas y cuales no, y muestra el botón para pasar de ronda. Al final de cada ronda se suman puntos por cada palabra correcta. Figura 4.20: Diagrama de actividad modo de juego Puzzle. 4.2.7. Teoría El modo teoría consiste en un vídeo en el que se explica como pronunciar el par de fonemas que se este practicando. Figura 4.21: Diagrama de actividad modo de juego Teoría. 4.4. Diagramas de diseño •Redux: desde aquí se maneja el estado interno de la aplicación móvil y se envían las peticiones a la API. •Node_modules: paquetes de Node.js con funcionalidades utilizadas en el proyecto que facilitan el desarrollo de ciertas tareas. Business layer: capa de negocio o controlador. En esta capa se reciben las peticiones a la API y se realizan las operaciones necesarias para el correcto funcionamiento de la aplicación. •Application facade: la fachada que recibe las peticiones del cliente y envía los datos recibidos a las entidades para procesarlos. •Business entities: las entidades que operan con los datos recibidos en la fachada y devuelven una respuesta. •Node_modules: al igual que en GUI layer, son paquetes de Node.js. Persitence layer: capa de acceso datos. Esta capa hace de intermediario entre la capa de negocio y la base de datos, y es la que lanza las solicitudes necesarias para las transacciones. •Data access: parámetros de acceso a la base de datos, para poder realizar la conexión, como ruta, usuario y contraseña. •Mongoose Models: modelos del framework Mongoose, que definen los objetos y las operaciones de transacción con la base de datos. Security layer: capa de seguridad. Aquí se encuentran los paquetes necesarios para garantizar la seguridad de la aplicación, tanto en las transacciones como en el almacenamiento. •Node security: la propia seguridad que tiene Node.js por defecto. •Operational management: herramienta de Node.js que se encarga de gestionar las peticiones llegadas al servidor por diferentes usuarios, formando una cola con ellas y respondiendo en orden de llegada. •JWT: estándar que define una forma segura de transmitir información entre dos partes mediante la firma digital de los datos. •BCrypt: paquete de Node.js utilizado para codificar datos, en el caso de este proyecto, las contraseñas. MongoDB database: base de datos en al que se almacenan los datos necesarios para la aplicación. 4.4.3. Diagrama de despliegue Como se puede observar en el diagrama de despliegue de la figura 4.26, un usuario se conectará desde una aplicación móvil, Android o iOS, y en el futuro podría ser posible vía web. Esta conexión con el servidor web Nginx se hace mediante peticiones HTTP. El servidor Nginx que actúa de servidor web y balanceador de carga, envía las peticiones al servidor Node.js. A su vez la aplicación Express.js realiza consultas a la base de datos MongoDB, conectándose mediante MongoDB driver, que en este 90 Estado final de la aplicación caso, ambas están en la misma máquina, pero perfectamente podrían estar en máquinas diferentes, simplemente habría que indicar en la aplicación Express.js la URL a la base de datos. Ver el apéndice B.1.2 para el manual de despliegue del sistema. Figura 4.26: Diagrama de despliegue. 4.4.4. Estructura del log de actividad Por día se genera un archivo JSON para cada jugador, almacenado en la ruta del servidor /users /nombre_usuario/logs, que contiene todas las partidas de ese día. Éste está formado por un array de objetos JSON, cada objeto representa una partida jugada. Por lo tanto, en el array de un fichero habrá tantos objetos como partidas se hayan jugado ese día. [ { " player ": { " username ": string , " maternLanguage ": string , " gameLanguage ": string , " difficulty ": string , " modality ": { " modality ": number , " mode ": string }, " challenge ": { " nameList ": string , " totalTimer ": number , " totalPoints ": number } }, " events ": [ { " date ": string , " eventName ": { " name ": string , " words ": string [] , " phoneme ": string , "chosen": string } } ] 91 4.4. Diagramas de diseño } ] Las propiedades del objeto son los siguientes: player: información relativa al jugador y detalles de la partida. •username: nombre del usuario que ha jugado la partida. •motherLanguage: idioma materno del usuario en formato BCP-47 [78]. •gameLanguage: idioma que se ha practicado en formato BCP-47. •difficulty: dificultad de la partida. De momento el parámetro siempre es NA, hasta que haya niveles de dificultad implementados. •modality: modalidad elegida. ◦modality: juego individual (1) o multijugador (2). ◦mode: modo de juego de la partida. Posibles valores: exposure, perception, pronunciation, mixed, memory, puzzle ytheory •challenge: resultado final de la partida. ◦nameList: lista que se ha practicado. ◦totalTimer: tiempo total que ha durado. ◦totalPoints: puntos totales obtenidos. events: array que contiene la información de los eventos transcurridos en la partida. •date: fecha y hora en formato ISO (ej.: 2011-10-05T14:48:00.000Z). •event: detalle del evento. Solo el atributo name es obligatorio, el resto depende de el tipo de evento que sea. ◦name: nombre del evento. Este puede ser: exposure, perception, prounciation, mixed, puzzle, memory o theory, cuando se inicia un modo de juego; listen y record para cuando se reproduce o graba un audio; y, prompt_out cuando se sale de la partida. ◦result: true si ha acertado, false si no. ◦wordsList: par de palabras involucradas. ◦correctWord (modo perception): palabra correcta. ◦words: (modo puzzle y memory) array de palabras. ◦phoneme (modo puzzle): fonema que hay que buscar. ◦chosen (modo puzzle): array con palabras elegidas. ◦solution (modo memory): array de las palabras correctas con las posiciones correspondientes al array de words. ◦correct (modo memory): array de booleanos. True, si la palabra es correcta, false si no. ◦word (reproducrir y grabar sonido): palabra que se ha grabado o reproducido. ◦audioFile (grabar sonido): nombre del archivo de audio. ◦alternatives (grabar sonido): alternativas proporcionadas por el ASR. 92 Capítulo 5 Pruebas Las pruebas tanto de integración en el servidor, como las unitarias en la app, se han automatizado mediante Jest [53]. En ambos entornos, para pasar los test basta con ponerse en la carpeta raíz del proyecto y ejecutar el comando: npm run test 5.1. Test en Backend Para el backend se han realizado test de integración, que consisten en probar la interacción entre diferentes partes del proyecto. En este caso, se simula un cliente para realizar peticiones a la API y así poder comprobar las respuestas que ésta proporciona en las diferentes situaciones posible. Antes de empezar a ejecutar los tests, automáticamente, se crea un usuario de prueba. Y antes de ejecutar cada test, se hace un login para poder obtener un token con el que identificarse en las llamadas que lo requieren. También se mockean algunos documentos a los que se hacen consultas para poder controlar las salidas. CP01 Registro de usuario Descripción Registrar un usuario en el sistema API REST /api/users Entrada { username: ”test_user_2”, password: ”1234”, email: ”[email protected]”, country: ”SPAIN”, language: ”es-ES” } Resultado esperado { user: { username: ”test_user_2”, email: ”[email protected]”, country: ”SPAIN”, language: ”es-ES” }, token: * } Tabla 5.1: Prueba CP01. 93 CP02 Registro de usuario ya existente Descripción Registrar un usuario que ya existe en el sistema API REST /api/users Entrada { username: ”test_user”, password: ”1234”, email: ”[email protected]”, country: ”SPAIN”, language: ”es-ES” } Resultado esperado ”duplicateError” Tabla 5.2: Prueba CP02. CP03 Registro de usuario: formato email incorrecto Descripción Registrar un usuario en el sistema con un email no válido API REST /api/users Entrada { username: ”test_user”, password: ”1234”, email: ”test.com”, country: ”SPAIN”, language: ”es-ES” } Resultado esperado ”validationError” Tabla 5.3: Prueba CP03. CP04 Cerrar sesión de un usuario Descripción Cerrar la sesión de un usuario identificado en el sistema API REST /api/users/me/logout Entrada Bearer token Resultado esperado ”Logged out.” Tabla 5.4: Prueba CP04. CP05 Cerrar sesión de un usuario, sin identificación Descripción Cerrar sesión de un usuario si enviar el token de identificación API REST /api/users/me/logout Entrada Resultado esperado { error: Unauthorized access. } Tabla 5.5: Prueba CP05. Pruebas CP06 Listado de lenguajes Descripción Listar los lenguajes disponibles para creación de un usuario API REST /api/masters/languages Entrada Resultado esperado [{ ”code”: ”af”, ”name”: ”Afrikaans” }, { ”code”: ”en-GB”, ”name”: ”English (United Kingdom)” }, { ”code”: ”es”, ”name”: ”Spanish” } Tabla 5.6: Prueba CP06. CP07 Listado de lenguajes erroneo Descripción Los lenguajes no se ordenan por orden alfabético de nombre, se devolverían en el orden que estén en el JSON API REST /api/masters/languages Entrada Resultado esperado No Igual a [{ ”code”: ”af”, ”name”: ”Afrikaans” }, { ”code”: ”es”, ”name”: ”Spanish” }, { ”code”: ”en-GB”, ”name”: ”English (United Kingdom)” } Tabla 5.7: Prueba CP07. CP08 Listado de paises Descripción Listar los países disponibles para la creación de un usuario API REST /api/users Entrada Resultado esperado [ { ”name”: ”AFGHANISTAN”, ”code”: ”AF” }, { ”name”: ”ALBANIA”, ”code”: ”AL” }, { ”name”: ”ALGERIA”, ”code”: ”DZ” }, ] Tabla 5.8: Prueba CP08. 95 5.2. Test en Frontend 5.2. Test en Frontend En el frontend se han hecho test unitarios. Un test unitario, se puede definir como una prueba que comprueba el correcto funcionamiento de una unidad de código [79]. En este proyecto se han realizado para probar el renderizado correcto de los componentes de la aplicación. Además de probar los componentes también se ha utilizado para probar que el estado de la aplicación sigue un flujo correcto, es decir, se han hecho pruebas con los dispatchers de Redux. Estos cuatro primeros test prueban la correcta renderización del componente "Box", el cual, se encarga de mostrar las palabras al usuario y renderizar los botones para grabar. El componente que se utiliza como entrada para esta suite tiene las siguientes propiedades: <Box word ={’ palabra ’} phonetic ={ ’ transcripcion ’} color ={ ’# fafafa ’} isCorrect ={ correct => jest . fn ( correct )} showHint ={( alternatives ) => jest. fn( alternatives )} setTimer ={( recording ) => jest . fn( recording )} /> Como se puede ver en el código anterior, en lugar de funciones reales, aparece jest.fn(). Este es el método [80] que tiene Jest para crear funciones mock, para casos en los que no se dispone de la función real. Para comprobar la estructura del componente renderizado, se ha utilizado la librería reacttest-renderer [81], que proporciona diferentes funciones con este fin, en este caso se ha utilizado la función toJSON, que convierte el componente en un objeto JSON de manera que se puede acceder al contenido de éste y al de todos sus hijos. CP09 Renderizado del componente Box Descripción Se comprueba que el componente se renderiza Componente Box Resultado esperado El componente se renderiza Tabla 5.9: Prueba CP09. CP10 Mostrar palabra correcta Descripción Se comprueba que la palabra mostrada al usuario es la que se ha establecido en la creación del componente (propiedad word en el componente) Componente Box Resultado esperado ’palabra’ Tabla 5.10: Prueba CP10. 96 Pruebas CP11 Mostrar transcripción fonética correcta Descripción Se comprueba que la transcripción mostrada al usuario es la que se ha establecido en la creación del componente (propiedad phonetic en el componente) Componente Box Resultado esperado ’transcripcion’ Tabla 5.11: Prueba CP11. CP12 Mostrar número de intentos Descripción Se comprueba que se muestra en número de intentos (por defecto 3) Componente Box Resultado esperado ’Remaining attempts: 3’ Tabla 5.12: Prueba C12. CP13 Colorear botones con el color correspondiente Descripción Se comprueba que los botones cogen el color que se ha establecido en la creación del componente (propiedad color en el componente) Componente Box Resultado esperado ’#fafafa’ Tabla 5.13: Prueba CP13. En los siguientes test se hacen pruebas sobre Redux, que gestiona el estado global de la aplicación. Para hacer estas comprobaciones se han realizado pruebas sobre las funciones que actúan como reducers (en el apartado 1.3.5.5 se habla más en detalle de estos conceptos). La entrada es un objeto conformado por el type y el payload de la acción que se ejecuta. Primero se prueba el reducer del usuario. CP14 Retorno del estado inicial Descripción El reducer devuelve el estado inicial Reducer User Entrada ’undefined’ Resultado esperado {} Tabla 5.14: Prueba CP14. 97 5.2. Test en Frontend CP15 Estado correcto tras login Descripción Devuelve la información del usuario después de un login exitoso Reducer User Entrada { type: LOGIN, payload: {user: {username: ’antonio’, email: ’[email protected]’, country: ’SPAIN’, language: ’es-ES’}, token: ’aaaaaaaaaaaaaaa’, refreshToken: ’bbbbbbbbbbb’ }} Resultado esperado {user: {username: ’antonio’, email: ’[email protected]’, country: ’SPAIN’, language: ’es-ES’}, token: ’aaaaaaaaaaaaaaa’, refreshToken: ’bbbbbbbbbbb’ } Tabla 5.15: Prueba CP15. CP16 Estado del usuario logueado Descripción Devuelve la información del usuario logueado Reducer User Entrada { type: SAVE_USER, payload: {user: {username: ’antonio’, email: ’[email protected]’, country: ’SPAIN’, language: ’esES’}} Resultado esperado {user: {username: ’antonio’, email: ’[email protected]’, country: ’SPAIN’, language: ’es-ES’} } Tabla 5.16: Prueba CP16. De aquí en adelante se prueba el reducer de las partidas. Para este caso se usa un estado inicial simulando que el objeto ya se ha inicializado y el contenido del estado es el siguiente: { gameLanguage : ’en -UK ’, gameId : ’134 ’ } CP17 Retorno del estado inicial Descripción El reducer devuelve el estado inicial Reducer Game Entrada ’undefined’ Resultado esperado { gameLanguage: ’en-UK’, gameId: ’134’ } Tabla 5.17: Prueba CP17. 98 CP18 Actualiza el idioma de la partida Descripción Actualiza y devuelve el idioma de la partida actual Reducer Game Entrada { type: SET_GAME_LANGUAGE, payload: ’es-ES’ } Resultado esperado { gameLanguage: ’es-ES’, gameId: ’134’ } Tabla 5.18: Prueba CP18. CP19 Actualiza el ID de la partida Descripción Actualiza y devuelve el ID de la partida actual Reducer Game Entrada { type: SET_GAME_ID, payload: ’135’ } Resultado esperado { gameLanguage: ’en-UK’, gameId: ’135’ } Tabla 5.19: Prueba CP19. Preguntas: ¿Le ha resultado agradable la interfaz? Si ¿Ha habido algún momento en el que no supiera que hacer? No ¿El tamaño de la letra le parece correcto? Si ¿El tamaño de los botones es adecuado? Si ¿Algún comentario que quiera hacer? No 5.3. Test de usabilidad 106 Usuario 2 - Tarea 1 Descripción: el usuario deberá completar un registro, hacer login y elige el idioma inglés de UK y un sonido cualquiera. Se parte desde la pantalla de login y se termina el menú de modos de juego. 1. El usuario encuentra llamativo y agradable el diseño de la aplicación. ¿Completado? SI NO Valoración 1 2 3 4 5 Métrica: Hace algún comentario al respecto Observaciones: No dice nada al respecto 2. El usuario sabe dónde pulsar para crear una nueva cuenta ¿Completado? SI NO Valoración 1 2 3 4 5 Métrica: Satisfactorio si tarda menos de 5 segundos en seleccionar la opción correcta. Tiempo: 8 seg Número de toques (mínimo 1): 1 Errores: 0 Observaciones: Ninguna 3. El usuario es capaz de realizar el registro. ¿Completado? SI NO Valoración 1 2 3 4 5 Métrica: Satisfactorio si no se atasca con ningún paso Tiempo: 120 seg Número de toques (mínimo 7 sin contar la escritura con el teclado): 7 Errores: 0 Observaciones: Ha buscado el país (España) por la letra E en lugar de por la letra S (Spain) 4. El usuario es capaz de hacer login en la app. ¿Completado? SI NO Valoración 1 2 3 4 5 Métrica: Satisfactorio si consigue loguearse Tiempo: 15 seg Número de toques (mínimo 3): 3 Errores: 0 Observaciones: Ninguna Pruebas 107 5. El usuario entiende que tiene que hacer en la selección de idioma y sonido. ¿Completado? SI NO Valoración 1 2 3 4 5 Métrica: Satisfactorio si elige la opción deseada sin confusión y en menos de 20 segundos. Tiempo: 10 seg Número de toques (mínimo 4): 4 Errores: 0 Observaciones: Ninguna Preguntas: ¿Le ha parecido intuitiva la interfaz? Si ¿Ha habido algún momento en el que no supiera que hacer? No ¿El tamaño de la letra le parece correcto? Si ¿El tamaño de los botones es adecuado? Si ¿Algún comentario que quiera hacer? Poner los países e idiomas en castellano. 5.3. Test de usabilidad 108 Usuario 1 - Tarea 2 Descripción: el usuario deberá completar un juego de la modalidad “mixto”. Se parte desde el menú de modos de juego y se termina el mismo. 1. El usuario encuentra llamativo y agradable el diseño de la aplicación. ¿Completado? SI NO Valoración 1 2 3 4 5 Métrica: Hace algún comentario al respecto Observaciones: No dice nada al respecto 2. El usuario elige el modo mixto. ¿Completado? SI NO Valoración 1 2 3 4 5 Métrica: Satisfactorio si elige la opción correcta en menos de 10 segundos Tiempo: 10 seg Número de toques (mínimo 1): 1 Errores: 0 Observaciones: Ninguna 3. El usuario reproduce la palabra del modo pronunciación. ¿Completado? SI NO Valoración 1 2 3 4 5 Métrica: Satisfactorio si el usuario da al play en menos de 5 segundos Tiempo: 20 seg Número de toques (mínimo 1): 1 Errores: 0 Observaciones: Parece que no sabe cómo actuar ante la primera pantalla, pero al final si que da al botón. 4. El usuario graba con su voz la palabra ¿Completado? SI NO Valoración 1 2 3 4 5 Métrica: Satisfactorio si el usuario graba la palabra en menos de 5 segundos Tiempo: 60 seg Número de toques (mínimo 1): 5 Errores: 5 Observaciones: El usuario no se da cuenta que para grabar hay que dejar pulsado el botón Pruebas 109 5. El usuario una vez acaba con la primera palabra repite el proceso con la segunda ¿Completado? SI NO Valoración 1 2 3 4 5 Métrica: Satisfactorio si se da cuenta que tiene que contestar a la segunda palabra Tiempo: - Número de toques (mínimo 2): - Errores: - Observaciones: No le da tiempo a contestar la segunda palabra 6. El usuario reproduce manualmente la palabra del modo percepción. ¿Completado? SI NO Valoración 1 2 3 4 5 Métrica: Satisfactorio si pulsa el botón de play a la primera Tiempo: 3 seg Número de toques: 1 Errores: 0 Observaciones: Ninguna 7. El usuario elige una palabra del modo percepción. ¿Completado? SI NO Valoración 1 2 3 4 5 Métrica: Satisfactorio si sabe cómo elegir la palabra deseada Tiempo: 2 seg Número de toques: 1 Errores: 0 Observaciones: Ninguna 8. El usuario elige finalizar la partida. ¿Completado? SI NO Valoración 1 2 3 4 5 Métrica: Satisfactorio si elige el botón volver al menú en menos de 10 segundos Tiempo: 7 seg Número de toques: 1 Errores: 0 Observaciones: Ninguna 5.3. Test de usabilidad 110 Preguntas: ¿Le ha resultado agradable la interfaz? Si ¿Ha habido algún momento en el que no supiera que hacer? Si. Cuando fallaba la grabación de palabras. ¿El tamaño de la letra le parece correcto? Si ¿El tamaño de los botones es adecuado? Si ¿Algún comentario que quiera hacer? Falta una explicación de lo que hay que hacer en el juego. Pruebas 111 5.3. Test de usabilidad 5.3.1. Conclusiones de los test de usabilidad Como era de esperar, el usuario con más manejo de la tecnología ha hecho prácticamente todas las tareas en menos tiempo que el otro. Aún así, el usuario con menos manejo, tampoco ha encontrado grandes problemas para moverse por la aplicación y jugar la partida. Tras acabar las pruebas y analizar los datos obtenidos, se pueden destacar varios aspectos de la aplicación a mejorar. A continuación se hace una lista de estos y sus posibles soluciones. Elección de idiomas en la creación de usuario. En el desplegable donde se puede establecer el idioma del usuario, aparecen idiomas sin región, lo que en ciertos casos (ej.: español), puede causar problemas con el ASR. Cómo solución, habría que extraer de la lista de selección los idiomas sin región. Las listas de idiomas y regiones en la creación de usuario sólo aparecen en inglés. Hay que añadir estas listas en más idiomas. Confusión a la hora de grabar audios. En lugar de dejar pulsado el botón, el usuario pulsa una vez. La solución es añadir algún tipo de aviso informando del uso del botón. Esto ya estaba contemplado pero no se había implementado en el momento de las pruebas. El usuario no sabe de qué va el juego. Se podría añadir sección de instrucciones, explicando brevemente el objetivo, las mecánicas y el sistema de puntuación de cada juego. 112 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. En este TFG se ha desarrollado una aplicación multiplataforma en la que, mediante elementos de juego y actividades predefinidas, se permite entrenar y mejorar la pronunciación de un idioma extranjero. Mediante la implementación de diferentes modos de juegos, se consigue que una actividad que puede resultar tediosa, sea divertida, incrementando de esta forma la motivación del usuario por aprender y practicar. Esta aplicación consta de una parte de servidor o backend, desarrollado con Node.js, Express.js y MongoDB, y otra parte, cliente o frontend, en la que se ha utilizado Node.js y React Native apoyado en el framework Expo. Además, las tecnologías de reconocimiento y sintetizado de voz que provee Google en Google cloud platform [82] han sido una parte clave del sistema final. Se han realizado pruebas unitarias y de usabilidad que han permitido obtener retroalimentación del sistema. Este proyecto implementa todos los modos de juego de los proyectos anteriores y añade dos modos de juego nuevos y un modo teórico. También deja preparada la base para añadir nuevos modos y funcionalidad multijugador. En el frontend, gracias a la fácil reutilización de los componentes básicos para la funcionalidad principal de la aplicación, entre otros, el de síntesis y el de reconocimiento de voz, ampliar la funcionalidad de la aplicación resulta muy sencillo y rápido. En cuanto a la parte backend, dependerá de la necesidad, pero la llamada para generar listas de pares es fácilmente modificable, como demuestran las adaptaciones del modo ’Puzzle’ y ’Memoria’. Además, gracias en parte a los componentes y a la estructura del proyecto, aislando el código por pantallas en el frontend y por modelos en el backend, hace que sea sencillo localizar el origen de posibles fallos o funcionalidades que necesiten una modificación, haciendo que el código sea fácil de mantener. A esto, hay que añadir que solo hay que mantener un código para todas las plataformas disponibles. En particular, las plataformas compatibles con este proyecto son Android e iOS. El código es fácilmente adaptable a web y escritorio, pero por falta de tiempo en este TFG no se ha llevado a cabo dicha adaptación. Durante el desarrollo del proyecto, han surgido muchas situaciones nuevas y se han descubierto nuevas tecnologías y herramientas. Para empezar, se ha hecho palpable la dificultad de hacer una estimación correcta durante la planificación, y más cuando no se conocen las tecnologías de desarrollo, 113 6.1. Trabajo futuro por ello es bueno tener un plan de actuación frente a los riesgos. También, la importancia de elegir una buena metodología para la situación concreta, en este caso, iterativa e incremental, ha sido muy importante porque ha permitido la adaptación de los requisitos y adaptar el ritmo de trabajo a los requisitos. Por otro lado, el realizar un despliegue real, con todo lo que ello conlleva en cuanto a configuración y otros detalles, también ha sido muy provechoso. Por último, tanto la automatización de pruebas para el código, como, sobretodo, las pruebas con usuarios reales han resultado ser de mucha ayuda para mejorar la aplicación, ya que desde el punto de vista del desarrollador, al conocerla perfectamente, hay ciertos escenarios que no se llegan a probar. A pesar de todo, se han quedado algunas características en el camino. Por ejemplo, no se ha implementado la selección de dificultad desde el frontend, si bien, el backend está preparado para ello. Algo que podría ser mejorado es la componentización de la parte frontend, después de haber adquirido cierta experiencia con React Native y con el propio proyecto, se ve claro que hay partes que deberían estar menos acopladas. Otra mejora podría ser migrar el código de JavaScript a TypeScript [83], ya que el tipado hace que el código se más entendible y a la larga hace que sea más fácil mantenerlo. Por último, hubiera sido interesante implementar integración continua en el backend, y puede ser interesante hacerlo en un futuro. En lo personal, el proyecto ha sido muy enriquecedor de principio a fin. Desde aplicar lo aprendido en la carrera en cuanto a planificación y estimaciones, hasta el aprender a usar herramientas nuevas como Expo o Swagger. Es cierto que en algunas partes se encontró mayor dificultad de la que se podía esperar, sobre todo por el desconocimiento de las tecnologías utilizadas. En definitiva, todo esto ha resultado en una experiencia muy interesante, similar a lo que podría ser el mundo laboral, y muy gratificante al ver el resultado final. 6.1. Trabajo futuro -Seguridad: añadir elementos para aumentar la seguridad, como por ejemplo: enviar un email al realizar el registro, requisitos de caracteres para la contraseña, comunicación por HTTPS y otros que puedan surgir. -Nuevos casos de juego: creando las pantallas correspondientes y ampliando la API REST con las llamadas necesarias. Por ejemplo, un modo de juego de entrenamiento, en el que el usuario pueda elegir las palabras a practicar en lugar de elegirse de forma aleatoria. -Multijugador: implementar desafíos por turnos o tiempo real contra otros jugadores. -Modo web: adaptar el código para que pueda compilar a web [84]. También habría que adaptar el diseño de la interfaz a escritorio [85]. -Diseño especifico para tablet: el juego corre perfectamente en tablets, pero el diseño es el mismo que en móvil. Una pantalla más grande se puede aprovechar mejor. Quizás pueda valer el mismo diseño que para escritorio. 114 Conclusiones -Accesibilidad: meter la opción de adaptar la interfaz para personas con algún tipo de discapacidad visual, auditiva o de otro tipo. -Internacionalizar servicios: por ejemplo, en la creación de usuario, los idiomas y países están sólo en inglés. Estaría bien que coincidieran con el idioma de la aplicación. -Añadir un apartado de instrucciones: dentro de la aplicación añadir una explicación breve de cómo jugar a cada modo de juego. -Solución de bugs: arreglar posibles bugs que vayan surgiendo. Sobre todo en el frontend, ya que el backend no tiene demasiada lógica más allá de las consultas a la base de datos. Lo más crítico durante el desarrollo en la parte del frontend ha sido el temporizador y la grabación de audios, así que, ante alguna acción no contemplada es probable que aparezca algún bug. -Elementos de gamificación: añadir elementos como rankings más específicos y sistemas de logros o trofeos. 115 B.1. Instalación del servidor npm run start Una vez veamos por consola el mensaje "Server running on port 3000", significará que el servidor ya está levantado. Mientras el servidor este arrancado, cada vez que se realice y guarde algún cambio en el código, el servidor se reinicia automáticamente para aplicarlo. B.1.2. Entorno despliegue B.1.2.1. Preparando el entorno Aquí se describe cómo desplegar el servidor en una máquina con sistema operativo Ubuntu 20.04.1 LTS. Para ello, se usa Nginx, para configurar el servidor proxy inverso, y PM2, el cual se encargará de mantener el servidor Node levantado. 1. Instalar un firewall básico [86]: # apt update # apt install ufw Permitimos el acceso vía ssh y habilitamos el firewall # ufw allow OpenSSH # ufw enable Una vez hecho esto, se recomienda usar un usuario con privilegios de administrador para seguir con el proceso, no se aconseja usar la cuenta de root por motivos de seguridad. 2. Instalar Nginx [45]: $ sudo apt update $ sudo apt install nginx Configuramos el firewall para que permita conexiones con Nginx $ sudo ufw allow ’Nginx HTTP ’ $ sudo ufw status Se puede comprobar que Nginx está activo con el siguiente comando $ systemctl status nginx Además si se accede a http://localhost, ahora aparece la página por defecto de Nginx. 3. Configurar Nginx: Primero, hay que crear un archivo de configuración. Substituir name_domain por el nombre de dominio correspondiente. 122 Manual de instalación y despliegue $ sudo nano / etc / nginx / sites - available / name_domain El contenido de este debe ser el siguiente: upstream api { server 127.0.0.1:3000; } server { listen 80 name_domain ; location / { proxy_pass http :// localhost :3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade ; proxy_set_header Connection ’upgrade ’; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade ; } location / api { proxy_pass http :// localhost :3000/ api ; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade ; proxy_set_header Connection " upgrade "; proxy_set_header Host $host; proxy_set_header X-Real -Ip $remote_addr ; proxy_set_header XForwarded - For $ prox y_ad d_x_forwarded_for ; proxy_set_header XForwarded - Proto $scheme ; proxy_redirect off; } } Lo siguiente es crear un link simbólico para activar el sitio: $ sudo ln -s / etc / nginx / sites - available / name_domain / etc / nginx / sites - enabled / Comprobar que el archivo de configuración es correcto: $ sudo nginx -t Por último, si la configuración es correcta, solo queda reiniciar Nginx: $ sudo systemctl restart nginx 4. Instalar Node.js [87]: $ sudo apt update $ sudo apt install curl $ cd ~ $ curl -sL https :// deb . nodesource . com/ setup_12 .x | bash - $ sudo apt install nodejs Si todo ha ido correctamente, se debe poder comprobar la versión de node: $ nodejs -v 123 B.1. Instalación del servidor Así como la versión de npm: $ npm -v Ahora necesitamos instalar el paquete build-essential para poder hacer funcionar ciertos paquetes de npm: $ sudo apt install build - essential 5. Instalar PM2 [88]: PM2 hace posible ejecutar en segundo plano aplicaciones para que puedan funcionar en segundo plano como un servicio. Se instala mediante npm: $ sudo npm install pm2 -g La opción -g hace que se instale de manera global y sea accesible desde todo el sistema. Es interesante hacer que PM2 se ejecute en el inicio del servidor, para esto escribir lo siguiente: $ sudo pm2 startup Y, por último, iniciar el servicio: $ sudo systemctl start pm2 - root . service 6. Instalar MongoDB [28]: Primero hay que importar la clave GPG: $ wget -qO - https :// www . mongodb .org / static / pgp / server -4.4. asc | sudo apt - key add - Crear el archivo lista. // Para Debian 10 " Buster " $ echo " deb http :// repo . mongodb .org / apt / debian buster /mongodb -org /4.4 main " | sudo tee / etc /apt / sources . list .d/ mongodb -org -4.4. list // Para Ubuntu 20 " Focal " $ echo " deb [ arch = amd64 , arm64 ] https :// repo . mongodb . org / apt / ubuntu focal / mongodb - org /4.4 multiverse " | sudo tee / etc / apt / sources . list .d/ mongodb -org -4.4. list Instalar los paquetes de MongoDB: $ sudo apt - get update $ sudo apt - get install -y mongodb - org =4.4.2 mongodb -org - server =4.4.2 mongodb -org -shell =4.4.2 mongodb -org - mongos =4.4.2 mongodb -org - tools =4.4.2 Iniciar MongoDB: $ sudo systemctl start mongod 124 Manual de instalación y despliegue Habilitamos MongoDB para que arranque de inicio: $ sudo systemctl enable mongod Para consultar los valores de la base de datos ejecutamos en el terminal: $ mongo > use ezlinguaDB Ahora se pueden ejecutar las consultas que se necesiten, por ejemplo, la siguiente devuelve los documentos de la colección games que son de tipo Puzzle: > show collections games sounds users > db . games . find ({" type ": " Puzzle "}) Después de llevar acabo estos pasos, el servidor ya está configurado. Lo siguiente será desplegar la aplicación. B.1.2.2. Desplegando la aplicación Nos movemos al directorio donde hemos descargado el proyecto y ejecutamos: $ npm i $ npm run deploy Si queremos parar el servidor, por ejemplo, para aplicar nuevos cambios, debemos ejecutar lo siguiente: $ npm run kill Después hay que volver a levantarlo. B.2. Aplicación cliente B.2.1. Entorno desarrollo Lo primero instalamos el CLI de Expo (versión 3.17.24 para asegurar compatibilidad con node 12.3.0): 125 B.2. Aplicación cliente npm install -g expo - cli@3 .17.24 Descargamos el código fuente y nos movemos al directorio que hayamos elegido y ejecutamos: npm i El proceso puede demorarse unos minutos. Una vez acabe ejecutamos: npm start Por defecto, la app apunta a la IP 192.168.1.133:3000 para conectar con el servidor. La opción recomendada es cambiar la IP del pc donde se esté ejecutando el servidor; otra opción es cambiar la IP desde el código de la app en el archivo /app/redux/api/utils.api.js. Si se apunta contra el servidor de desarrollo, todos los dispositivos deben estar conectados a la misma red para que haya comunicación. Una vez hecho esto veremos un codigo QR tanto en la consola como en el navegador, el cual tenemos que escanear con el dispositivo en el que queremos ejecutar la aplicación. Para poder ejecutar el código durante el desarrollo y así ver los cambios en tiempo real, se necesita instalar una aplicación, que se explica a continuación. B.2.1.1. Cliente para desarrollo en Android Se necesita descargar la aplicación Expo Go desde Google play [39]. Una vez descargada, desde la propia aplicación hay que escanear el código QR. B.2.1.2. Cliente para desarrollo en iOS Para iOS el proceso cambia un poco. Primero se descarga la aplicación Expo Go desde la App Store [40]. Una vez descargada, hay que escanear el código QR desde la aplicación de Cámara del dispositivo. B.2.2. Generando build Antes de proceder a generar los paquetes para los distintos sistemas operativos, hay que tener Expo CLI instalado, como se explica en la sección anterior, y los parámetros de configuración deseados en el archivo /App.json [89]. Además hace falta una cuenta de Expo.io, la cual se puede crear desde la consola una vez ejecutamos el comando build o directamente desde la página de Expo [27]. Desde esta página se puede ver el proceso de compilación y además guarda los paquetes generados durante treinta días. 126 Manual de instalación y despliegue B.2.2.1. Generando APK Desde el directorio donde tengamos descargado el proyecto, ejecutar: expo build : android La primera vez que se hace una build se muestra el siguiente mensaje: [ exp ] No currently active or previous builds for this project . Would you like to upload a keystore or have us generate one for you ? If you don ’t know what this means , let us handle it! :) 1) Let Expo handle the process ! 2) I want to upload my own keystore! Si no se tiene keystore, existe la posibilidad de que Expo la genere automáticamente. Si se elige la opción 1, después hay que ejecutar el siguiente comando para poder ver las credenciales y hacer una copia de seguridad de estas. expo fetch : android : keystore Estas credenciales son importantes, ya que sin ellas no podremos actualizar la app en Google Play. Cuando acabe el proceso se mostará por consola el siguiente mensaje, con el link desde el que hay que descargar el .apk. Build finished . Successfully built standalone app : [ link ] B.2.2.2. Generando iOS Ejecutar desde el directorio del proyecto: expo build :ios En este caso se necesita una cuenta de desarrollador de Apple para poder continuar con el proceso. Al igual que al generar el .apk, también se puede dejar que Expo gestione las credenciales, a elección de cada uno. B.2.2.3. Generando estáticos para web Ejecutar desde el directorio del proyecto: 127 B.3. Parámetros de configuración expo build :web Este comando genera los estáticos en la carpeta web-build. Sin embargo, para conseguir que la versión web funcione se requieren algunas modificaciones en el código original, ya que hay ciertas incompatibilidades que hacen que no llegue a arrancar. B.3. Parámetros de configuración En esta sección se va a hablar de las posibles configuraciones de la aplicación, tanto del backend como del frontend. B.3.1. Backend En el Backend hay, por un lado, el fichero /.env, que establece las siguientes variables de entorno: MONGODB_URL: URL de la base de datos Mongo. JWT_KEY: la clave publica que usa la API para la autenticación con JWT. PORT: puerto en el que se despliega el servidor. API_KEY_PATH: ruta al fichero JSON con los datos de autenticación de Google Cloud Platform. Ver apartado B.4 para el turorial de cómo generarlo. API_PROYECT_ID: id del proyecto de Google Cloud Platform. CONFIG_PATH: ruta al fichero de configuración que se quiere utilizar. Gracias a esta variable de entorno se pueden tener varios ficheros de configuración, y elegir aquí cual aplicar. De este fichero se habla en detalle en el siguiente apartado. El fichero .env no se puede cambiar en caliente, es decir, para que se apliquen los cambios hay que parar y desplegar el servidor. Por otro lado, esta el fichero de configuración /configs/config.default.js, que si se puede cambiar en caliente, y contiene un objeto JavaScript con los siguientes atributos: ASR: número de palabras que se quiere que devuelva el ASR. usersPath: ruta donde se guardará la información de los usuarios (logs y audios). filesPath: ruta donde están almacenados los ficheros JSON con las listas de palabras, con formato de nombre nombreLista_códigoPaís_códigoRegión.json. Los códigos con el estándar BCP-47 [78]. También en este archivo se puede configurar para cada modo de juego lo siguiente: 128 Manual de instalación y despliegue puntuation: puntuación por cada acierto en las partidas de ese modo. time: tiempo de cada ronda en las partidas de ese modo. rounds: número de rondas en las partidas de ese modo. Hay dos excepciones, el modo Exposure, que solo necesita el parámetro rounds. Y el modo Mixed, que en lugar del atributo time, tiene los atributos timeProunciation ytimePerception, que son, respectivamente, los tiempos para las rondas de pronunciación y percepción en el modo Mixto. B.3.2. Frontend En el frontend sólo hay un parámetro de interés en cuanto a configuración se refiere. Está en /app /redux/api/utils.api.js y es la URL a la que apunta para las conexiones con el backend. La variable se llama baseURL y cada vez que se cambie hay que generar los paquetes de nuevo y actualizarlos en la tienda correspondiente. B.4. Generar key para la API STT de Google En esta sección se explica, paso por paso, como obtener una key para las APIs de Google Cloud Platform, y como activar, en este caso, la API Speech-to-Text. Antes de empezar, lo primero que hay que hacer es crear una cuenta de Gmail, si no se tiene una. Una vez se dispone de la cuenta hay que acceder a la consola de Google Cloud Platform [82]. En este caso se va a crear una cuenta de prueba, que permite 3 meses de uso con un crédito de 300$ . Una vez se ha creado la cuenta en Google Cloud Platform, hay que acceder a la consola [90]. 1. Entrar en la sección APIs y servicios. La barra de búsqueda es de gran ayuda para moverse por la consola, ya que tiene multitud de secciones, y de primeras, puede resultar muy compleja. Figura B.1: Paso 1. 129 2. Entrar en el apartado de Credenciales y pulsar Crear credenciales. Figura B.2: Paso 2. 3. Elegir Cuenta de servicio. Figura B.3: Paso 3. 4. Escribir un nombre y una descripción y dar a Crear. El ID se genera automáticamente. En esta pantalla no hace falta rellenar nada más. Figura B.4: Paso 4. 5. Volver al apartado de Credenciales y buscar, en Cuentas de servicio, el que se ha creado. Pulsar encima para entrar a los detalles. Figura B.5: Paso 5. 6. Donde pone Claves, hay que pulsar Añadir clave y, posteriormente, Crear clave. Figura B.6: Paso 6. 7. Para este caso, se necesita la clave en formato JSON. Seleccionar éste y dar a crear, después, automáticamente se descargara la clave en nuestro ordenador en un fichero JSON. Figura B.7: Paso 7.