# Ocurrencias

> Condiciones vigiladas de la cosa bajo prueba, escritas como una expresión JavaScript sobre los canales del modelo y juzgadas durante una corrida o siempre.

Una **ocurrencia** registra que la cosa bajo prueba hizo algo digno de nota. Donde una alarma vigila
la planta y el equipo, una ocurrencia pertenece al procedimiento: sus flancos se quedan con la
corrida que los observó y entran además en la cronología persistente de Ocurrencias de la página
Eventos. Su condición es una expresión JavaScript sobre los canales del modelo, con antirrebote en
los dos flancos y condicionada por la calidad de lo que lee. Las ocurrencias viven en Process >
Modelos > modelo > Preparación > **Ocurrencias** y exigen el permiso **Editar recetas y
evaluaciones**.

## La carpeta Ocurrencias {#the-occurrences-folder}

Al seleccionar la fila **Ocurrencias** se abre la página de la carpeta ("Condiciones vigiladas de lo
que se está probando. Cada flanco se queda con su corrida cuando procede y entra además en el
histórico permanente de ocurrencias.") con una tarjeta por ocurrencia, por nombre; al hacer clic en
una tarjeta se abre y la X la quita. Sin ninguna, la página dice "Todavía no hay ocurrencias. Agregue
una."

| Comando | Qué hace | Atenuado cuando (situación) | No se dibuja cuando (rol) |
| --- | --- | --- | --- |
| **Ocurrencia** (barra de detalle, con la carpeta seleccionada; botón derecho **Agregar ocurrencia**) | Agrega `Ocurrencia <n>`: gravedad Advertencia, armada durante los procedimientos, activada, sin mensaje, condición vacía. La fila se agrega a su grupo, resaltada y desplazada hasta quedar a la vista allí; su tarjeta la abre. | Cualquier unidad tiene una corrida, o el runtime está detenido. | Sin Editar recetas y evaluaciones. |

## La página de la ocurrencia {#the-occurrences-page}

El encabezado lleva el nombre, una píldora con la gravedad (en el color propio de la gravedad) y una
píldora **Desactivada** cuando la ocurrencia está apagada. Debajo pueden aparecer dos clases de
aviso:

- Una nota de precaución cuando la condición guardada no valida (el borrador se guarda igual; la nota
  dice qué está mal, véase más abajo).
- Un aviso **Evaluación no disponible** por cada unidad en la que la condición en vivo no se pudo
  evaluar, como "`<unit>`: `<error>`". El diagnóstico de una unidad se escribe una vez por cada error
  que no cambia y se limpia cuando la evaluación vuelve a salir bien.

### Identidad y comportamiento {#identity--behavior}

| Campo | Qué es | Valores / predeterminado | Efecto |
| --- | --- | --- | --- |
| **Nombre** | El nombre de la ocurrencia: la fila del árbol, la etiqueta del evento en el archivo de la corrida, la cronología de Eventos y los reportes. | Texto libre; `Ocurrencia <n>` al crearla. | Renombra la fila y cómo la llama la lista de verificación de un procedimiento. |
| **Gravedad** | El peso de una activación. El selector muestra cada opción en la tinta que llevará su píldora. | **Información**, **Advertencia** (predeterminada), **Crítica**. | Colorea la píldora y el episodio dondequiera que se liste. Durante una corrida, la activación de una ocurrencia de Advertencia o Crítica pide además una notificación del sistema operativo mientras la aplicación está oculta o minimizada; Información se queda en la ventana. |
| **Armado** | Cuándo se juzga la condición. | **Durante un procedimiento** (predeterminado): solo mientras está activa una corrida de un procedimiento que la arma, sobre las filas grabadas. **Siempre**: también fuera de las corridas, por un observador de fondo que lee en vivo los vínculos de la unidad. | Una ocurrencia Siempre no necesita ningún procedimiento que la arme; una armada Durante un procedimiento la juzgan solo los procedimientos que la marcan. |
| **Retardo a la activación (ms)** | Cuánto tiene que mantenerse cierta la condición antes de confirmar **Activada**, con la resolución de las muestras. | Un número de milisegundos; 0 de forma predeterminada. El campo no acepta un número negativo: la entrada se rechaza, la nota bajo el campo lo dice, y regresa el valor anterior. | Da antirrebote al flanco de subida. |
| **Retardo a la desactivación (ms)** | Cuánto tiene que mantenerse falsa la condición antes de confirmar **Restablecida**. | Igual; 0 de forma predeterminada. | Da antirrebote al flanco de bajada. |
| **Activada** | Si la ocurrencia se arma siquiera. | Encendida de forma predeterminada. | Una ocurrencia desactivada nunca se arma, ni en una corrida ni fuera de ella, y nunca bloquea el Arranque. |
| **Mensaje** | El texto grabado y anunciado con una activación. | Texto libre; vacío de forma predeterminada. | Viaja con cada flanco al archivo de la corrida y al diario. |

### Condición {#condition}

"Una sola expresión JavaScript que devuelve un booleano." La tarjeta tiene un editor de código, la lista de
las referencias que puede usar ("Referencias de canal disponibles: Channels.Ch_1,
Channels.Outlet_temperature, …") y el recordatorio "Durante una corrida la condición lee las columnas
registradas del datalog; el observador Siempre lee en vivo los vínculos de la unidad. La sintaxis, las
referencias que faltan y las fallas de evaluación en ejecución se muestran aquí sin tratarlas como
falso ni como pérdida de señal."

Un canal se referencia como `Channels.<identifier>`, donde el identificador es el nombre del canal
depurado: sobreviven las letras y los dígitos, todo otro carácter pasa a `_`, y un nombre que empieza
por un dígito gana un `_` delante. `Channels` contiene solo los canales del modelo y nada más, así
que un canal llamado `Math`, `isNaN` o `true` sigue siendo un nombre de canal válido y no oculta
ninguna global de JavaScript. Un `NaN` presente y bueno es un dato que usted puede probar con
`isNaN(Channels.Pv)`. Ejemplos: `Channels.Outlet_temperature > 80`,
`Channels.Door_open && Channels.Heater_on`.

El borrador se valida mientras escribe, contra valores de muestra del tipo de cada canal, y la nota
de precaución bajo el encabezado dice qué falla:

| Nota | Significado |
| --- | --- |
| "Error de sintaxis: …" | La expresión no se analiza. |
| "La referencia de canal 'Channels.X' no existe en este modelo." | Una referencia no nombra ningún canal. |
| "Más de un canal se corresponde con 'Channels.X'." | Dos nombres de canal se depuran al mismo identificador; renombre uno en la cuadrícula de Canales. |
| "La condición debe devolver un booleano, pero devolvió `<type>`." | La expresión da algo que no es verdadero ni falso. |
| "Error de evaluación: …" | La expresión lanza un error. |

Una condición no válida se guarda igual como borrador. Tiene consecuencias en otro lado: una
ocurrencia activada que no pasa la validación y que un procedimiento arma (marcada en él, o armada
Siempre) bloquea el Arranque de ese procedimiento, y la página del procedimiento muestra "La
ocurrencia '`<name>`' no es válida: …"; una ocurrencia Siempre no válida no arranca su observador
fuera de corrida y deja aquí un diagnóstico visible en vez de repetirlo en cada sondeo.

Cada evaluación corre en un motor acotado (un límite de 500 ms, un número acotado de sentencias y una
memoria acotada), así que una expresión desbocada falla su evaluación y no la estación.

## Cómo se juzga una ocurrencia {#how-an-occurrence-is-judged}

Durante una corrida la condición se juzga sobre las filas que graba el datalog, así que un canal que
el datalog del procedimiento no graba no está disponible para ella. Un procedimiento que arma una
ocurrencia sobre un canal así, o que arma una y no graba nada en absoluto, se rechaza en su propia
página y en el Arranque: la ocurrencia nunca juzgaría, y la nota de precaución la nombra. Fuera de las
corridas, una ocurrencia Siempre la juzga un observador que lee en vivo los vínculos de la unidad.
Cualquiera de los dos jueces mantiene el último estado confirmado mientras cualquier canal
referenciado no está disponible: solo un valor ausente o una calidad mala suspenden el juicio, y un
valor presente y bueno (un `NaN` incluido) es dato evaluable. El juez graba cuatro transiciones:
**Activada** (después del retardo de activación), **Restablecida** (después del retardo de
desactivación), **No disponible** (un canal referenciado perdió su señal) y **Recuperada** (todo canal
referenciado regresó; la condición se juzga de nuevo y el retardo aplicable vuelve a empezar).

Durante una corrida toda transición se escribe primero en el archivo de la corrida y después se
copia, con su contexto de corrida, al diario persistente de la página [Eventos](events-occurrences);
fuera de las corridas el observador escribe solo en el diario. Arrancar una corrida descarta el juez
fuera de corrida de la unidad, y salir de la corrida crea uno nuevo, así que ninguna activación cruza
un límite sin observación. Las ediciones del nombre, del mensaje o de la gravedad afectan solo a los
flancos posteriores; las ediciones de la condición, de los retardos, del modo de armado o del estado
de activación empiezan una observación nueva.

Los episodios (de la activación al restablecimiento, con todo intervalo de pérdida de señal contado
aparte) se derivan de esos flancos dondequiera que la aplicación los muestre: la tarjeta Ocurrencias
de un panel, la página Eventos, Históricos y los reportes. El tiempo activo de un episodio es
exactamente el intervalo entre los dos flancos persistidos, así que excluye el retardo de activación e
incluye el de desactivación: el reloj arranca cuando la condición ya se mantuvo el retardo de
activación, y se detiene solo cuando se escribe el restablecimiento, después de que corrió el retardo
de desactivación. Ese es el número que un reporte le entrega a un tercero.

## Dónde se usa una ocurrencia {#where-an-occurrence-is-used}

La página de un procedimiento lleva la tarjeta **Ocurrencias armadas durante este procedimiento**,
con una píldora "`<n>` armadas" y una casilla por ocurrencia del modelo, por nombre. Marcar una la
arma durante las corridas de ese procedimiento; una ocurrencia armada **Siempre** vigila de todos
modos y no necesita marca. Sin ninguna ocurrencia en el modelo la tarjeta dice "Todavía no hay
ocurrencias en este modelo. Agregue algunas en Ocurrencias del modelo." Véase
[Procedimientos](process-procedures).

Renombrar un canal reescribe las referencias `Channels.<identifier>` de ese canal en todas las
condiciones del modelo; no toca cadenas, comentarios ni una propiedad del mismo nombre en otro
objeto.

## Quitar la ocurrencia {#remove-occurrence}

**Quitar la ocurrencia** está en el grupo de peligro de la barra de detalle con la ocurrencia
seleccionada, en su menú del botón derecho, y como la X de la tarjeta de la página de la carpeta.
Pregunta primero ("Eliminar la ocurrencia", "Esto quita la ocurrencia del modelo.") y la desarma de
todo procedimiento que la marcaba. Exige Editar recetas y evaluaciones y se atenúa bajo el bloqueo de
ingeniería y el runtime detenido.

## Qué no hace una ocurrencia {#what-an-occurrence-does-not-do}

- No es una alarma: no se reconoce, no tiene prioridad y no vigila tags. Las alarmas de la planta
  están en la página [Logic](logic-alarms).
- No dispara nada. Una activación se graba y se anuncia; no lleva pegada ninguna acción, etiqueta ni
  reporte.
- No puede leer nada más que los canales del modelo: ningún tag, ninguna variable, ningún otro
  modelo.
- No se juzga distinto por unidad: una condición sirve a todas las unidades, sobre los vínculos o las
  filas grabadas de cada una.
