Diseño y Programación Orientados a Objetos
1er. Sem 2019
Tarea 3: Semáforos como Objetos de Software

Lea detenidamente la tarea. Si algo no lo entiende, consulte en clases. Si es preciso, se incorporarán aclaraciones al final.
Objetivos de la tarea:
* Ejercitar la configuración de un ambiente de trabajo para desarrollar aplicaciones en lenguaje C++ (se sugiere trabajar con Jgrasp o Eclipse )
* Reconocer clases y relaciones entre ellas en lenguaje C++.
* Ejercitar la entrada y salida de datos en C++.
* Ejercitar la preparación y entrega de resultados de software (creación de makefiles, readme, documentación, manejo de repositorio -GIT).
* Familiarización con una metodología de desarrollo "iterativa" e "incremental". 

Descripción General

  En esta tarea se pide modelar semáforos en una intersección de calles. En particular analizaremos el funcionamiento de los semáforos ubicados en la intersección de Avenida Sporting Club con 1 Norte en Viña del Mar , ver Figura 1.

Figura 1: Cruce a considerar: Intersección de Avenida Sporting Club con 1 Norte (Captura de pantalla tomada de Google Maps)

En esta intersección encontramos semáforos vehiculares y peatonales. En su operación actual regulan flujos vehiculares de 1 Norte desde la costa hacia el interior o con giro a la izquierda hacia Sporting, flujos vehiculares de 1 Norte desde el interior hacia la costa o con giro a la derecha hacia Sporting, flujos vehiculares saliendo de Sporting con giro a la izquierda o derecha, paso peatonal en 1 Norte y paso peatonal en Sporting. Si bien el giroo a la izquierda saliendo de Sporting es prohibido en horas de la mañana, no considere esta restricción en esta tarea.

En Chile los semáforos son de 3 etapas: Rojo, Verde, Amarillo, para luego volver al Rojo. Las etapas de semáforos peatonales son: Rojo, Verde, Verde parpadeante, para luego volver a Rojo. Los semáforos de giro se muestran con flecha verde, fecha parpadeante o amarillo y flecha apagada o rojo.

En esta intersección el semáforo peatonal de 1 Norte tiene botón de solicitud y el peatonal de Sporting no lo tiene. Al llegar a Sporting subiendo por 1 Norte, esta calle tiene 3 pistas. La de más a la izquierda cuenta con un sensor inductivo en el pavimento. Así sólo se autoriza el giro a izquierda hacia Sporting si hay vehículos en esa pista.

Modelo para Semáforos

Se modelarán los tipos de semáforo existentes en esta intersección.  Usted puede acudir a esa intersección o bien puede recorrer la intersección usando Street View de Gooogle Maps para identificar los tipos de semáforos presentes en esa intersección. Algunas vistas de esos semáforos está en Figura 2.



a) Vehicular de 3 luces 

b) Giro y de giro simple

c) Peatonal con botonera

d) Peatonal sin botonera

e) Controlador de semáforos

Figura 2: Algunos tipos de semáforos presentes en intersección de las avenidas 1 Norte con Sporting Club

Para modelar un semáforo consideremos que todo semáforo tiene 3 estados, así como se sugirió en tarea 2.

Cada estado de un semáforo puede ser almacenado en un atributo de éste. Otros atributos de un semáforo pueden ser los tiempos que las luces verde y amarillo deben permanecer encendidas. Normalmente la duración del rojo del semáforo "S" depende de la secuencia de otros semáforos antes de volver "S" a estado verde. Por esta razón la duración del rojo puede corresponder a la duración de la secuencia completa involucrando otros semáforos.

Un "semáforo de 4 luces" es un semáforo que tiene 3 luces y además otro semáforo con una luz verde que parpadea para indicar cercanía a su término. Es decir los podríamos modelar como 2 semáforos separados.

Un semáforo peatonal puede ser modelado como un semáforo de dos luces.

Un botón puede ser modelado como una valor booleano que normalmente está en falso y pasa a verdadero cuando es accionado mientras la luz está en rojo. Luego su estado vuelve a falso nuevamente cuando la luz pasa de parpadeante a rojo.

Un sensor inductivo se comporta de manera similar a un botón. Tiene un valor booleano normalmente en falso y pasa a verdadero cuando estando en rojo un auto pasa sobre él. Luego su estado vuelve a falso cuando la luz que controla pasa de verde parpadeante a rojo.

Los semáforos normalmente trabajan en grupos paralelos, es decir, dos o tres de igual tipo y con encendidos de manera sincrónica para ue sean vistos desde distintas posiciones. Si bien la extensión para manejar esta situación no es compleja, en esta tarea se pide programar un solo semáforo para controlar cada flujo vehicular o cruce peatonal.

Además de los semáforos, usted podría haber notado que cercano a una intersección hay un controlador de la secuencia de los semáforos (Figura 2.e). Esta caja recibe la información de la(s) botoneras y los sensores inductivos para mantener una secuencia predefinida o variarla para introducir verde en alguna de las direcciones controladas por la presencia de alguna solicitud vía botón o sensor inductivo.

Así, el sistema de semáforos de la intersección mencionada se puede modelar como se muestra en Figura 3.

Figura 3: Modelo tarea para semáforos en intersección Avenida Sporting Club con 1 Norte

Siguiendo un lazo repetitivo, el controlador va otorgando autorización de avanzar a cada flujo. Como cada semáforo tiene su tiempo de autorización de avance y alerta de cambio ("amarillo"), el controlador obtiene esos tiempos desde cada semáforo, cambia la señal a avance, espera que pase el tiempo correspondiente, luego cambia al señal de alerta de cambio (amarillo), y finalmente vuelve a señal de detención ("rojo") cuando concluye el tiempo de alerta de cambio ("amarillo").  En una intersección, la duración de un semáforo en "rojo" depende de los tiempos de "verde" y "amarillo" de los otros semáforos. Esa secuencia la maneja el controlador.

Para simular la acción de transeúntes esperando por cruzar y la presencia de vehículos deseando doblar a la izquierda para seguir Avenida Sporting (activan el sensor inductivo), se usará un archivo de texto cuyas líneas siguen el formato:

< 1 | 0 >  <tab>  < 1 | 0 >

Un ejemplo para una línea sería:

1    0  

Cada línea representa el estado de los dos sensores luego de transcurrir un segundo. Es decir el programa avanza el tiempo en un segundo y lee una nueva línea. El orden representa el estado de botonera cruce de 1 Norte y sensor inductivo.  Si el primer valor indica 1, significa que en ese momento un usuario presionó el botón para cruzar 1 Norte. Si el segundo indica 1, significa que un auto está sobre o paso por el sensor inductivo. Un valor 0 significa carencia de activación.

Como salida, su programa enviará a la salida estándar líneas con el siguiente formato para la primera línea y las siguientes:

<tab>  A   <tab>   B   <tab>   1  <tab>   2  <tab>   3  <tab>   4  <tab>   5    // sólo la primera línea, este comentario no va en la salida

<tiempo en [s]> <tab> <V | P | R> <tab> <V | P | R> <tab> <V | A | R> <tab> <V | A | R> <tab>  <V | A | R> <tab> <V | A | R> <tab>  <V | A | R>  // las restantes líneas

Los primeros dos V, P o R corresponden al estado de los semáforos peatonales (V -> Verde, P -> Parpadeo,  R -> Rojo), primero cruce 1 Norte (A) y luego cruce Sporting (B).

Luego se muestra el estado de los semáforos 1, 2, 3, 4, y 5 (Verde, Amarillo o Rojo) .

Desarrollo de la Tarea en Etapas

Para llegar al resultado final de esta tarea, usted aplicará la metodología "Iterativa e Incremental" para el desarrollo de software. Junto a su grupo usted irá desarrollando etapas que abordan en cada ciclo (o etapa) incrementalmente los requerimientos de la tarea. En cada etapa usted obtendrá una solución que funciona para un subconjunto de los requerimientos finales y será un avance hacia el resultado final. Su grupo deberá entregar una solución para cada una de las etapas aún cuando la última integre las primeras. Los archivos de readme, documentación y otros sólo se deben adjuntar a la última etapa. Esto tiene por finalidad, familiarizarse con la metodología de desarrollo de software "iterativo e incremental".

Primera Etapa: Semáforo Vehicular

En esta etapa se pide implementar la clase StreetTrafficLight como clase hija de TrafficLight. Considera aquí un diseño similar al de la tarea 2.

Desarrolle el programa de prueba la clase TestStage1. En un loop de N ciclos (N es un parámetro del programa), TestStage1 hará cambiar las luces de un semáforo generando una salida con formato de línea:

<tiempo en [s]> <tab>  <V | A | R>

Para ejecutar esta etapa, usted usa:

$ ./TestStage1 <N> <redTime>

N es el número de ciclos de la secuencia completa del semáforo y readTime corresponde al tiempo en que este semáforo estará en rojo.

Segunda Etapa: Semáforo peatonal con botonera

Para esta etapa usted debe revisar el código de ayuda para la clase Timer. Revisando su código main y makefile, analice cómo usar esta clase. Usted es libre de usar otras clases para realizar una funcionalidad similar a la clase Timer usada en Java.

En esta etapa se pide implementar las clases DetectorDeRequerimiento, SemaforoP, Controlador, SimuladorEntradas. La clase DetectorDeRequerimiento solo tiene un booleano como estado y los siguientes métodos:

public: boolean isON(); {...}

public void setOn(); {...}

public void setOff();{...}

Use sobrecarga de operadores para mostrar el estado del semáforo por la salida.

Notar que la clase DetectorDeRequerimiento puede generar instancias para solicitar verde de un semáforo peatonal (botón) o instancias para solicitar girar (sensor inductor).

La clase SemaforoP, al igual que todos los semáforos, tiene como atributo el tiempo de cruce y el tiempo de alerta de fin de autorización. Además puede tener un atributo para almacenar cada uno de estos tres estados del semáforo. Métodos de la clase SemaforoP son:

public: SemaforoP(int greenTime, int blinkingTime); {...}

public void turnRedLightOn(); {...}

public void turnGreenLightOn(); {...}

public void turnGreenLightOff(); {...}

public int getGreenLightTime(); {...}

public int getBlinkingTime(); { ...}

Use sobrecarga de operadores para mostrar el estado del semáforo por la salida.

La clase Controlador tiene como atributos un semáforo peatonal y un botón. En su constructor recibir ambos objetos.

public: void Controlador (SemaforoP semp, DetectorDeRequerimiento boton); {...}

Controlador además tiene el método:

public: void manageTraffic(); {...}

En este método el controlador mantiene el semáforo en rojo y cada un segundo verifica si el estado del botón ha cambiado. El archivo de entrada debe tener el siguiente formato:

< 1 | 0 >

0 indica botón no presionado, 1 lo contrario

Cuando el botón pasa a estado activo (1), el controlador lleva el semáforo a verde por el tiempo que él indica, luego lo hace parpadear y finalmente lo vuelve a llevar a rojo y vuelve a verificar el estado del botón cada un segundo.
En esta etapa los cambios ocurrirán emulando el tiempo real; es decir, en efecto el controlador dormirá (sleep) por cierto tiempo antes de invocar un cambio de color en semáforo. Para dejar su programa "dormir" usted puede invocar el método sleep. Aquí usted puede ver un ejemplo de uso una clase similar a Timer de java y un ejemplo de su uso  este código fue probado en sistema operativo linux (como aragorn).

En esta etapa, la clase SimuladorEntradas tiene como atributo el botón y una referencia a un archivo de entrada. Uno de sus constructores debe ser:

public: void SimuladorEntradas(DetectorDeRequerimiento boton, string filename); {...}

filename es el nombre del archivo de entrada que contiene líneas que indican la solicitud de usuarios (una línea corresponde a un segundo, en cada línea habrá un 1 ó un 0). Cuando SimuladorEntradas encuentra un 1 (activación), invoca el método correspondiente del botón.

La clase SimuladorEntradas debe implementar la clase abastracta Listener (del código de ayuda entregado), la cual obliga implementar el método:

public: void actionPerformed(); {...}

Esto es necesario para hacer uso de una instancia de la clase MyTimer, la cual permitirá invocar el método actionPerformed repetidamente y en paralelo con la ejecución del controlador (sería el programa de prueba del ejemplo). Así es posible emular eventos en el botón al mismo tiempo que el controlador cambia el estado del semáforo peatonal. Cuando se llega al fin de archivo de eventos de botón, el programa debe terminar invocando exit(0);

Finalmente usted debe crear el programa de prueba la clase TestStage2 la cual debe generar instancias de DetectorDeRequerimiento, SemaforoP, Controlador, y SimuladorEntradas. En su función método main debe crear una instancia de MyTimer con argumento SimuladorEntradas para comenzar la lectura de los eventos de entrada definidos en el archivo para el botón. La creación de instancia de MyTimer inicia una ejecución paralela (otra hebra) al código de creación de esa instancia.

Como salida se espera una salida por pantalla de formato:

<tab>  A    // sólo primera línea

<tiempo en [s]> <tab> <V | P | R>   // todas las restantes

La ejecución de esta etapa debería ser del tipo:

$./TestStage2 <nombre del archivo de eventos de entrada>

Tercera Etapa: Semáforo de giro

En analogía a la etapa 2 desarrolle la clase SemaforoDeGiro la cual se espera se modele de forma similar al semáforo peatonal.

Esta etapa debería ser simple de desarrollar una vez desarrollada la etapa previa.

Modifique la clase Controlador, en particular su constructor según:

public: void Controlador ( SemaforoDeGiro semg, DetectorDeRequerimiento sesorInductivo); {...}

Cree el programa de prueba la clase TestStage3 para mostrar por la salida estándar el estado del semáforo de giro conforme autos se ubican sobre él (esto se modela en el archivo de entrada poniendo 1 en el tiempo en que llega un vehículo sobre el sensor).

El archivo de entrada y la salida a pantalla son análogos a la etapa previa.

La ejecución de esta etapa es como la previa:

$./TestStage3 <nombre del archivo de eventos de entrada>

Cuarta Etapa: Control de Tránsito en intersección Avenida Sporting Club con 1 Norte

Modifique la clase Controlador para admitir los tipos de semáforos presentes en esta intersección. Modifique el método manageTraffic para dar el paso a cada flujo de personas o vehículos según corresponda y siguiendo el orden que la esquina real asigna, excepto que su controlador sólo autoriza el cruce a peatones en 1 Norte luego de haber presionado su botón y permiso de giro a la izquierda de 1 Norte a Sporting sólo cuando un auto active el sensor magnético.

Modifique la clase SimuladorEntradas para activar los requerir paso peatonal o giro según se indique en archivo de entrada, use formato señalado en la sección Descripción General de la tarea.

Cree el programa de prueba la clase TestStage4 para mostrar por la salida estándar el estado de cada semáforo siguiendo el formato descrito en la sección Descripción General.

La ejecución de esta etapa debería ser del tipo:

$./TestStage4 <nombre del archivo de eventos de entrada>

Extra Créditos: Generación de gráfico a partir de la salida usando formado csv.

Esta parte es voluntaria. Si la desarrolla, su grupo puede aspirar a 5 puntos adicionales (la nota final se satura en 100%). Redirija hacia un archivo la salida de una ejecución de su programa donde se aprecie la interacción de ambos semáforos peatonales y sensor de giro. Importe el archivo resultante en una planilla excel y genere en su planilla un gráficos para mostrar el estado de cada semáforo en el tiempo. Ponga sus curvas gráficos alineadasos verticalmente para apreciar el estado de cada semáforo alineado verticalmente con el estado de los otros semáforos. Incluya ese gráfico en la documentación de su tarea.

Aspectos generales:

* Los grupos sólo deben estar constituidos por alumnos de un mismo paralelo.
* Si su grupo no lograra concluir todas las etapas, envíe hasta donde hayan llegado, documentando la etapa de mayor nivel lograda.
* Revise las instrucciones para la realización de tareas.
* Para enviar los datos a un archivo de salida, redireccione la salida a pantalla usando:
$ ./StageX  <parámetros>  >  miSalida.csv
  Si usted quiere hacer un gráfico temporal de las salidas, usted puede tratar este archivo como si fuera planilla electrónica. Usted podrá usar "tabs" y/o "comas" como separadores de columnas.

* No dude en consultar al profesor o ayudantes sobre dudas de esta tarea.