Some months ago I discussed some internal features of a discrete-event simulation. My next series of exercises and ruminations will proceed toward building one in JavaScript, using the simple pseudo-construct I outlined in the linked post.
I’ll start with the creation of a future events queue. Since the point is to get something running in a reasonably brief series of posts I’ll keep it simple. There are many ways to make a future events queue more efficient, but for our purposes we’ll create one with a straightforward insert/pull structure. That is, it’ll be a single list of items, sorted by time (we’ll assume items occurring at the exact same time are processed in the order in which they were added to the queue, in one dimension.
Here’s a rough bit of code I worked out a while ago.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
//global simulation clock var globalSimClock = 0.0; //starts at zero, units to be specified var globalSimUnits = "minutes"; var globalInsertTime = 0.0; //events queue item function futureEventItem(time,type,entityID,previousState,nextState) { this.activationTime = 0.0; if (type == "advance") { this.activationTime = globalSimClock + time; //activate 'time' from now } else if (type == "absolute") { if (time > globalSimClock) { this.activationTime = time; //activate at specified absolute time, if in future } else { alert("Invalid time past time supplied. Entity ID: "+entityID+" Current Time: "+globalSimClock+" Speficied Time: "+time); //alert on invalid time } } this.entityID = entityID; this.previousState = previousState; this.nextState = nextState; this.getActivationTime = function() { return this.activationTime; }; this.reportItem = function() { console.log("Time: "+this.activationTime+" ID: "+this.entityID+" Prev: "+this.previousState+" Next: "+this.nextState); }; }; //futureEventItem function futureEventsQueue() { this.feq = new Array(); this.feqSize = 0; this.insertTime = 0.0; this.findLaterTime = function(item) { globalSimClock = 10.0; var a = item.getActivationTime(); var b = globalInsertTime; //this.insertTime; why is the scope of "this" messed up here? window and not queue var result = a > b; return result; }; this.insertItem = function(time,type,entityID,previousState,nextState) { //create futureEventItem var feqItem = new futureEventItem(time,type,entityID,previousState,nextState); this.insertTime = feqItem.getActivationTime(); globalInsertTime = this.insertTime; if (this.feqSize == 0) { this.feq[0] = feqItem; this.feqSize++; console.log("Array size: "+this.feq.length); } else { //find index of feq item to insert before var insertIndex = this.feq.findIndex(this.findLaterTime); //var insertIndex = this.feq.findIndex(this.findLaterTime1); //insert the element if (insertIndex < 0) { insertIndex = this.feq.length; } this.feq.splice(insertIndex,0,feqItem); this.feqSize++; console.log("Array size: "+this.feq.length); } }; this.reportSize = function() { console.log("Number of events in queue: "+this.feqSize); }; }; //futureEventsQueue function reportItemInfo(element, index, arr) { globalSimClock = 10.0; console.log("reportItemInfo: element: "+element+" index: "+index+" arr: "+arr); element.reportItem(); } function findLaterTime1(item) { globalSimClock = 10.0; return item.getActivationTime() > globalInsertTime; }; //initialize future events queue feq = new futureEventsQueue(); feq.reportSize(); //should be zero; feq.insertItem(40.0,"absolute",333,"prev1","next1"); feq.feq.forEach(reportItemInfo); feq.reportSize(); //should be 1 globalSimClock = 10.0; feq.insertItem(20.0,"advance",444,"prev2","next2"); feq.feq.forEach(reportItemInfo); feq.reportSize(); //should be 2 feq.insertItem(50.0,"absolute",555,"prev3","next3"); feq.feq.forEach(reportItemInfo); feq.reportSize(); //should be 3 |
This code generates the following output to the console, which indicates that the basic insertion mechanism is working.
Number of events in queue: 0
Array size: 1
reportItemInfo: element: [object Object] index: 0 arr: [object Object]
Time: 40 ID: 333 Prev: prev1 Next: next1
Number of events in queue: 1
Array size: 2
reportItemInfo: element: [object Object] index: 0 arr: [object Object],[object Object]
Time: 30 ID: 444 Prev: prev2 Next: next2
reportItemInfo: element: [object Object] index: 1 arr: [object Object],[object Object]
Time: 40 ID: 333 Prev: prev1 Next: next1
Number of events in queue: 2
Array size: 3
reportItemInfo: element: [object Object] index: 0 arr: [object Object],[object Object],[object Object]
Time: 30 ID: 444 Prev: prev2 Next: next2
reportItemInfo: element: [object Object] index: 1 arr: [object Object],[object Object],[object Object]
Time: 40 ID: 333 Prev: prev1 Next: next1
reportItemInfo: element: [object Object] index: 2 arr: [object Object],[object Object],[object Object]
Time: 50 ID: 555 Prev: prev3 Next: next3
Number of events in queue: 3