Saltar al contenido principal

Resumen

Un Calendario (Schedule) es lo que ancla una simulación a la temporización del mundo real. Sin un calendario, un modelo se ejecuta en tiempo abstracto con llegadas sintéticas — útil para trabajo exploratorio, pero no para comparar contra tu piso de planta real. Con un calendario, la simulación se ancla a fechas reales, patrones de turnos reales y planes de producción reales. El material entra cuando tu plan dice que lo hace, las transiciones de turno disparan a horas de reloj de pared específicas, y los resultados son comparables directamente a lo que produjo tu piso de planta. Cada uso serio de ProDex involucra al menos un calendario. La mayoría de los modelos tienen varios — uno para el plan “normal”, algunos para escenarios alternativos que estás comparando. Los calendarios viven junto a las Instantáneas (Snapshots) como las dos cosas que una fila de comparación de Experimento (Experiment) reúne. Una Instantánea congela el modelo + calendario juntos (el calendario está incrustado en la instantánea, no referenciado); el calendario activo cuando se capturó la instantánea viaja con ella.

Elegir un Calendario

El selector de calendario vive en la barra superior del Modelador. El menú desplegable lista cada calendario definido en el modelo, más:
  • Default (no schedule) — cuando se selecciona, el modelo se ejecuta en tiempo abstracto con las llegadas estocásticas que las Fuentes (Sources) definan. No hay un objeto de calendario detrás de esto — es una selección nula.
  • + New schedule — crea un calendario fresco y vacío y cambia a él.
  • Edit — abre el modal Schedule Editor para el calendario actualmente seleccionado. Vive dentro del menú desplegable (no junto al selector).
  • Delete — elimina el calendario actualmente seleccionado. Abre un diálogo de confirmación: “Delete Schedule — Are you sure you want to delete ‘{name}’? This action cannot be undone.”

El editor de Calendario

El editor de calendario es un modal titulado Edit {schedule name} que toma el área de trabajo mientras creas la temporización y eventos de un calendario. La parte superior del modal tiene cuatro campos que definen el calendario:
  • Name — corto, descriptivo. Esto es lo que aparece en el selector de la barra superior.
  • Description — texto libre opcional explicando qué representa este calendario.
  • Start Time — el momento de reloj de pared en que comienza la simulación. Cada marca de tiempo de evento en este calendario debe caer en o después de Start Time.
  • End Time — el momento de reloj de pared en que termina la simulación. Si se deja en blanco, la simulación se ejecuta durante la Duration configurada del modelo a partir de Start Time. Si se establece, End Time anula Duration.
Los datetimes deben tener información de zona horaria. Todas las marcas de tiempo en un calendario (Start Time, End Time y el release_time de cada evento) deben incluir un offset UTC o sufijo Z. Los datetimes naive fallan la validación inmediatamente — el calendario no se guardará, y cualquier ejecución (Run) contra él se aborta. El selector de datetime del modal emite valores con offset por defecto; el validador rechaza cualquier otra cosa.
Debajo de los cuatro campos, un alternador de vista Timeline / Table controla cómo se presentan los eventos. La vista Timeline coloca los eventos a lo largo de un eje de reloj de pared — útil para detectar los límites de turno y el espaciado visualmente. La vista Table lista cada evento en una cuadrícula ordenable — útil para revisión masiva y detección de errores tipográficos en las marcas de tiempo. Desde la perspectiva del esquema, un calendario contiene exactamente dos arreglos de nivel superior:
  • material_releases[] — entidades entrando al modelo en tiempos específicos
  • scheduled_actions[] — asignaciones y emisiones disparadas en tiempos específicos, opcionalmente condicionadas
La interfaz expone esto como tres secciones — MATERIAL RELEASE, ASSIGN VARIABLE, EMIT EVENT — porque cada acción programada lleva un arreglo interno actions[] donde cada acción es o un assign o un emit. Los dos tipos de acción comparten una entrada padre scheduled_actions[] y heredan su release_time y condition opcional. Un solo botón + en la parte superior derecha del modal abre un selector para qué tipo de evento agregar — material release, assign-variable o emit-event.

Qué contiene un Calendario

Un calendario es una secuencia de liberaciones de material y acciones programadas, cada una marcada con un tiempo de reloj de pared absoluto específico. La simulación se ejecuta desde Start Time hasta End Time (o durante la Duration configurada del modelo si End Time no está establecido), y cada evento dispara cuando el tiempo de simulación de reloj de pared alcanza su marca de tiempo. Cada marca de tiempo de evento es absoluta — no un offset relativo desde Start Time.

Liberaciones de material

Una liberación de material le indica a una Source o Búfer (Buffer) que emita una o más entidades en un tiempo de reloj de pared específico. El formulario tiene estos campos de esquema:
  • element_id — el id de una Source o Buffer desde la cual liberar. Admite direccionamiento jerárquico (model_node_1::source_1) para componentes dentro de un Model Node.
  • entity_type_id — el slug del tipo de entidad a liberar.
  • quantity — un entero positivo (exclusiveMinimum: 0, tipado como entero; sin unión DSL).
  • release_time — momento absoluto de reloj de pared en que dispara la liberación (datetime ISO con zona horaria).
  • attributes — valores a establecer en las entidades recién creadas usando las seis estrategias de asignación: Fixed, DSL Expression, Round Robin, Random Choice, Random, Weighted.
Las liberaciones de material son cómo modelas “la demanda que realmente sucedió”. En lugar de una Source con una tasa de llegada exponencial sintética, le das una secuencia de órdenes reales: el 1 de noviembre de 2024 a las 7:00 AM UTC liberar 50 unidades de Producto A con priority="rush" y due_priority=5; el 1 de noviembre de 2024 a las 9:00 AM UTC liberar 30 unidades de Producto B; y así sucesivamente.
La lógica de llegada de una Source y las liberaciones de material se ejecutan en paralelo. No son mutuamente exclusivas. Una Source puede seguir produciendo llegadas estocásticas mientras un calendario simultáneamente inyecta lotes específicos en tiempos programados, y acciones release_entity impulsadas por eventos pueden dispararse sobre ambas. Si quieres una Source solo de calendario, deja su lógica de llegada vacía.

Acciones programadas

Una acción programada se dispara en un tiempo de reloj de pared específico sin estar atada al evento del ciclo de vida de ningún componente. Campos de esquema:
  • release_time — momento absoluto de reloj de pared en que dispara la acción (con zona horaria).
  • condition (opcional) — expresión DSL booleana. La acción solo dispara si la condición evalúa verdadero en release_time.
  • actions[] — lista de entradas assign o emit que disparan juntas en este tiempo.
Los dos tipos de acción son: Las acciones vinculadas a componentes — Pause, Resume, Set Capacity, Release Entity — no son válidas directamente como acciones programadas. Si necesitas un cambio de capacidad programado, el patrón es:
  1. Un emit programado dispara en el límite del turno — por ejemplo, publica el topic shift_start_night.
  2. Un Event Listener en el recurso (Resource) se suscribe a ese topic y establece la capacidad al valor nocturno.
Esta separación mantiene los calendarios declarativos (“a las 6:00 PM UTC del 1 de noviembre de 2024, anuncia que el turno nocturno ha comenzado”) y permite que los Event Listeners manejen los efectos secundarios a nivel de componente.
SELF no está disponible en acciones programadas. SELF está restringido a event hooks y event listeners. Desde una acción programada, referencia componentes por su id explícito en funciones de consulta de componentes en su lugar.

Direccionamiento jerárquico

element_id acepta el separador :: para componentes dentro de un Model Node. Ejemplos:
  • source_1 — una Source de nivel superior
  • model_node_1::source_1 — una Source dentro de un Model Node
  • outer_node::inner_node::buffer_1 — anidado profundamente
Todos los segmentos son slugs de componente, no nombres visibles. El separador :: está reservado — ningún id de componente individual puede contenerlo.

El patrón de programación de turnos

La mayoría de las fábricas tienen capacidad basada en turnos que cambia durante el día y la semana. La forma idiomática de modelar esto en ProDex combina calendarios, topics, variables de estado y event listeners:
  1. Una variable de estado de turnoCURRENT_SHIFT, tipo text, valor inicial "day".
  2. Acciones emit programadas en los límites de turno — publica el topic shift_day al inicio de cada turno diurno, publica el topic shift_night al inicio de cada turno nocturno, cada uno con su release_time de reloj de pared específico.
  3. Un Event Listener en cada recurso afectado suscribiéndose a los topics de turno — cuando se publica shift_night, establece la capacidad de la máquina CNC al valor nocturno y actualiza CURRENT_SHIFT a "night".
  4. Las expresiones referencian CURRENT_SHIFT — las tasas de llegada, la puntuación de prioridad y cualquier otra cosa que varíe por turno lee la variable de estado y se ramifica en consecuencia.
Esta descomposición mantiene la lógica de turno en un lugar (el Event Listener en el recurso) y la temporización de turno en el calendario. Cambia el calendario por un plan de turnos diferente y los cambios de capacidad fluyen automáticamente.

Múltiples Calendarios por modelo

Un modelo puede tener múltiples calendarios definidos simultáneamente. Cada uno es un conjunto completo de liberaciones de material y acciones programadas con su propio Start Time y End Time; eliges cuál usar desde el selector de la barra superior al ejecutar una simulación, y cualquier Instantánea guardada mientras un calendario está activo incrusta ese calendario para ejecuciones aguas abajo. Usos típicos:
  • Escenarios base vs. estrés — un calendario “normal” y un calendario de “aumento de demanda”, comparados en el mismo experimento.
  • Repetición histórica — la demanda real del último mes como un calendario, un pronóstico de demanda planificada como otro.
  • Variaciones de turno — un calendario estándar de cinco días y un calendario alternativo de siete días con cobertura de fin de semana.
Una fila de Experimento empareja una Instantánea (modelo + calendario, incrustado) con otra. Variar el calendario entre instantáneas te permite preguntar “¿cómo se desempeña esta configuración de modelo bajo diferentes perfiles de demanda?” Variar el modelo te permite preguntar “¿qué configuración es mejor para esta demanda?”

Start Time y End Time

  • Start Time es el momento de reloj de pared en que comienza la simulación. Cada marca de tiempo de liberación de material y acción programada debe caer en o después de Start Time.
  • End Time, si se proporciona, es cuando termina la simulación. Útil para ejecutar el mismo calendario contra una ventana más corta o más larga sin editar los eventos del calendario.
  • Si End Time se deja en blanco, la simulación se ejecuta durante la Duration configurada del modelo desde Start Time.
  • Los eventos con marca de tiempo después de End Time (o después de Start Time + Duration si no hay End Time establecido) nunca disparan.
Las zonas horarias importan — el mismo calendario ejecutado con Start Time en UTC vs. tiempo local producirá resultados diferentes para los límites de turno a menos que los eventos de turno estén marcados en la misma zona. El editor de calendario muestra los tiempos en tu zona seleccionada; elige una y mantente con ella para todo el calendario.

Consejos

  • Cada modelo serio necesita un calendario. Las llegadas sintéticas están bien para la primera pasada; los calendarios reales son requeridos para resultados comparables.
  • Usa marcas de tiempo absolutas de reloj de pared consistentemente. Es tentador pensar en offsets relativos (“liberar en +3600s”) pero cada evento necesita un release_time absoluto. Si estás esbozando un calendario en papel, calcula las marcas de tiempo absolutas desde tu Start Time base antes de ingresarlas.
  • Usa condition en acciones programadas para condicionar el comportamiento al estado en tiempo de ejecución — p. ej., solo emitir un topic si una variable de estado está en un modo particular.
  • Mantén la lógica a nivel de calendario en el calendario, la lógica a nivel de componente en los Event Listeners. El calendario emite la señal; el listener maneja los efectos secundarios.
  • Usa múltiples calendarios para experimentos. El punto entero de los experimentos es la comparación — los calendarios son un eje de variación, la configuración del modelo el otro.
  • Dos eventos en la misma marca de tiempo disparan en un orden no especificado. Si el orden importa, distáncialos por una pequeña cantidad (un segundo) o encadénalos a través de un topic.