Skip to main content

Overview

The Timeline class provides chronological event logging for the simulation. Each UI module creates its own timeline instance to display execution events as they happen.

Class: Timeline

Location

source/js/ui/timeline.js

Constructor

timeline.js
export class Timeline {
  constructor(container) {
    this.container = container;
  }
}
Parameters:
  • container - DOM element where timeline events will be rendered

Example Instantiation

ui.js
import { Timeline } from "./timeline.js";
import { $ } from "../utils/dom.js";

const timeline = new Timeline($("timeline"));

Methods

addEvent(text)

Adds a new event to the timeline with a timestamp. Parameters:
  • text - String describing the event
Behavior:
  • Creates a timestamped log entry
  • Prepends (adds to top) so newest events appear first
  • Uses HH:MM:SS format in 24-hour time
Example:
timeline.addEvent("🔑 Cliente-1 entro en Seccion Critica");
timeline.addEvent("💸 Cliente-2 modifico el saldo: -$100");
timeline.addEvent("🔓 Cliente-1 salio y libero el Mutex");
Implementation:
timeline.js
addEvent(text) {
  const log = create("div");
  log.className = "text-[11px] font-mono py-1.5 border-b border-gray-800";
  
  const now = new Date();
  const timeStr = now.toLocaleTimeString([], {
    hour12: false,
    minute: "2-digit",
    second: "2-digit",
  });
  
  log.innerHTML = `<span class="text-green-500">[${timeStr}]</span> <span class="text-gray-200">${text}</span>`;
  
  // Inserta arriba para mostrar primero lo mas reciente.
  this.container.prepend(log);
}
Rendered Output:
<div class="text-[11px] font-mono py-1.5 border-b border-gray-800">
  <span class="text-green-500">[14:23:15]</span> 
  <span class="text-gray-200">🔑 Cliente-1 entro en Seccion Critica</span>
</div>

clear()

Removes all events from the timeline. Example:
timeline.clear();
Implementation:
timeline.js
clear() {
  this.container.innerHTML = "";
}
Usage: Typically called when generating a new scenario to start fresh:
ui.js
$("generateScenario").onclick = () => {
  // ... setup code
  timeline.clear();
  timeline.addEvent(`Sistema listo: ${num} hilos creados.`);
  // ... more setup
};

Event Flow

The timeline integrates with the simulation execution cycle:
// 1. Engine executes a step and returns events
const events = engine.step(context);
// events = ["🔑 Cliente-1 entro en Seccion Critica", "💸 Cliente-2 modifico el saldo: -$100"]

// 2. UI logs each event to timeline
if (events.length === 0) {
  if (active) {
    timeline.addEvent("Planificador: Sin tareas pendientes.");
  } else if (!this.simulationFinished) {
    timeline.addEvent("Simulacion terminada satisfactoriamente.");
    this.simulationFinished = true;
  }
} else {
  events.forEach((e) => timeline.addEvent(e));
}

Event Types by Scenario

Mutex (Bank Scenario)

"🔑 Cliente-1 entro en Seccion Critica"
"💸 Cliente-1 modifico el saldo: -$100"
"💵 Cliente-2 ingreso al saldo: +$50"
"🔓 Cliente-1 salio y libero el Mutex"
"🔒 Cliente-3 esta esperando el Mutex"
"⚠️ Cliente-2 pidio retirar $500, pero solo se retiro $100 (saldo insuficiente)"

Semaphore (Printer Scenario)

"🟢 Trabajo-1 obtuvo Impresora-1"
"⏳ Trabajo-2 espera una impresora libre"
"🖨️ Trabajo-1 imprime 5 paginas en Impresora-1"
"🔁 Trabajo-1 libera Impresora-1 y la pasa a Trabajo-2"
"✅ Trabajo-3 libera Impresora-2"

Condition Variables (Restaurant Scenario)

"👨‍🍳 Chef preparo un plato (1/5)"
"🔔 Chef llamo a Cliente-1: comida lista"
"🍽️ Cliente-1 recibio un plato y pasa a comer"
"🪑 Cliente-2 espera comida en el restaurante"
"🍴 Cliente-1 comio su plato"
"📣 Chef anuncio comida, pero no habia clientes esperando"

Barrier (Race Scenario)

"🏃 Corredor-1 llego al checkpoint"
"🧱 Corredor-1 espera en el checkpoint (1/2 en cola)"
"🏃 Corredor-2 llego al checkpoint"
"🚦 Corredor-2 abrio barrera y libero a: Corredor-1"
"✅ Corredor-1 cruza el checkpoint tras apertura de barrera"
"🏁 Corredor-1 llego a la meta"

Monitor (Library Scenario)

"📖 Lector-1 entro a la biblioteca como lector"
"👩‍🎓 Lector-1 esta leyendo Libro (catalogo v1)"
"🚪 Lector-1 salio de lectura"
"🧑‍💼 Bibliotecario entro al monitor en modo escritura"
"🗂️ Bibliotecario actualizo catalogo a version 2"
"✅ Bibliotecario libero monitor y desperto a: Lector-2, Lector-3"

Join/Await (House Construction Scenario)

"🧱 Albañil construye Cimientos (1/3)"
"🧱 Albañil construye Cimientos (2/3)"
"🏗️ Albañil termino Cimientos"
"⛓️ Techador espera join de Albañil"
"✅ Techador join cumplido con Albañil"
"🕒 Supervisor espera await de: Albañil, Techador, Electricista"
"✅ Supervisor await cumplido: Albañil, Techador, Electricista"
"🏠 Supervisor entrego la casa terminada"

Peterson’s Algorithm (Robot Station Scenario)

"🔐 Robot-1 entro a estacion compartida"
"🤖 Robot-2 espera turno en estacion (turn=1)"
"⚙️ Robot-1 usa estacion (uso 1)"
"🔓 Robot-1 libero estacion y desperto a Robot-2"

Timeline Styling

The timeline uses a monospace font and consistent styling:
text-[11px]        /* Small text size */
font-mono          /* Monospace font for alignment */
py-1.5             /* Vertical padding */
border-b           /* Bottom border separator */
border-gray-800    /* Dark border color */
text-green-500     /* Green timestamps */
text-gray-200      /* Light gray event text */

Event Ordering

Events are displayed in reverse chronological order (newest first):
[14:23:18] 🔓 Cliente-1 salio y libero el Mutex
[14:23:17] 💸 Cliente-1 modifico el saldo: -$100
[14:23:16] 🔑 Cliente-1 entro en Seccion Critica
[14:23:15] Sistema listo: 3 hilos creados.
This is achieved by using prepend() instead of append():
this.container.prepend(log);  // Adds to top

Integration with UI Modules

Each UI module creates its own timeline:
// Mutex scenario
const timeline = new Timeline($("timeline"));

// Semaphore scenario  
const timeline = new Timeline($("semTimeline"));

// Condition scenario
const timeline = new Timeline($("condTimeline"));

// Barrier scenario
const timeline = new Timeline($("barTimeline"));

// Monitor scenario
const timeline = new Timeline($("monTimeline"));

// Join scenario
const timeline = new Timeline($("joinTimeline"));

// Peterson scenario
const timeline = new Timeline($("petTimeline"));
This ensures events from different scenarios don’t mix.

Typical Usage Pattern

ui.js
init(engine) {
  const timeline = new Timeline($("timeline"));
  let context = null;
  
  // Generate scenario
  $("generateScenario").onclick = () => {
    // ... setup
    timeline.clear();
    timeline.addEvent("Sistema listo: 3 hilos creados.");
    // ... more setup
  };
  
  // Execute step
  const runTick = (engine, context, timeline) => {
    const events = engine.step(context);
    
    if (events.length === 0) {
      if (active) {
        timeline.addEvent("Planificador: Sin tareas pendientes.");
      } else {
        timeline.addEvent("Simulacion terminada satisfactoriamente.");
      }
    } else {
      events.forEach(e => timeline.addEvent(e));
    }
  };
}

Event Sources

Timeline events come from:
  1. Engine Execution - engine.step() returns event strings
  2. UI Messages - Status updates from UI module
  3. Scenario Initialization - Setup messages when creating scenarios

Engine Events

Generated in engine.js by the execute() method:
engine.js
execute(thread, inst, ctx) {
  switch (inst.type) {
    case Instructions.ACQUIRE:
      if (mutex.acquire(thread)) {
        thread.nextInstruction();
        return `🔑 ${thread.name} entro en Seccion Critica`;
      }
      return `🔒 ${thread.name} esta esperando el Mutex`;
    
    case Instructions.WITHDRAW:
      // ... logic
      return `💸 ${thread.name} modifico el saldo: -$${allowed}`;
    
    // ... more cases
  }
}

UI Status Messages

ui.js
if (events.length === 0) {
  if (active) {
    timeline.addEvent("Planificador: Sin tareas pendientes.");
  } else if (!this.simulationFinished) {
    timeline.addEvent("Simulacion terminada satisfactoriamente.");
    this.simulationFinished = true;
  }
}

Scenario Setup Messages

ui.js
timeline.clear();
timeline.addEvent(`Sistema listo: ${num} hilos creados.`);
operations.forEach((op, i) => {
  const action = op.type === Instructions.DEPOSIT ? "ingresar" : "retirar";
  timeline.addEvent(`Cliente-${i + 1} va a ${action} $${op.amount}.`);
});

Best Practices

  1. Clear on New Scenario - Always clear the timeline when starting fresh
  2. Use Emojis - Visual icons help distinguish event types quickly
  3. Be Descriptive - Include relevant details (thread names, amounts, etc.)
  4. Handle Empty Events - Check events.length before iterating
  5. Prevent Duplicates - Use simulationFinished flag for final messages

Timeline Container Requirements

The container should:
  • Be scrollable if events overflow
  • Have a dark background for readability
  • Support monospace font rendering
Example HTML:
<div id="timeline" class="h-64 overflow-y-auto bg-slate-950 rounded-lg p-2"></div>

Next Steps