En esta unidad didáctica 3 vamos a continuar con el trabajo desarrollado en la anterior, incorporando a nuestro estudio los bloques de Representación y Razonamiento Lógico.
El primero de ellos, el bloque de Representación engloba los procesos necesarios para que la información procedente del bloque de Percepción sea representada adecuadamente de modo que podamos simplificar los procesos posteriores. Por otro lado el bloque de Razonamiento Lógico determina el comportamiento del sistema de Inteligencia Artificial, es decir, establece la forma en la que se aplican las acciones al entorno y se toman las decisiones necesarias para que la respuesta obedezca la motivación planteada.
Así que partiremos de un estudio empírico sobre las localizaciones objeto del trabajo en el presente proyecto tal y como se puede ver en el gráfico siguiente:
Como podéis observar, un sistema de representación como el que se muestra en esta imagen simplifica la compresión del lector y por lo tanto la implementación de los bloques posteriores. En dicha representación podemos identificar las 4 localizaciones con las que venimos trabajando, pero también los lugares de tránsito.
Igualmente, a través de un estudio empírico, hemos dispuesto los tiempos que nos lleva pasar de un punto a otro del sistema. Estos tiempos no son minutos, sino más bien una ponderación, unos pesos utilizados por el sistema para alcanzar la ruta más rápida y por ello aplicar el Razonamiento Lógico de nuestro sistema IA.
Necesitamos que en los dispositivos móviles tengamos instalados estas dos aplicaciones:
RECURSOS:
Carpeta Drive con Imágenes y Proyecto
ENLACES:
Para el diseño de la App en lo que a componentes se refiere os dejo nuevamente un vídeo con una introducción a aquellos que he añadido en esta segunda fase. Os recomiendo de nuevo importar el proyecto que he dejado en la carpeta Drive anterior y de ese modo podáis ver con detenimiento cómo quedan las propiedades de cada componente.
Igualmente, insisto en que es más que recomendable continuar duplicando el proyecto de la UD2 y seguir experimentando hasta conseguir ciertas habilidades en el trabajo con MIT App Inventor.
Comenzamos con la definición de variables globales. Nuevamente recordar el concepto de variable informática como el un espacio en la memoria del programa asociado un nombre.
El conjunto de variables globales (accesible en todo el programa), es el siguiente:
Comentar un poco algunas de éstas. Por ejemplo tenemos Var_Origen que toma el valor registrado desde la Screen1, Var_NombreRutas con todos los puntos por los que debemos pasar, no sólo las localizaciones registradas en la misma variable que la práctica de la UD2; Var_NombreLocalizaciones. Tenemos también la variable Var_Tiempos como la lista del tiempo que tardamos en ir de una localización a otra y otras variables cuyo significado iremos viendo poco a poco.
Una vez las tengáis definidas, es recomendable que minimicéis al menos las listas para que ocupen menos espacio. Para ello, basta con pinchar doble clic sobre la parte superior izquierda.
A continuación modificamos dos funciones de la unidad anterior UD2; al iniciar la Screen2 y al pulsar el botón de Altavoz. El resto las he dejado minimizadas porque no se modifican, se quedan tal y como estaban programadas. Eso si, es recomendable ver que no hay errores en dichas funciones principalmente a la hora de haber cometido errores en el nombre de variables.
Para empezar vamos a crear varios procedimientos con esos nombres. Estos procedimientos se pueden añadir desde la parte de bloques integrados (parte superior) dándoles en cada caso su nombre y configurando a través del símbolo del engranaje aquellos casos en los que el procedimiento necesita de algunos parámetros, como es el caso de ImprimirSecciones o ImrpimirImagenesOrigenDestino. Eso si, de momento los dejaremos así sin programar, pero ya pudiendo ser usados en el resto del código.
Una vez inicializadas las etiquetas correspondientes a la localización del Origen y cargar enla Lista_Localizaciones todas las posibles vías, vamos a programar el bloque que se ejecutará cuando pulsemos el botón Destino, aunque recordemos que no es un botón, sino un objeto de tipo Selector de Lista.
Como podemos ver, primero sacamos el número de las localizaciones de origen y destino dentro de la lista de Rutas. Este proceso nos es necesario para luego recorrer las localizaciones y calcular el tiempo que necesitamos en la búsqueda de la ruta más rápida.
A continuación si no hemos seleccionado como destino el mismo lugar en el que estamos entonces reflejamos el destino en la etiqueta correspondiente, ocultamos el selector de destino y mostramos el panel de Ruta que estaba oculto.
La programación finaliza con la llamada al procedimiento CalculaRutas que hemos creado anteriormente pero aún no programado.
Comenzaremos programando en esta sesión el cálculo de la ruta más rápida. Para ello comenzamos creando variables locales, que son aquellos que sólo se pueden utilizar dentro de este procedimiento.
A continuación comenzamos dos recorridos, uno incrementando con el contador auxiliar desde el punto de origen hasta el de destino, sumando los tiempos y el número de saltos (secciones) de cada paso, y otro a continuación en el que el contador va en sentido opuesto, componiendo un código casi idéntico por lo que podemos usar la opción de duplicar bloques. Eso sí, hay que tener en cuenta que cuando se hace el recorrido al revés, los tiempos se deben ir sumando justo después de decrementar el contador (esta pequeña diferencia se la agradecemos a nuestro compañero Carlos que se dio cuenta del error). Vale la pena como ejercicio propuesta o reflexión para nuestro alumnado.
Al finalizar comparamos los tiempos y la ruta más rápida es la elegida. A esto llamamos "Razonamiento Lógico" y aunque no es un sistema del todo inteligente, si que nos sirve para hacer entender en qué consiste la representación y el razonamiento. Veamos cómo queda:
Vayamos entonces a programar este bloque de "RepresentaciónRutas". Quizás sea el más complejo de entender. Trataremos de explicarlo. Recomiendo ampliarlo pinchando en botón derecho sobre la imagen y abrir en una nueva pestaña, aunque también puede verse dentro del proyecto proporcionado.
Para empezar, la programación de este procedimiento se divide en dos parte bastante bien diferenciadas por la declaración de una variable local llamada ContadorAuxiliar.
En la parte superior tenemos un bucle con varias condiciones, cuyo objetivo es marcar el estado en el que el usuario se encuentra de alcanzar su destino. Como vemos cada una de las 3 condiciones nos lleva a unos procedimientos, que aunque aún no están programados, si que parece que mostrarán al usuario en el principio o final de la ruta hacia su punto destino. Por ejemplo el primer condicional se pregunta si el número de secciones (pasos entre estancias) es 1, entonces directamente estamos en el UltimoPaso y por lo tanto sólo veremos el salto siguiente final. En el segundo condicional la cuestión es si estamos al principio de la ruta hacia el destino y en el último condicional lo que mira es si hemos llegado al final con un número de secciones (pasos) diferentes a 1.
Una vez establecidos estos condicionantes, tenemos una segunda parte del código en el que definimos una variable local llamada ContadorAuxiliar que nos permitirá ir recorriendo los diversos pasos de la ruta a través de los puntos que haya calculado el procedimiento CalculaRutas. En estos condicionales se puede observar como tenemos en cuenta que la ruta se recorra en una dirección u otra (de ahí la variable Var_Dirección que si recuerdas almacena (del procedimiento CalculaRutas) el valor de 1 o -1 según vaya en un sentido u otro.
Una vez establecidos con el ContadorAuxiliar el siguiente paso o salto, entonces llamamos al procedimiento ImprimirSecciones (al que hay que configurar mediante el símbolo del engranaje que admita de entrada dos variables que llamaremos SecciónOrigen y SecciónDestino).
Vayamos ahora con este procedimiento llamado ImprimirSecciones. Es un procedimiento que no tiene ningún problema de entender, pues lo único que hace es preguntar origen y destino y en función de éstos muestra por pantalla una foto u otra a la par que pone información de ruta. Para su programación recomiendo usar la opción de duplicar, pues todos los condicionantes (16 en total) mantienen la misma estructura.
Como podemos ver, es un bucle muy sencillo y repetitivo que requiere más trabajo que otra cosa, pero nada complicado de entender. Eso sí, este procedimiento llama ahora al procedimiento ImprimirImagenesOrigenDestino que es el encargado de que esos valores que hemos dado a las variables se refleje en la pantalla.
Vamos con el bloque ImprimirImagenesOrigenDestino que se encarga de pintar las fotos y poner los nombres de las secciones que se recorren.
Como podemos ver es un bloque de código muy sencillo que refleja en las componentes de la pantalla las variables que recoge de la llamada anterior. Vamos ahora con los bloques de PrimerPaso y UltimoPaso.
Como podéis ver, estos procedimientos simplemente muestran y ocultan los botones de navegación adecuados a cada una de las situaciones. Eso sí, ahora queda programar lo que harán en caso de ser pulsados, así que añadimos los eventos de estos botones.
A través del evento que se ejecuta al pulsar sobre el Botón Btn_Siguiente lo que hacemos es que dependiendo de la dirección aumentamos o disminuimos el contador, teniendo en cuenta que si llega al final del camino se inicie en el punto siguiente para que sea cíclico, es decir, si estamos en dirección creciente y llegamos a 8 pues que lo inicie en 1. Por último mostramos el botón Btn_Previo y llamamos a RepresentaciónRutas.
Vamos con el Btn_Previo:
Podemos hacer uso del código del Btn_Siguiente, eso sí, atento a las correcciones porque en este caso los incrementos/decrementos y condicionales tienen valores correspondientes a la acción de ir al paso anterior. Por lo demás es prácticamente igual. En cuanto al Btn_Llegada queda tal y como se ve a continuación.