package art.servers.rtzserver.utils; import art.library.model.devices.colors.controller.RTZ32.RTZ32_Controller; import art.library.model.devices.colors.controller.RTZ32.RTZ32_ControllerInformation; import art.library.model.devices.colors.controller.RTZ32.configuration.RTZ32_Configuration; import art.library.model.devices.colors.controller.RTZ32.configuration.RTZ32_Configuration_Program; import art.library.model.devices.colors.controller.RTZ32.configuration.RTZ32_Configuration_Program_Group; import art.library.model.devices.colors.controller.RTZ32.configuration.RTZ32_Configuration_Program_Trolley_Cancellation; import art.library.model.devices.colors.controller.RTZ32.configuration.RTZ32_Configuration_Program_Trolley_Correlation_Master; import art.library.model.devices.colors.controller.RTZ32.configuration.RTZ32_Configuration_Program_Trolley_Correlation_Slave; import art.library.model.devices.colors.controller.RTZ32.configuration.RTZ32_Configuration_Program_Trolley_Retractable; import art.library.model.devices.colors.controller.RTZ32.configuration.RTZ32_Configuration_Program_Trolley_Saturation; import art.library.model.devices.colors.controller.RTZ32.configuration.RTZ32_Configuration_Program_VariablePhase; import art.library.model.devices.colors.controller.RTZ32.configuration.constants.RTZ32_Constants_Colors; import art.library.model.devices.colors.controller.RTZ32.information.RTZ32_Information_Program; import art.library.model.devices.colors.controller.RTZ32.types.RTZ32_Distribution; import art.library.model.devices.colors.controller.RTZ32.types.RTZ32_Distribution_Group; import art.library.model.devices.colors.controller.RTZ32.types.RTZ32_Distribution_Group_Segment; import art.library.model.devices.colors.controller.RTZ32.types.RTZ32_Validation_Result; import art.servers.Shared; import java.util.ArrayList; import java.util.List; public class VALIDATION { // Validaciones según se va configurando el reparto: // Valores mayor que el ciclo // Fases Variables ERROR --> "La Fase Variable con Inicio xx y Fin yy está fuera de los límites temporales" // Fases Escamoteables ERROR --> "La Fase Escamoteable con Inicio xx y Fin yy está fuera de los límites temporales" // Puntos de Cancelación ERROR --> "El Punto de Cancelación está fuera de los límites temporales" // Puntos de Correlación ERROR --> "El Punto de Correlación está fuera de los límites temporales" // Zonas de Saturación ERROR --> "La Zona de Saturación con Inicio xx y Fin yy está fuera de los límites temporales" // Impulsos WARNING --> "El impulso rebasa el tiempo del ciclo, esta operación sólo es válida para grupos especiales de bomberos. ¿Está seguro que desea modificar este dato? // Valores igual al ciclo // Fases Variables WARNING --> "La Fase Variable con Inicio xx y Fin yy está fuera de los límites temporales" // Fases Escamoteables WARNING --> "La Fase Escamoteable con Inicio xx y Fin yy está fuera de los límites temporales" // Puntos de Cancelación WARNING --> "El Punto de Cancelación está fuera de los límites temporales" // Puntos de Correlación WARNING --> "El Punto de Correlación está fuera de los límites temporales" // Zonas de Saturación WARNING --> "La Zona de Saturación con Inicio xx y Fin yy está fuera de los límites temporales" // Impulsos WARNING --> "El grupo con orden X y Tipo X tiene impulsos fuera de rango" // Repartir Tiempos // Si al repartir tiempos el valor del ciclo no se ve modificado, únicamente se mostrará // un MessageBox "El reparto de movimiento se ha realizado correctamente // Si al repartir tiempos el valor del ciclo se modifica, // se informará con MessageBox "Esta operación variará el tiempo del ciclo" WARNING, // y tras realizarse otro con "El reparto de movimiento se ha realizado correctamente" public static RTZ32_Validation_Result validate(RTZ32_Controller controller, RTZ32_Information_Program program_information, String language) throws Exception { RTZ32_Validation_Result result = new RTZ32_Validation_Result(); RTZ32_Configuration configuration = program_information.configuration.rtz32; RTZ32_Configuration_Program program = configuration.getProgram(program_information.program); // Comprobar el número de grupos y tipos // No se completan las Observaciones ERROR --> "El campo "Observaciones" no puede estar vacío" if ((program_information.description == null) || (program_information.description.length() == 0)) { result.errors.add(Shared.getMessage(language, "Description field cannot be empty")); } // Si existe un cambio de estados de Grupo dentro de la Fase Variable (No comprobar grupos tipo 30 y 40) WARNING --> // "La Fase Variable con Inicio xx y Final yy tiene cambios de estado en el Grupo con orden X y Tipo X" for (RTZ32_Configuration_Program_Group group : program.groups) { if (group.isEmpty() == false) { int type = configuration.getGroup(group.group).getType(); if ((type != 30) && (type != 40)) { for (Integer impulse : group.impulses) { for (RTZ32_Configuration_Program_VariablePhase variable : program.variablePhases) { if ((impulse >= variable.startTime) && (impulse < variable.endTime) && (variable.isEmpty() == false)) { String message = Shared.getMessage(language, "Impulse detected inside variable phase") + "\r\n"; message = message + Shared.getMessage(language, "Group number") + " " + group.group + "\r\n"; message = message + Shared.getMessage(language, "Variable phase") + " [ " + variable.startTime + " → " + variable.endTime + " ]\r\n"; message = message + Shared.getMessage(language, "Impulse time") + " " + impulse; result.warnings.add(message); } } } } } } // Si el final de la FV no coincide con un cambio de estado WARNING --> " // La Fase Variable con Inicio xx y Final xx debe tener al menos un cambio de estado de algún grupo en su final" for (RTZ32_Configuration_Program_VariablePhase variable : program.variablePhases) { if (variable.isEmpty() == false) { if (check_end_phase(program, variable) == false) { String message = Shared.getMessage(language, "No group changes at the end of the variable phase") + " [ " + variable.startTime + " → " + variable.endTime + " ]"; result.warnings.add(message); } } } // Debe haber entre 2 y 8 fases Variables WARNING --> "Debe haber al menos 2 Fases Variables" int totalVariablePhases = getNumberVariablePhases(program); if (totalVariablePhases < 2) { String message = Shared.getMessage(language, "The number or variable phases is less than 2"); result.warnings.add(message); } if (totalVariablePhases > 8) { String message = Shared.getMessage(language, "The number or variable phases is greater than 8"); result.warnings.add(message); } // Fase Escamoteable dentro de Fase Variable WARNING --> " La fase variable con inicio xx y fin xx tiene solapada una fase escamoteable" for (RTZ32_Configuration_Program_Trolley_Retractable retractable : program.trolley.retractables) { for (RTZ32_Configuration_Program_VariablePhase variable : program.variablePhases) { if ((retractable.isEmpty() == false) && (variable.isEmpty() == false)) { if ( ((variable.startTime >= retractable.startTime) && (variable.startTime < retractable.endTime)) || ((variable.endTime > retractable.startTime) && (variable.startTime <= retractable.endTime)) ) { String message = Shared.getMessage(language, "Variable phase overlaps retractable phase") + "\r\n"; message = message + Shared.getMessage(language, "Variable phase") + " [ " + variable.startTime + " → " + variable.endTime + " ]\r\n"; message = message + Shared.getMessage(language, "Retractable phase") + " [ " + retractable.startTime + " → " + retractable.endTime + " ]"; result.warnings.add(message); } } } } // Nº Puntos Correlación según el tipo de regulador: // CTMaestro: WARNING --> " Debe tener entre 1 y 4 Puntos de Correlación Maestro" // Esclavo: WARNING --> " Debe tener entre 1 y 4 Puntos de Correlación Esclavo" // MaestroEsclavo: WARNING --> "Debe tener 1 Maestro o 1 Esclavo" // EsclavoMaestro: WARNING --> "Debe tener 1 Maestro o 1 Esclavo " if (controller.getDeviceInformation().mode == RTZ32_ControllerInformation.MODE_CENTRALIZED_MASTER) { if (getNumberCorrelationsMaster(program) < 1) { String message = Shared.getMessage(language, "The number of masters correlations is less than 1"); result.warnings.add(message); } if (getNumberCorrelationsMaster(program) > 4) { String message = Shared.getMessage(language, "The number of masters correlations is greater than 4"); result.warnings.add(message); } } if (controller.getDeviceInformation().mode == RTZ32_ControllerInformation.MODE_CENTRALIZED_SLAVE) { if (getNumberCorrelationsSlave(program) < 1) { String message = Shared.getMessage(language, "The number of slaves correlations is less than 1"); result.warnings.add(message); } if (getNumberCorrelationsSlave(program) > 4) { String message = Shared.getMessage(language, "The number of slaves correlations is greater than 4"); result.warnings.add(message); } } if (controller.getDeviceInformation().mode == RTZ32_ControllerInformation.MODE_CENTRALIZED_MASTER_SLAVE) { int masters = getNumberCorrelationsMaster(program); int slaves = getNumberCorrelationsSlave(program); if (masters == 1) result.warnings.add(Shared.getMessage(language, "A minimum of 1 correlation master is required")); if (slaves == 1) result.warnings.add(Shared.getMessage(language, "A minimum of 1 correlation slave is required")); if (masters > 4) result.warnings.add(Shared.getMessage(language, "A maximum of 4 correlation master are allowed")); if (slaves > 4) result.warnings.add(Shared.getMessage(language, "A minimum of 4 correlation slave are allowed")); } if (controller.getDeviceInformation().mode == RTZ32_ControllerInformation.MODE_CENTRALIZED_SLAVE_MASTER) { int masters = getNumberCorrelationsMaster(program); int slaves = getNumberCorrelationsSlave(program); if (masters == 1) result.warnings.add(Shared.getMessage(language, "A minimum of 1 correlation master is required")); if (slaves == 1) result.warnings.add(Shared.getMessage(language, "A minimum of 1 correlation slave is required")); if (masters > 4) result.warnings.add(Shared.getMessage(language, "A maximum of 4 correlation master are allowed")); if (slaves > 4) result.warnings.add(Shared.getMessage(language, "A minimum of 4 correlation slave are allowed")); } // Punto Correlación tipo Esclavo y de Pto. de Cancelación: // Si el Time Out del esclavo no está programado WARNING --> "El Punto de correlación esclavo con valor XX no tiene valor para TimeOut" // Si el Tiempo de espera del punto de cancelación no está programado WARNING --> "El Punto de cancelación con valor XX no tiene valor para el tiempo máximo de espera" for (RTZ32_Configuration_Program_Trolley_Correlation_Slave correlation : program.trolley.correlationsSlave) { if (correlation.isEmpty() == false) { if (correlation.timeout == 0) { String message = Shared.getMessage(language, "Timeout for slave correlation not set") + " [ " + correlation.time + ", " + correlation.timeout + " ]"; result.warnings.add(message); } } } for (RTZ32_Configuration_Program_Trolley_Cancellation cancellation : program.trolley.cancellations) { if (cancellation.isEmpty() == false) { if (cancellation.timeout == 0) { String message = Shared.getMessage(language, "Timeout for cancelation point not set") + " [ " + cancellation.time + ", " + cancellation.timeout + " ]"; result.warnings.add(message); } } } // Punto de Correlación Esclavo no están al final de una fase variable WARNING --> "El Punto de Correlación con valor XX debe estar situado en el final de una Fase Variable" for (RTZ32_Configuration_Program_Trolley_Correlation_Slave correlation : program.trolley.correlationsSlave) { if (correlation.isEmpty() == false) { if (existsVariablePhaseWithEndTime(program, correlation.time) == false) { String message = Shared.getMessage(language, "Slave correlation time does not match with the end of any phase") + " [ " + correlation.time + " ]"; result.warnings.add(message); } } } // Número de grupos de peatones <= 6 if (configuration.getGroupType(20).size() > 6) { String message = Shared.getMessage(language, "The maximum number of pedestrians groups (trolley) is 6"); result.errors.add(message); } // Número de grupos de tranvia =< 4 if (configuration.getGroupType(30).size() > 4) { String message = Shared.getMessage(language, "The maximum number of trolley groups is 4"); result.errors.add(message); } if (configuration.getGroupType(40).size() > 4) { String message = Shared.getMessage(language, "The maximum number of trolley groups is 4"); result.errors.add(message); } // Tiempo mínimo de peatones RTZ32_Distribution distribution = new RTZ32_Distribution(program_information.configuration.rtz32, program_information.program); int pedestrianPosition = 0; for (int i=0; i segments = group.listBars.get(j); if (segments.size() > 0) { int minimumGreenTime = configuration.trolleys.trolleys[j].pedestrians[pedestrianPosition].minimumGreenTime; for (Integer time : getGreensTimes(segments)) { if (time < minimumGreenTime) { String message = Shared.getMessage(language, "Pedestrian group (trolley) with green times less than minimim green time configured") + "\r\n"; message = message + Shared.getMessage(language, "Group number") + " " + group.groupNumber + "\r\n"; message = message + Shared.getMessage(language, "Pedestrian order") + " " + (pedestrianPosition + 1) + "\r\n"; message = message + Shared.getMessage(language, "Trolley order") + " " + (j + 1) + "\r\n"; message = message + Shared.getMessage(language, "Minimum green time") + " " + minimumGreenTime + "\r\n"; message = message + Shared.getMessage(language, "Green time") + " " + time; result.warnings.add(message); } } } } pedestrianPosition = pedestrianPosition + 1; } } // Valores mayor que el ciclo: // Fases Variables ERROR --> "La Fase Variable con Inicio xx y Fin yy está fuera de los límites temporales" for (RTZ32_Configuration_Program_VariablePhase variable : program.variablePhases) { if (variable.isEmpty() == false) { if ((variable.startTime >= program.cycle) || (variable.endTime > program.cycle) || (variable.startTime < 0) || (variable.endTime < 1)) { String message = Shared.getMessage(language, "Variable phase out of bounds") + " [" + variable.startTime + " → " + variable.endTime + " ]"; result.errors.add(message); } } } // Fases Escamoteables ERROR --> "La Fase Escamoteable con Inicio xx y Fin yy está fuera de los límites temporales" for (RTZ32_Configuration_Program_Trolley_Retractable retractable : program.trolley.retractables) { if (retractable.isEmpty() == false) { if ((retractable.startTime >= program.cycle) || (retractable.endTime > program.cycle) || (retractable.startTime < 0) || (retractable.endTime < 1)) { String message = Shared.getMessage(language, "Retractable phase out of bounds") + " : [ " + retractable.startTime + " → " + retractable.endTime + " ]"; result.errors.add(message); } } } // Puntos de Cancelación ERROR --> "El Punto de Cancelación está fuera de los límites temporales" for (RTZ32_Configuration_Program_Trolley_Cancellation cancellation : program.trolley.cancellations) { if (cancellation.isEmpty() == false) { if ((cancellation.time > program.cycle) || (cancellation.time < 0)) { String message = Shared.getMessage(language, "Cancellation point out of bounds") + " [ " + cancellation.time + " ]"; result.errors.add(message); } } } // Puntos de Correlación ERROR --> "El Punto de Correlación está fuera de los límites temporales" for (RTZ32_Configuration_Program_Trolley_Correlation_Master correlation : program.trolley.correlationsMaster) { if (correlation.isEmpty() == false) { if ((correlation.time > program.cycle) || (correlation.time < 0)) { String message = Shared.getMessage(language, "Correlation master out of bounds") + " [ " + correlation.time + " ]"; result.errors.add(message); } } } for (RTZ32_Configuration_Program_Trolley_Correlation_Slave correlation : program.trolley.correlationsSlave) { if (correlation.isEmpty() == false) { if ((correlation.time > program.cycle) || (correlation.time < 0)) { String message = Shared.getMessage(language, "Correlation slave out of bounds") + " [ " + correlation.time + " ]"; result.errors.add(message); } } } // Zonas de Saturación ERROR --> "La Zona de Saturación con Inicio xx y Fin yy está fuera de los límites temporales" for (RTZ32_Configuration_Program_Trolley_Saturation saturation : program.trolley.saturations) { if (saturation.isEmpty() == false) { if ((saturation.startTime >= program.cycle) || (saturation.endTime > program.cycle) || (saturation.startTime < 0) || (saturation.endTime < 1)) { String message = Shared.getMessage(language, "Saturation out of bounds") + " [ " + saturation.startTime + " → " + saturation.endTime + " ]"; result.errors.add(message); } } } // Impulsos WARNING --> "El impulso rebasa el tiempo del ciclo, esta operación sólo es válida para grupos especiales de bomberos. ¿Está seguro que desea modificar este dato? for (RTZ32_Configuration_Program_Group group : program.groups) { for (Integer impulse : group.impulses) { if ((impulse > program.cycle) || (impulse < 0)) { String message = Shared.getMessage(language, "Impulse time out of bounds") + "\r\n"; message = message + Shared.getMessage(language, "Group number") + " " + group.group + "\r\n"; message = message + Shared.getMessage(language, "Impulse time") + " " + impulse; result.warnings.add(message); } } } // Valores igual al ciclo: // Fases Variables WARNING --> "La Fase Variable con Inicio xx y Fin yy está fuera de los límites temporales" // Fases Escamoteables WARNING --> "La Fase Escamoteable con Inicio xx y Fin yy está fuera de los límites temporales" // Puntos de Cancelación WARNING --> "El Punto de Cancelación está fuera de los límites temporales" // Puntos de Correlación WARNING --> "El Punto de Correlación está fuera de los límites temporales" // Zonas de Saturación WARNING --> "La Zona de Saturación con Inicio xx y Fin yy está fuera de los límites temporales" // Impulsos WARNING --> "El grupo con orden X y Tipo X tiene impulsos fuera de rango" // Esto no tiene sentido return result; } public static RTZ32_Validation_Result eprom(RTZ32_Controller controller, RTZ32_Information_Program program, String language) throws Exception { RTZ32_Validation_Result result = new RTZ32_Validation_Result(); RTZ32_Configuration configuration1 = program.configuration.rtz32; RTZ32_Configuration configuration2 = program.configuration.rtz32; //TODO //RTZ32_Configuration configuration2 = controller.getDeviceConfiguration().rtz32; // Nº de Regulador distinto al de la tabla 95 WARNING if (configuration1.controllerNumber != configuration2.controllerNumber) { result.warnings.add("Controller number does not match"); } // Nº de grupos distinto al de la tabla 95 WARNING if (configuration1.getNumberValidGroups() != configuration2.numberGroups) { result.warnings.add("Number of groups does not match"); } if (configuration1.getNumberValidGroups() != configuration2.getNumberValidGroups()) { result.warnings.add("Number of groups does not match"); } // Incompatibilidad de impulsos con tabla 91 (entre verdes) y // tabla 92 (de los marcados como incompatibles en la tabla 91 // que no se produzca ninguna coincidencia entre verde y ámbar) WARNING return result; } private static boolean check_end_phase(RTZ32_Configuration_Program program, RTZ32_Configuration_Program_VariablePhase variable) { try { for (RTZ32_Configuration_Program_Group group : program.groups) { for (Integer impulse : group.impulses) { if (impulse == variable.endTime) { return true; } } } } catch (Exception exception) { } return false; } private static int getNumberVariablePhases(RTZ32_Configuration_Program program) { int total = 0; try { for (RTZ32_Configuration_Program_VariablePhase variable : program.variablePhases) { if (variable.isEmpty() == false) { total = total + 1; } } } catch (Exception exception) { } return total; } private static int getNumberCorrelationsMaster(RTZ32_Configuration_Program program) { int total =0; try { for (RTZ32_Configuration_Program_Trolley_Correlation_Master correlation : program.trolley.correlationsMaster) { if (correlation.isEmpty() == false) { total = total + 1; } } } catch (Exception exception) { } return total; } private static int getNumberCorrelationsSlave(RTZ32_Configuration_Program program) { int total = 0; try { for (RTZ32_Configuration_Program_Trolley_Correlation_Slave correlation : program.trolley.correlationsSlave) { if (correlation.isEmpty() == false) { total = total + 1; } } } catch (Exception exception) { } return total; } private static boolean existsVariablePhaseWithEndTime(RTZ32_Configuration_Program program, int time) { try { for (RTZ32_Configuration_Program_VariablePhase variable : program.variablePhases) { if ((variable.isEmpty() == false) && (variable.endTime == time)) { return true; } } } catch (Exception exception) { } return false; } private static List getGreensTimes(List segments) { List result = new ArrayList(); // Get number of reds for (int i=0; i