JSSim
JavaScript Discrete Simulation Tool
Version 2


 

Contents

1 Introduction

2 Object-Oriented Programming in JavaScript

3 JSSim Basic Ideas

4 Time Control

5 Random Numbers

6 Statistics

7 Data Structures

8 Utilities

9 Input/Output General Guidelines

10 Examples

 

 

 

 

J. Sklenar
Department of Statistics and Operations Research
Faculty of Science
University of Malta
Malta, January 2008

Footer Navigation



1 Introduction

JavaScript is a script language interpreted by web browsers. JavaScript is the original name owned by Netscape, a similar language is called JScript by Microsoft. Both are supposed to be compatible with the standard ECMA-262 that is also approved by the ISO as ISO-16262. That’s why the language is also called ECMAScript. Next the name JavaScript will be used. Compatibility with the ECMA standard does not guarantee equal behavior in all browsers, so it is suggested to check pages that use JSSim code in your favorite browser. Note also that currently JSSim supports only client-side applications.

 

JavaScript is not a classical class-based strongly typed object-oriented language (OOL) like for example Simula or Java. In fact it is the opposite. Nevertheless the object model of JavaScript enables use of all important techniques of object-oriented programming (OOP), either directly or with some additional support. For example inheritance has to be programmed explicitly. That’s why the chapter 2 of this manual shows how to use the techniques of object-oriented programming in JavaScript. Regarding other features of the language, JavaScript contains everything that we expect in a high-level language. Description of the language as such is of course out of the scope of this manual.

 

A JavaScript programmer is thus making use of a modern programming language that, together with HTML, supports creation of documents that can contain user-friendly input of validated data, any kind of data processing, and lucid presentation of results. Solutions based on JavaScript and HTML are typically placed on the web and made thus available literally to everybody who has a browser supporting particular versions of these two languages. These capabilities have been applied to create various web-hosted problem-solving tools. Such tools can contain simple and medium-scale simulation models. Several simulation models have already been implemented and placed on the web with very encouraging response. Routines used to create these models, including a simple event-oriented simulation engine together with a collection of classes for general use in discrete simulation, have been collected into a tool called JSSim (JavaScript Simulation). This document is a JSSim manual that assumes that the reader is familiar with JavaScript and HTML.

 

Back to top


2 Object-Oriented Programming in JavaScript

In this chapter we assume that the reader is familiar with basic ideas of object-oriented programming. A very fundamental introduction is available in my Turbo Pascal page at: http://staff.um.edu.mt/jskl1/turbo.html#OOP .

 

Everything is an object

 

Some authors would not call JavaScript an OOL, but in fact JavaScript programmer works only with objects and their methods and properties. If not stated explicitly, properties mean value attributes, but in JavaScript there is actually very little difference between value attributes – properties and procedure attributes - methods. Due to loose typing a property can become a method and vice versa. Most JavaScript “programs” are short snippets incorporated into HTML documents by using the tag <SCRIPT> that can also reference a separate file with JavaScript code (default extension js). JavaScript code is processed by the browser’s interpreter as a part of the (re)loading process. Such code typically defines functions and declares and initializes global variables. Using OOP terminology, such code is interpreted in the context of the so-called global object. For each browser window or each frame within a window a separate global object is created. So for example a global variable declared by the following statement:

 

var expduration = 1000;  //default experiment duration

 

in fact creates (declares) a property of the global object that can be called directly by its name, but also as this.expduration or window.expduration. The keyword this is a reference (handle) of the current object. Similarly each global function declared by the user is a method of the particular global object. All standard properties and functions are also pre-defined properties of the global objects (for example mathematical functions and constants are accessible through the Math object that is an automatically created property of the global object). What about the statements written directly in <SCRIPT> tags? Here the best analogy is the “life” as defined for Simula class instances. There can be a lot of such code in several <SCRIPT> tags and in js files. All this code is performed in lexical order as the life of the global object (obviously without any possibility to break and postpone its execution). Interpreted JavaScript has only run-time; compile-time does not exist. Still there are two stages: (re)loading is a sort of early or first run-time stage. During this stage the programmer creates all global data that includes “declaration” of prototypes – see later, and creation of global object instances. Second run-time stage is made of execution of functions activated by browser events (like for example pressing a button). Even now, all is done in the context of the so-called call object. Each activation of a function creates a separate call object, so declaration of a local variable (say var x = 0;) in fact creates a property of the call object. Actual parameters of the function call are also considered as properties of the call object (there is another array property arguments that contains all parameters passed to the function, so in JavaScript it is possible to write functions accepting variable number of parameters).

 

Every function can be a constructor

 

In JavaScript object instances are created by the operator new similarly as in practically all OOLs:

 

queue = new FifoQueue("q1”,0);  // new queue object

 

The difference between JavaScript and compiled OOLs is the fact that there is no class declaration in JavaScript. So the constructor has much more important role. Unlike constructors of compiled OOLs that basically just initialize the instance, JavaScript constructor actually creates (constructs) an instance by creating its properties and possibly methods. There is no special keyword to write constructors, so each function can potentially be a constructor. We already know that for each function call JavaScript creates a call object. It in fact creates another initially empty object (here we shall call it created object) that can be in the function body referenced by the keyword this. Functions that are not intended to be constructors ignore it. Note that call object and created object are really two distinct objects. For example consider the following statements anywhere in a function body:

 

var x = 1;

this.x = 2;

alert(x);

 

The value displayed will be 1 (property of the call object), alert(this.x) would display 2 (property of the created object). A constructor function is not supposed to return any value, but it can. If it returns an object, the standard created object is ignored and the returned object will be used instead. But there is more: in JavaScript each function is in fact represented by a function object created during parsing a function. With respect to possible use of the function as a constructor, let’s call this object constructor object or simply constructor. Unlike the other two objects associated with a function call (call and created objects) that exist only temporarily during the function execution, constructor object is permanent (it is removed by loading another document). Because it is an object, it can have properties and methods. The most important one is prototype – see the next chapter. Using OOP terminology each constructor (and so each function) has - or can have - the same role as class declaration in compiled OOLs. Whether a particular function really represents a class depends only on its body (constructors are supposed to create properties by statements like the above one: this.x = 2;) and especially on its use after the new operator. Note that constructors can create value properties and methods in unified way:

 

function point(xcoor, ycoor) {

   this.x = xcoor;

   this.y = ycoor;

   this.shift = function(dx,dy){this.x+=dx; this.y+= dy}

};

 

Note that all instances created by the above constructor will have their own code of the method shift. The obvious requirement is a code stored only once for all instances. In JavaScript this is achieved by prototypes.

 

Prototypes

 

Prototype is the property of each function (constructor), so there is one prototype for every class (provided the function is used as a constructor). JavaScript enables objects (instances) to access prototype properties and methods in the same way as its own private properties and methods: o.m() activates the method m of the object o. It can be either private local method of the instance or a prototype method common to all instances of the class of o. Sharing prototype methods by all instances is no problem, but what about value properties? JavaScript avoids clashes and side-effects by making prototype value properties read-only. They are created and initialized at parse time; instances can only read their values. They can be useful as constants common to all instances of the particular class. Creating prototype properties (not typical) and prototype methods thus completes the class definition. Let's summarize: each class is represented by two permanent objects: constructor and prototype (constructor's property) and then there can be any number of instances that can have their own properties and methods and that can access properties and methods of the two permanent objects. Using the prototype paradigm the class point can be implemented in this way:

 

function point(xcoor,ycoor) {

   this.x = xcoor;

   this.y = ycoor

};

 

point.prototype.shift = function(dx,dy) {

   this.x+=dx; this.y+=dy

};

 

Now the code of the method shift is stored only once with obvious consequence - after its modification all instances will use the modified version.

 

Standard OOP techniques

 

The two previous paragraphs give a hint how to create the usual four types of properties and methods associated with a certain class:

 

Instance value properties are created by the constructor (or by a function called by the constructor – see later) using the handle this.

 

Instance methods can be created either directly by the constructor or preferably by the prototype – see the two above examples.

 

Class value properties that are associated with the class as such, not with the individual instances can be created as properties of the constructor:

 

point.count = 0; // number of created points

 

Class constants can be properties of either the constructor:

 

point.maxX = 800; // maximum x co-ordinate

 

or the prototype which ensures the read-only access:

 

point.prototype.maxX = 800; // maximum x co-ordinate

 

Class methods associated with the class as such, not with the individual instances can be created as methods of the constructor:

 

point.distance = function(p1,p2) {

     var dx = p1.x - p2.x;

     var dy = p1.y – p2.y;

return Math.sqrt(dx*dx + dy*dy)

};

 

Note that the above declaration is logical – distance applies to two points, so it is more natural to declare it as a class method and not as an instance method.

 

Inheritance

 

Let’s consider only instance value properties and instance methods and let’s create a subclass colorpoint with one more property color and one more method changecolor. Unfortunately we have to consider separately inheritance of value properties and inheritance of methods.

 

Regarding value properties it is possible to repeat creation of superclass properties in the subclass constructor. There are two reasons against this approach: first there is redundant code and what’s more important, any modification in the superclass must be repeated in all subclasses with obvious danger of inconsistency. The solution is a function used both by the superclass and the subclass:

 

function pointProperties(xcoor,ycoor,obj) {

   obj.x = xcoor;

   obj.y = ycoor

};

 

function point(initx,inity) {

   pointProperties(initx,inity,this)

};

 

function colorpointProperties(xcoor,ycoor,icolor,obj) {

   pointProperties(xcoor,ycoor,obj);

   obj.color = icolor

};

 

function colorpoint(initx,inity,initcolor) {

   colorpointProperties(initx,inity,initcolor,this)

};

 

Inheritance outlined in the previous example can continue – colorpoint can be used as a superclass etc. Note that in order to allow inheritance; constructors just call functions that create the properties. Of course private methods can be inherited in the same way as value properties.

 

Methods stored in prototypes can be inherited either by replacing the whole prototype object or by copying the methods. The first method can be used in our example in this way:

 

colorpoint.prototype = new point(0,0);

colorpoint.prototype.changecolor = function(c) {

   this.color = c

};

 

The first statement replaces the standard prototype by a point instance; the second statement creates the new method. There are two flaws – first the new prototype has also the two value properties (x and y). It is not a mistake. Assuming that the constructor creates properties with the same names, prototype read-only properties are not visible and the only problem is wasted memory. The second flaw is more serious. All prototypes have a property constructor that is a reference to the function object of the constructor function that has created this object. It can be very useful to check types of instances (like “is” in Simula). Obviously by replacing the standard prototype by another object as in the above example, the constructor property also changes. To get exactly what we want, methods have to be copied from superclass to subclass. The following function uses the fact, that objects in JavaScript can be treated as associative arrays and a special form of the “for” statement based on this fact:

 

function inherit(from,to) {

    for(var p in from.prototype)

     if (typeof from.prototype[p] == "function")

        to.prototype[p] = from.prototype[p]

};

 

inherit(point,colorpoint);

colorpoint.prototype.changecolor = function(c) {

   this.color = c

};

 

The first statement copies all prototype methods; the second statement creates the new method.

 

Polymorphism

 

Polymorphism is basically not compatible with strong typing. That’s why classical compiled OOLs introduce late binding through virtual methods that represents probably the most complicated part of OOP. Note that Java does not have virtual methods, but it means that all methods are in fact virtual. Programmer’s comfort is paid by time. Interpreted loosely typed JavaScript is polymorphic by nature. Moreover polymorphism is not limited to inheritance sequences. Consider the next two statements: p = x; p.m(); They will work for any object x that has a method m. JavaScript does not perform any type check, everything is the programmer’s responsibility. So the flexibility is paid by very limited security. That’s why JavaScript can not compete with classical OOLs in large software development projects.

 

 

Other techniques

 

Interpreted JavaScript enables techniques not conceivable in compiled strongly typed OOLs. Among others the following is possible:

 

Adding instance properties and methods can be a fast alternative to inheritance, especially in case of small number of instances. At any time it is possible to create new properties and methods:

 

origin = new point(0,0);

p = new point(ix,iy);

p.d = point.distance(origin,p); //New property of p

p.dupdate = function() {        //New method of p

   this.d = point.distance(origin,this)

};

 

Modification of instance properties and methods is also possible. It can be used for example as an alternative to status variables. Instead of testing a status, activate directly the method that has been updated accordingly. It is also possible to change a method into a property and vice versa, but then they have to be treated accordingly.

 

Partial inheritance is a technique not allowed in OOLs. Nevertheless there are situations when a simplified version of a certain class is required. This technique has been used in JSSim to create a discrete random distribution object as a simplified version of general random distribution object that has already been available. The point is inheriting only some methods (obviously they must be self-sufficient). The following example shows another version of the function inherit - actually the one available in JSSim and its use. The function first tests the number of actual parameters passed to it. If there are two parameters it copies all methods as in the above example. Otherwise it assumes that after the first two object parameters there is a list of strings – names of methods to be copied:

 

function inherit(from,to) {

  if (arguments.length == 2) { // Inherit all

    for(var p in from.prototype)

     if (typeof from.prototype[p] == "function")

       to.prototype[p] = from.prototype[p]

  } else {                     // Inherit the listed methods

    for (var i=2; i<arguments.length; i++)

     to.prototype[arguments[i]] =

             from.prototype[arguments[i]];

  }

};

inherit(Distribution,DiscreteDistribution,

        'fixtable','last','compareWithLastValue','showTable',

        'accept','edit','insert','deleteit','cleartable',

        'confirmtable','generate','save','load');

 

Only the 13 listed methods are inherited.

 

Conclusion

 

JavaScript programmers can use all fundamental techniques of OOP together with new techniques offered by loose JavaScript typing.

 


Back to top


3 JSSim Basic Ideas

JSSim is a collection of JavaScript declarations that together with appropriate HTML documents support user-friendly development of web hosted tools that contain simple and medium scale simulation models. Simulation models based on JSSim are incorporated into HTML documents. HTML code implements the link between the model and the user – it is used for inputs and outputs of the model and to control it. JavaScript code is made of two parts – JSSim JavaScript source file(s) and the user JavaScript code, preferably also in a separate file. All JSSim declarations are included in the file jssim.js, so a heading of the HTML document is supposed to contain the following script tag:

<SCRIPT LANGUAGE="JavaScript" SRC="jssim.js"></SCRIPT>

JSSim also exist as a collection of separate source files, so in order to save loading time of the document it is possible to include only files with used declarations. User JavaScript code can be written either directly in a script tag as it is done in the demo examples, or preferably in a separate js file referenced by a script tag similar to the one above. There will also be short snippets of JavaSript code written directly in HTML tags – for example validation of input data. These snippets can be just calls to functions written either by the user or standard JSSim validation functions – see later.

Facilities found in languages and tools for programming discrete simulation models can be classified into the following main groups:

 

-        Time control, synchronization and communication of processes

-        Generation of random numbers

-        Transparent collection of statistical data and statistical analysis

-        Advanced data structures

-        User-friendly Input and Output

Next chapters will summarize the implementation of these facilities in JSSim together with specific functions given by the web-hosted nature of the models.

Back to top


 

4 Time Control

To select the time control of JSSim models we have considered only the two commonly used approaches. While the process-oriented discrete simulation represents the most advanced way of modeling the dynamics of complex systems, the classical event-oriented approach is simpler and easier to learn and to implement. That’s why it has been chosen for a JavaScript based tool that is not intended for large simulation studies. Assuming that the reader is familiar with the event-oriented principle, these are the basic facts: During (re)loading of the document the engine creates two global variables: the time and the empty sequencing set (SQS – name borrowed from Simula). Events are represented by event notices created by the user and stored in the SQS. Each event notice has the occurrence time of the event and any other user-defined data. The engine assigns the time when the event is scheduled. From the user’s point of view, the SQS is a list of event notices ordered by the time of occurrence in increasing way. After activation, the engine repeatedly removes the first event notice from SQS, updates the model time, and activates a user routine that is given the reference to the event notice. Simulation ends by the empty SQS or by any user supplied condition. These are the engine routines that are called from the user’s part of the simulation model:

 

initialize_run() is a routine that clears the SQS (the previous experiment may have finished with nonempty SQS) and sets the model time to zero. It should be called at the beginning of the model initialization.

 

evnotice() is the event notice constructor. It returns an object with the time property that is used later by the engine and should not be accessed by the user. The user can add any other properties to distinguish between types of events and to store other model dependent data.

 

schedule(event,t) schedules the event whose notice is the first parameter at the time given by the second parameter. It is not possible to go back in time, so for t less than modeltime() the event is scheduled at modeltime().

 

modeltime() is the current time of the model. Scheduling an event e after a delay d is performed as follows:

 

  schedule(e,modeltime()+d)

 

cancel(event) cancels a scheduled event. The function returns a Boolean value that reports whether canceling was successful – the function returns false if event has not been scheduled.

 

sim_run(stats,length,run,expers) starts the simulation experiment. This routine should be called after the model initialization that has to schedule at least the first event. The first two arguments control the progress reporting in the status bar. If stats is true, time progress will be reported, length is shown as the duration of the experiment. If stats is false, only the run number is shown. The last two arguments are the current run number and the total number of repetitions. The routine ends by reaching the empty SQS or by the user supplied terminating condition - the user’s routine finish_run().

 

simulation_run(stats,length) starts the simulation experiment. It is the old version of the above routine before repetitions were implemented. It is kept for compatibility of older models.

 

The above routines are common to all simulation models. Model specific behavior is implemented by two routines that have to be supplied together with the code (preferably also a routine) that starts the simulation. These are the routines (together with examples) that represent the user’s part of the simulation control:

 

finish_run() tests whether simulation should be terminated. It is called by the engine after updating the model time just before activating the next event. It can just test the time against the experiment duration or it can implement a more complicated terminating condition, like for example serving a given number of customers. The following is the function of a model where the experiment is finished by reaching its duration runlength:

 

function finish_run() {

  return (modeltime()>runlength)

};

 

eventroutine(event) is activated by the engine each time an event is to occur. The routine is given the reference to the event notice that has been removed from the SQS. The rest is the user's responsibility. Typically there will be some properties created by the user used to switch between various types of events. It might be a good idea to keep this routine short and simple and to write routines for various types of events similarly as they are written in event oriented simulation languages. The following is the function of a model with two types of events. Note that the event notices have two user-defined properties: eventtype and servnum (the server number):

 

function eventroutine(event) {

  switch (event.eventtype) {

    case 1:  next_arrival(); break;

    case 2:  end_of_service(event.servnum); break;

    default: alert("Wrong eventtype: " + event.eventtype)

  }

};

 

The start of simulation has also to be programmed. For example it can be a function activated by pressing a button “Run”. This function is supposed to perform the following activities exactly in this order:

 

-        Initialization of the engine by initialize_run()

-        Model specific initialization

-        Starting simulation by simulation_run()

-        Model specific experiment evaluation.

 

The following is an example of a function activated by pressing the button “Run” and its link to HTML for the single queue simulation model version #1.

 

<INPUT TYPE="button" VALUE="Run" onClick="simulation()">

 

function simulation() {       // Simulatiom experiment

   if ((arrival.disttype=="User") && !(arrival.confirmed)) {

     alert("Can't start simulation. Arrival intervals table

            has not been confirmed.");

     return false;

   };

   if ((service.disttype=="User") && !(service.confirmed)) {

     alert("Can't start simulation. Service duration table

            has not been confirmed.");

     return false;

   };

   initialization();          // Model global initialization

   runnumber = 1;

  

   while (runnumber<=numofexp) {  // Repetitions loop

 

     initialize_run();        // This prepares the engine

     run_init();              // Run initialization

     nextarrival();           // Scheduling first arrival 

     sim_run(showstatus,runlength,runnumber,numofexp);

                              // This starts the simulation

    

     lqe.update(queue.average()); // queue length statistics

     wqe.update(wtime.average()); // queue time statistics

     le.update(ssize.average());  // system size statistics

     we.update(stime.average());  // system time statistics

    

     runnumber++;

   };

   evaluation();              // Experiment evaluation

   return true;

};

 

Back to top


5 Random Numbers

JSSim contains a rather complex class used to generate instances (objects) that represent random numbers. These can have either a theoretical distribution, but primarily they are supposed to contain tables used to generate values with a general (for example experimentally obtained) distribution. Methods are available for entering and editing such tables. Working with empirical tables is user-friendly; table entries can be modified, inserted and deleted. Table can be entered as a cdf (cumulative distribution function) or a pdf (probability distribution function). In both cases there is a re-calculation to the other type. During editing tables can be left temporarily inconsistent, but before use a table has to be checked and confirmed. Both values and cdf entries must form non-decreasing sequences. Sum of probabilities has to be 1; a confirmation method offers adjustment of the last entry if the sum is smaller. Associated HTML text contains a help that explains the basic ideas and the inversion method, so only basic knowledge of probability is assumed. Large tables can be saved and loaded (provided cookies are enabled in the browser). Figure 1 shows a table created by HTML used to enter parameters of a random variable. The controls are self-explaining. Figure 1 shows the situation just after confirmation of an empirical cdf table by pressing the button “Check & Confirm”. Inversion is used for generation that can be either discrete or interpolated. The technique of restricted inheritance (simplification) mentioned earlier was used do declare a simplified version of this class for generation of discrete random numbers with empirical distribution only. Its instances have been used for example to represent random movements of customers in queueing networks. Work with random numbers is very simple. Instances are first created by statements similar to the following one located typically in the head code that is interpreted during loading of the document:

 

var arrival = new Distribution("a1");

 

The method generaten(n) returns the random values generated by the random stream n. So during simulation statements similar to the next one are used:

 

var x = arrival.generaten(1);

 

 

 

Figure 1: Entering parameters of a random variable

 

Initially JSSim used the standard JavaScript random generator Math.random(). Later a Linear Congruential Generator (LCG) has been implemented with constants known as MINSTD (Minimum Standard) that passed all usual tests. JSSim contains routines for initialization and use of any number of random streams, for details see the code. To keep compatibility, the random objects now contain two generation methods. One is using the standard generator Math.random(), the other one is using a JSSim random stream of a given number.

 


 

The following is the class summary of the random object that lists the constructor, the value properties that might be useful, and the methods. Next we shall keep this format. For more details see the JavaScript code and the examples.

 

Class Distribution

 

Constructor

 

Distribution(name)   .name = object and screen text name

 

Properties

 

status               user table distribution status

confirmed            whether user distribution has been confirmed

disttype             type of distribution

enterMode            entering mode (pdf, cdf)

generMode            generation mode (continuous, discrete)

 

Methods

 

scrupdate()          screen update

update(index)        internal update

 index = distribution type

testpar1(tx)         testing first distribution parameter

 tx = tested value (text)

testpar2(tx)         testing second distribution parameter

 tx = tested value (text)

fixtable()           conversion pdf – cdf

last()               index of last table entry

compareWithLastValue(textElement)    testing next table entry

                      textElement = the text value

showTable()          converting table to text form

accept(tx,tp)        acceptind value,probability pair

                      tx = value

                      tp = probability (or cdf value)

edit()               editing a table entry

insert()             inserting a table entry

deleteit()           deleting a table entry

cleartable()         erasing the table and data

confirmtable()       checking the table

generate()           generating next random value by using the standard JavaScript generator Math.random()

generaten(n)         generating next random value by using the native JSSim LCG generator

                      n = number of random stream used

toString()           converting all parameters to string

save(cn)             saving to a cookie

 cn = cookie name

load(cn)             loading from a cookie

 cn = cookie name

fromString(cv)       extracting parameters from a string

 cv = string

 


 

Class DiscreteDistribution

 

Constructor

 

DiscreteDistribution(name) name = object and screen text name

 

Properties

 

status               user distribution status

confirmed            whether user distribution has been confirmed

disttype             type of distribution

enterMode            entering mode (pdf, cdf)

generMode            generation mode (continuous, discrete)

 

Methods

 

scrupdate()          screen update

fixtable()           conversion pdf – cdf

last()               index of last table entry

compareWithLastValue(textElement)    testing next table entry

                      textElement = the text value

showTable()                converting table to text form

accept(tx,tp)        acceptind value,probability pair

                      tx = value

                      tp = probability (or cdf value)

edit()               editing a table entry

insert()             inserting a table entry

deleteit()           deleting a table entry

cleartable()         erasing the table and data

confirmtable()       checking the table

generate()           generating next random value by using the standard JavaScript generator Math.random()

generaten(n)         generating next random value by using the native JSSim LCG generator

                      n = number of random stream used

toString()           converting all parameters to string

save(cn)             saving to a cookie

 cn = cookie name

load(cn)             loading from a cookie

 cn = cookie name

fromString(cv)       extracting parameters from a string

 cv = string

 

Back to top


6 Statistics

To collect statistics of a certain variable x automatically, it is necessary to update certain figures (like for example its time integral) after each updating of x. In other words all assignment statements that have x on the left side must also activate a certain routine that updates what is necessary. Simulation languages like Simscript do it automatically (Simscript calls this mechanism left monitoring), but there is of course nothing like that in JavaScript. Transparent collection of statistical data and simple statistical analysis are implemented by the classes Accumulator and Tally (Simscript terminology is used). The instances of these two classes are basically real variables with transparent collection of statistics. The consequence for the user is the difference in the form of the assignment statement. The usual a = x has to be replaced by a method call a.updateto(x). They differ in time treatment.

Tally ignores the time; the statistics is based on the collection of the assigned values only. Objects of the class Tally are thus used for figures whose statistics does not depend on time integrals. As an example consider time spent in a queue. It is calculated for each customer at the beginning of the service by subtracting the time when the customer arrived to the queue from the current time. Each calculation then updates the statistical object. The following has to be done:

 

1) Tally object is created, typically by the head code:

 

waitingtime = new tally();

 

2) Before starting the experiment the Tally object has to be initialized:

 

waitingtime.initiate();

 

3) For each customer it is updated similarly as follows where cust is the customer handle and sertimein is the arrival time:

 

waitingtime.update(modeltime() - cust.ser