Options
All
  • Public
  • Public/Protected
  • All
Menu

Class Entity<S>

Abstract base class for Entity objects.

Entities are the actors in simulations.

They have an asynchronous script method that contains the actions carried out by the entity within the simulation.

These actions typically include asyncronous methods such as delay, enterQueue, seize, and waitSignal. Calls to asynchonous methods should include the await keyword.

For example:

class Customer extends Entity<BarberShop> {
    service = new Uniform(15 - 3, 15 + 3);
    async script() {
        const shop = this.simulation;
        await this.enterQueue(shop.qWait); // enter the line
        await this.enterQueue(shop.qJoe); // seize Joe the barber
        this.leaveQueue(shop.qWait); // leave the line
        await this.delay(this.service.sample()); // get a haircut
        this.leaveQueue(shop.qJoe); // free Joe        
    }
}

Type parameters

Hierarchy

Index

Constructors

constructor

  • new Entity<S>(options?: any): Entity<S>
  • Initializes a new instance of the Entity class.

    Entities are typically created by the {@link Simulation.bootstrap} method in the parent simulation, either using the Simulation.generateEntities method (which creates and activates entities) or the Simulation.activate method (which activates new entities).

    Type parameters

    Parameters

    • Optional options: any

      Object with parameters used to initialize the Entity.

    Returns Entity<S>

Accessors

priority

  • get priority(): number
  • set priority(value: number): void
  • Gets or sets a number that represents the entity's priority.

    The default value for this property is 0.

    Entities with higher priority will skip ahead of other entities when entering Queue objects and when finishing delays that end at the same simulated time.

    Returns number

  • Gets or sets a number that represents the entity's priority.

    The default value for this property is 0.

    Entities with higher priority will skip ahead of other entities when entering Queue objects and when finishing delays that end at the same simulated time.

    Parameters

    • value: number

    Returns void

serial

  • get serial(): number
  • Gets a serial number that uniquely identifies the Entity.

    Returns number

simulation

  • get simulation(): S
  • Gets a reference to the Simulation object that this entity is part of.

    Returns S

Methods

canEnterQueue

  • canEnterQueue(q: Queue, units?: number): boolean
  • Checks whether the entity can enter a Queue immediately.

    Parameters

    • q: Queue

      Queue to check.

    • units: number = 1

      Number of units to check for.

    Returns boolean

    True if the queue has at least units capacity units available, false otherwise.

delay

  • delay(delay: number, path?: IMovePath, signal?: any): Promise<number>
  • Async method that simulates a delay.

    When this method is invoked, the Entity pauses execution for a given number of simulated time units.

    For example, the script below causes the Customer entity to enter a service queue qJoe, then undergo a delay based on a service random variable, then leave the service queue:

    class Customer extends Entity<BarberShop> {
        service = new Uniform(15 - 3, 15 + 3);
        async script() {
            const shop = this.simulation;
            await this.enterQueue(shop.qWait); // enter the line
            await this.enterQueue(shop.qJoe); // seize Joe the barber
            this.leaveQueue(shop.qWait); // leave the line
            await this.delay(this.service.sample()); // get a haircut
            this.leaveQueue(shop.qJoe); // free Joe        
        }
    }
    

    Note that calls to async methods such as delay, enterQueue, seize, and waitSignal should be preceded by the await keyword.

    If you use the signal parameter to create an interruptible delay, the call to delay may return when the specified delay has elapsed or when the specified signal has been received. You can use this feature to implement preempting services. For example, the code below shows a preemt method:

    class Preempt extends Entity {
    
        // seizes a resource and applies an interruptible delay to allow
        // higher-priority entities to preempt the service.
        async preempt(resource: Queue, delay: number, trackingQueues: Queue[] = []) {
    
            // while we have a delay
            while (delay >= 1e-3) {
    
                // send signal to interrupt lower-priority entities
                this.sendSignal(resource);
    
                // seize the resource
                trackingQueues.forEach(q => this.enterQueueImmediately(q));
                await this.enterQueue(resource);
                trackingQueues.forEach(q => this.leaveQueue(q));
    
                // apply interruptible delay and update delay value
                delay -= await this.delay(delay, null, resource);
    
                // release the resource (time-out or signal)
                this.leaveQueue(resource);
            }
        }
    }
    

    Parameters

    • delay: number

      Number of simulated time units to wait for.

    • Optional path: IMovePath

      IMovePath object containing information about how the entity should be animated during the delay.

    • Optional signal: any

      Signal that can be used to interrupt the delay.

    Returns Promise<number>

    The amount of simulated time elapsed since the method was invoked.

dispose

  • dispose(): void
  • Method invoked when an Entity finishes executing its script.

    Returns void

enterQueue

  • enterQueue(queue: Queue, units?: number): Promise<number>
  • Async method that waits until a Queue has enough capacity, then adds this Entity to the Queue seizing a specified number of capacity units.

    An entity may enter multiple queues at once, but it cannot enter the same queue multiple times.

    For example, the script below causes the Customer entity to enter a service queue qJoe, then undergo a delay based on a service random variable, then leave the service queue:

    class Customer extends Entity<BarberShop> {
        service = new Uniform(15 - 3, 15 + 3);
        async script() {
            const shop = this.simulation;
            this.enterQueueImmediately(shop.qWait); // enter the line
            await this.enterQueue(shop.qJoe); // seize Joe the barber
            this.leaveQueue(shop.qWait); // leave the line
            await this.delay(this.service.sample()); // get a haircut
            this.leaveQueue(shop.qJoe); // free Joe        
        }
    }
    

    In the example above, the qWait queue has unlimited capacity. It does not restrict the flow of entities, but simply tracks how many queue capacity units were used and for how long.

    The qJoe queue, on the other hand, does have limited capacity. Entities trying to enter it may experience delays, having to wait until there is enough capacity. Like qWait, it also tracks how many queue capacity units were used and for how long.

    Note that calls to async methods such as delay, enterQueue, seize, and waitSignal should be preceded by the await keyword.

    Parameters

    • queue: Queue

      Queue that the Entity will enter.

    • units: number = 1

      Number of Queue capacity units to seize.

    Returns Promise<number>

    The amount of simulated time elapsed since the method was invoked.

enterQueueImmediately

  • enterQueueImmediately(queue: Queue, units?: number): void
  • Adds this Entity into a Queue seizing a specified number of capacity units without any wait.

    This method is synchronous. It does not require an await and assumes the queue has enough capacity to take the entity.

    This method is slightly more efficient than {@see enterQueue}, but should only be used if the Queue is guaranteed to have enough capacity.

    For example:

    class Customer extends Entity {
        async script() {
            let sim = this.simulation as MMC;
    
            // enter waiting queue
            if (sim.qWait.canEnter()) { // queue has enough capacity
                this.enterQueueImmediately(sim.qWait); // no need to wait (faster)
            } else {
                await this.enterQueue(sim.qWait); // will have to wait (slower)
            }
    
            await this.enterQueue(sim.qService);
            this.leaveQueue(sim.qWait);
            await this.delay(sim.service.sample());
            this.leaveQueue(sim.qService);
        }
    }
    

    Parameters

    • queue: Queue

      Queue that the Entity will enter.

    • units: number = 1

      Number of Queue capacity units to seize.

    Returns void

getAnimationPosition

  • Gets an IAnimationPosition value used by the Animation class to position entities in animated queues.

    By default, the Animation class animates entities in queues based on the queue location and angle, and on the entity's icon. This method allows you to override the default queue layout and provide custom positions for the entities in the queues.

    For example, the code below overrides the getAnimationPosition method to calculate the entity's position and angle based on the entity's position along a car-following strip:

    export class Car extends Entity implements ICarFollow {
        speed = 0; // starting speed
        accel = 10; // acceleration/deceleration
        position = 0; // current position
        maxSpeed = 0; // random value from simulation
    
        async script() {
            // script updates 'position'
            // ...
        }
    
        // gets the car's animation position
        getAnimationPosition(q: Queue, start: IPoint, end: IPoint): IAnimationPosition {
            const
                sim = this.simulation as CarFollow,
                pt = Point.interpolate(start, end, this.position / sim.stripLength);
            return {
                position: pt,
                angle: Point.angle(start, end, false)
            }
        }
    }
    

    Parameters

    • q: Queue

      Queue being animated.

    • start: IPoint

      Position of the queue's start.

    • end: IPoint

      Position of the queue's end.

    Returns IAnimationPosition

    An IAnimationPosition value used to position the entity in the animation, or null to use the standard queue layout.

leaveQueue

  • leaveQueue(q: Queue): void
  • Causes the Entity to leave a Queue it has previously entered using the enterQueue method.

    Parameters

    Returns void

script

  • script(): Promise<void>
  • Async method that contains the sequence of operations to be carried out by an Entity within a Simulation.

    The script method contains the bulk of the simulation logic. It typically contains of sequences of calls to methods that cause the entity to enter or leave queues (enterQueue/leaveQueue), undergo delays (delay), or wait for and send signals (waitSignal/sendSignal).

    For example:

    class Customer extends Entity<BarberShop> {
        service = new Uniform(15 - 3, 15 + 3);
        async script() {
            const shop = this.simulation;
            await this.enterQueue(shop.qWait); // enter the line
            await this.enterQueue(shop.qJoe); // seize Joe the barber
            this.leaveQueue(shop.qWait); // leave the line
            await this.delay(this.service.sample()); // get a haircut
            this.leaveQueue(shop.qJoe); // free Joe        
        }
    }
    

    Returns Promise<void>

seize

  • seize(resource: Queue, delay: number, waitingQueues?: Queue | Queue[], preemptSignal?: any, units?: number): Promise<void>
  • Seizes a resource (possibly preempting it), enters one or more waiting queues, performs a delay, and leaves the waiting queues and the resource.

    This method provides a short way of telling an entity to enter one or more waiting queues, seize a resource, leave the waiting queues, use the resource for a while, and leave the resource. For example:

    async script() {
    
        // this call
        await this.seize(sim.qResource, sim.delay.sample(), sim.qWait);
    
        // does the same as this
        this.enterQueueImmediately(sim.qWait);
        await this.enterQueue(sim.qResource);
        this.leaveQueue(sim.qWait);
        await this.delay(sim.delay.sample());
        this.leaveQueue(sim.qResource);
    }
    

    The seize method also allows you to specify a preempt signal, which is used to provide preemptive behavior. If used, entities with higher priority will be able to temporarily stop lower-priority entities, perform their work, and restore the suspended entities when done. For example:

    async script() {
    
        // execute some work allowing higher-priority entities to 
        // temporarily suspend the transaction and resume it later.
        // (this example uses sim.qResource as a preempt signal)
        await this.seize(sim.qResource, sim.delay.sample(), sim.qWait, sim.qResource);
    }
    

    Parameters

    • resource: Queue

      Resource to seize.

    • delay: number

      Amount of time required to perform the work.

    • waitingQueues: Queue | Queue[] = null

      Waiting queues. Waiting queues should have unlimited capacity.

    • preemptSignal: any = null

      Signal used to pre-empt the resource (defaults to none).

    • units: number = 1

      Number of Queue capacity units to seize.

    Returns Promise<void>

sendSignal

  • sendSignal(signal: any, releaseMax?: number): number
  • Sends a signal that releases entities currently waiting for the signal.

    Parameters

    • signal: any

      Signal value.

    • Optional releaseMax: number

      Maximum number of entities to release. If not specified, all entities waiting for the signal are released.

    Returns number

toString

  • toString(): string
  • Returns a string representation of the Entity.

    This method is typically used for debugging.

    Returns string

    A string representation of the Entity.

waitSignal

  • waitSignal(signal: any): Promise<number>
  • Pauses entity execution until another entity sends a signal.

    For example, the code below shows how you could use the sendSignal and waitSignal methods to simulate a traffic light:

    class Car extends Entity {
        async script() {
            let sim = this.simulation as CrossWalk;
    
            // enter crossing wait area
            await this.enterQueue(sim.qCarXing);
    
            // wait for green light
            while (sim.light != Signal.GREEN) {
                await this.waitSignal(Signal.GREEN);
            }
    
            // leave crossing wait area
            this.leaveQueue(sim.qCarXing);
        }
    }
    class TrafficLight extends Entity {
        async script() {
            let sim = this.simulation as CrossWalk;
            while (true) {
                this.setLight(Signal.GREEN);
                await this.delay(sim.cycle.green);
                this.setLight(Signal.YELLOW);
                await this.delay(sim.cycle.yellow);
                this.setLight(Signal.RED);
                await this.delay(sim.cycle.red);
            }
        }
        setLight(value: Signal) {
            const sim = this.simulation as CrossWalk;
            sim.light = value;
            let released = this.sendSignal(value);
            console.log('light is', Signal[sim.light], released, 'entities released at', sim.timeNow);
        }
    }
    

    Note that calls to async methods such as delay, enterQueue, seize, and waitSignal should be preceded by the await keyword.

    Parameters

    • signal: any

      Value of the the signal to wait for.

    Returns Promise<number>

    The amount of simulated time elapsed since the method was invoked.

Generated using TypeDoc