Diseño y Programación Orientados a Objetos
1er. Sem 2019
Tarea 1: 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 Java (se sugiere trabajar con Jgrasp o Eclipse )
* Modelar objetos reales como objetos de software.
* Reconocer clases y relaciones entre ellas en códigos fuentes Java.
* Ejercitar la extensión de clases dadas para satisfacer nuevos requerimientos.
* Ejercitar la entrada y salida de datos.
* Conocer el formato .csv y su importación a una planilla electrónica.
* 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 Matta con Los Placeres, ver Figura 1.

Figura 1: Cruce a considerar como ejemplo: Intersección de Avenida Matta con Los Placeres

En esta intersección encontramos 5 conjuntos de semáforos, que en su operación actual regulan lo siguiente: flujo vehicular bajando por Matta, flujo vehicular viniendo desde la derecha para seguir derecho por Los Placeres, flujo vehicular viniendo desde la derecha por Los Placeres y girarán a la izquierda para subir por Matta, flujo vehicular viniendo desde la izquierda por Los Placeres, cruce peatonal en Matta, y cruce peatonal en Los Placeres.

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.

A diferencia de los semáforos peatonales de esta intersección, en esta tarea los peatones deberán presionar un botón para solicitar se incluya el verde para ellos. Otra diferencia en esta tarea será la inclusión de un modelo para un sensor inductivo en el pavimento en la pista de los automóviles para doblar a la izquierda viniendo desde Los Placeres para subir por Matta. Quizás usted no haya notado este tipo de sensores de presencia de vehículos. En la pista señalada aquí no hay este tipo de sensor, pero sí se encuentra en otras pistas de la ciudad con el propósito de habilitar el giro a la izquierda sólo si hay autos esperando por ello. La Figura 2 muestra la apariencia de tales sensores.

Figura 2: Sensor inductivo para habilitar giro, caso 1 Norte para doblar hacia Los Castaños en Viña.


Modelo para Semáforos

Se modelarán dos tipos de semáforos: de tres luces como el de la Figura 3 y de cuatro luces como el de la Figura 4. También se creará objetos de software para un tipo de semáforo peatonal como el mostrado en Figura 5.



Figura 3: Semáforo de 3 luces 

Figura 4: Semáforo de 4 luces 

Figura 5 Semáforo peatonal con botonera

Figura 6: Controlador de semáforo

Para modelar un semáforo consideremos el semáforo tiene 3 luces. Reconocemos aquí el objeto luz de las cuales un semáforo tiene 3 como atributos. 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áfores antes de volver S a verde. Por esta razón la duración del rojo no es definida por cada semáforo sino por 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 una luz verde que parpadea para indicar cercanía a su término. Es decir los podríamos modelar como objetos 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 a verde.

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 a verde.

Los semáforos normalmente trabajan en parejas, es decir, dos de igual tipo y con encendidos de manera sincrónica. Si bien la extensión para manejar esta situación es simple, en esta tarea se pide un solo semáforo para controlar cada flujo de vehículos o peatones.

Además de los semáforos, usted podría haber notado que cercano a una intersección hay una caja como la mostrada en Figura 6. Se trata del sistema controlador de la secuencia de los semáforos. 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 7.

Figura 7: Modelo tarea para semáforos en intersección Matta-Los Placeres

Siguiendo un lazo repetitivo, el controlador va otorgando autorización de avanzar a cada flujo. Como cada semáforo tiene su tiempo de verde y amarillo, el controlador obtiene esos tiempos desde cada semáforo, cambia la luz que debe encenderse y espera que pase el tiempo correspondiente luego cambia al color amarillo de manera similar y finalmente vuelve a rojo cuando concluye el tiempo de amarillo.  Así la duración de un semáforo en rojo depende del paso a verse y amarillo de los otros semáforos. Esa secuencia la maneja el controlador.

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

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

Cada línea representa el estado de los tres sensores luego de un segundo transcurrido. Es decir el programa deja pasar un segundo y leerá una nueva línea. El orden representa el estado de botonera cruce Placeres, botonera cruce Matta, y sensor inductivo.  Si primer valor indica 1, significa que en ese momento un usuario presionó el botón para cruzar Placeres. Si el tercero indica 1, significa que un auto está sobre o paso por el sensor inductivo. Un valor 0 significa que el botón no está presionado.

Como salida, su programa enviará a la salida estándar líneas con el siguiente formato:

<tiempo en [s]> <tab> <1 | 0> <tab> <1 | 0> <tab> <1 | 0> <tab> <2 | 1 | 0> <tab> <2 | 1 | 0> <tab>  <2 | 1 | 0> <tab>

Los primeros dos 1 ó 0 corresponden al estado de los semáforos peatonales (1 -> Verde, 0 -> Rojo), primero cruce Placeres y luego cruce Matta.

Luego se muestra el estado de la luz de giro (verde o apagada)

Luego se muestra el estado de los tres semáforos (verde, amarillo o rojo). Primero flujo Placeres hacia Valparaíso, luego flujo Placeres Viña y finalmente flujo bajando Matta.

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 irán abordando gradualmente 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. Esto tiene por finalidad, familiarizarse con la metodología de sesarrollo de software "iterativo e incremental".


Primera Etapa: Semáforo de tres luces

En esta etapa se pide implementar la clase Semaforo3 para un semáforo de tres luces las cuales serán almacenadas como tres atributos booleanos. Además tendremos como atributos el tiempo en verde y el tiempo en amarillo será un atributo estático de la clase y su valor será de 3 segundos.

Como métodos, la clase Semaforo3 debe incluir:

public Semaforo3 (int greenTime) {...}

public void turnRedLightOn() {...}

public void turnYellowLightOn() {...}

public void turnGreenLightON() {...}

public int getGreenTime() {...}

public static int getYellowLightTime() { ...}

public String toString() {...}

Desarrolle la clase TestStage1. En un loop de N segundos o N ciclos (N es un parámetro del programa, usted indique en  archivo readme si es su solución corresponde a segundos o ciclos del semáforo), TestStage1 hará cambiar las luces del semáforo generando una salida con formato de línea:

<tiempo en [s]> <tab>  <2 | 1 | 0>

Para ejecutar esta etapa, usted usa:

$ java TestStage1 <N> <redTime>

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 y comprender el ejemplo InnerClassTest.java visto en clases. En esta etapa usted no requiere ocupar clases anidadas, pero sí ocupará la clase Timer (ya existente 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(){...}

public String toString(){..}

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 los semáforos, tiene como atributo el tiempo de verde y el tiempo de parpadeo. Además tiene dos luces que pueden ser representadas por dos valores booleanos. 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() { ...}

public String toString(){..}

La clase Controlador tiene como atributos un semáforo peatonal y un boton. En su contructor recibir ambos objetos.

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

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. Cuando el botón pasa a estado activo, 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 etado 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 estático Thread.sleep(lomg millis). Aquí usted puede ver un ejemplo de uso de este método. Usted debe poner el llamado a sleep dentro de la sentencia try {....} catch(..) {..} similar a la del ejemplo. try-catch se usa para el manejo de excepciones (errores en tiempo de ejecución), tema a cubrir más adelante.

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

public 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 interfaz ActionListener, la cual obliga implementar el método:

public void actionPerformed(ActionEvent event) {...}

Esto es necesario para hacer uso de una instancia de la clase Timer, la cual permitirá invocar el método actionPerformed repetidamente y en paralelo con la ejecución del controlador. 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 System.exit(0);

Finalmente usted debe crear la clase TestStage2 la cual debe generar instancias de DetectorDeRequerimiento, SemaforoP, Controlador, y SimuladorEntradas. En su método main debe crear una instancia de Timer con argumento SimuladorEntradas e invocar su método start() para comenzar la lectura de los eventos de entrada definidos en el archivo para el botón. La invocación a start() del la instancia de Timer inicia una ejecución paralela (otra hebra) y el método main continúa en la siguiente instrucción. Así usted podrá en el método main invocar a continuación el método manageTraffic el cual generará la salida de los estados del semáforo peatonal.

Nota: Mecanismos distintos a Timer para generar el mismo efecto son posibles de usar si lo desea, aquí se sugiere usar Timer porque es el mecanismo visto en clases.

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

$java 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. Modifique la clase Controlador, en particular su constructor según:

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

Cree 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 archvio de entrada poniendo 1 en el tiempo en que llega un vehículo sobre el sensor).

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

Cuarta Etapa: Control de Tránsito en intersección Los Placeres con Avenida Matta

Modifique la clase Controlador para adminitir los tipos de semáforos presentes en esta intersección. Modifique el método manageTraffic para dar le 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 da el paso a peatones y perminso de giro a la izquierda de Placeres a Matta solo 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 la clase TestStage4 para mostrar por la salida estándar el estado de cada semáforo sigueindo el formato descrito en la sección Descripción General.

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

$java 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 prupo 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. Inporte el archivo resultante en una planilla excel y genere en su planilla un gráficos para mostar el estado de cada semáforo en el tiempo. Ponga sus gráficos alineados 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 ser 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:
$ java 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 "comas" como separadores de columnas.

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