{"id":1047,"date":"2016-10-05T16:24:52","date_gmt":"2016-10-05T21:24:52","guid":{"rendered":"http:\/\/rpchurchill.com\/?p=1047"},"modified":"2016-10-05T16:24:52","modified_gmt":"2016-10-05T21:24:52","slug":"a-simple-discrete-event-simulation-part-20","status":"publish","type":"post","link":"https:\/\/rpchurchill.com\/wordpress\/posts\/2016\/10\/05\/a-simple-discrete-event-simulation-part-20\/","title":{"rendered":"A Simple Discrete-Event Simulation: Part 20"},"content":{"rendered":"<p>After defining things more clearly yesterday I offer this version of an arrivals component.  Here&#8217;s how it&#8217;s supposed to work.<\/p>\n<p>The component is created using an external call.<\/p>\n<p>The graphic properties are initialized using a separate call to <code>this.basicDefine<\/code>.  Most of the graphic characteristics are fixed; only the location and colors can be changed.  Once we&#8217;re done debugging this capability would no longer be needed, but for now it demonstrates something of the separation between the model and what is displayed.  The method to draw the component is <code>this.basicDisplay<\/code>, and it should be called whenever the status is updated.<\/p>\n<p><code>this.blockIncrement<\/code> is called using the discrete-event mechanism to generate the entities for that time span.<\/p>\n<p><code>this.entityStatus<\/code> is called when the generated entities wake up for the first time.  The entities have to be able to refer back to the generator that created them in order to display the activation status in this way.<\/p>\n<p><code>this.destroy<\/code> is probably not needed, but is included for completeness and because good housekeeping is usually desirable.<\/p>\n<p><code>this.activate<\/code> is the standard discrete-event activity mechanism for timed activities.<\/p>\n<p>All values needed to display the component&#8217;s status are declared as properties.<\/p>\n<p>All of the initialization, display, and activity code is folded directly into the element&#8217;s object definition.<\/p>\n<p>It has not been debugged and run yet so there are doubtless some errors and omissions.  Remember that any updates to the display involve clearing the screen and cycling through all of the objects to get them to draw themselves.  This being the case the call to draw things should not be evoked as shown here.  Rather, a global redraw flag should be set which initiates that process if appropriate when events are pulled from the future events queue or current events queue.<\/p>\n<pre class=\"toolbar-overlay:false wrap:false height-set:true lang:default decode:true \">\r\n    var globalCTX;\r\n\r\n    \/\/function to generate new entities\r\n    this.generateNewEntity = function(generator,start) {\r\n      \/\/generator is an arrivals component\r\n      \/\/start is an initial activation time\r\n      var newEntity = new entityA(start);\r\n      setOfEntities.push(newEntity);\r\n      generator.entityStatus();\r\n    }\r\n\r\n    \/\/Arrivals component: generates entities that will be processed by the model\r\n    function arrivalsComponent(scheduleBlockMinutes,scheduleArray) {\r\n      setOfEntities.push(this);\r\n      this.componentID = getNewID();\r\n      this.componentName = \"arrivals\";\r\n      this.startBlockTime = globalSimClock;\r\n      this.incrementTime = scheduleBlockMinutes;\r\n      this.endBlockTime = globalSimClock + this.incrementTime;\r\n      this.entitiesScheduled = 0;\r\n      this.entitiesRemaining = 0;\r\n      this.currentEntityID = \"\";\r\n      this.activity = \"creation\";\r\n      this.scheduleIndex = 0;\r\n      this.endTime = endSimTime;\r\n      this.nextState = \"increment\";\r\n      feq.newItem(globalSimClock,this);  \/\/assume all components created at time zero\r\n      this.basicDefine = function(x,y,cs,cl,cv,ctx) {\r\n        this.xLocation = x;\r\n        this.yLocation = y;\r\n        this.width = 150;\r\n        this.height = 112;\r\n        this.colorShape = cs;\r\n        this.colorLabels = cl;\r\n        this.colorValues = cv;\r\n        this.ctx = ctx;     \/\/ctx is a canvas context handle\r\n      }\r\n      this.basicDisplay = function() {\r\n        this.ctx.strokeStyle = this.colorShape;\r\n        this.ctx.beginPath();\r\n        this.ctx.moveTo(this.xLocation+0.5,this.yLocation+0.5);\r\n        this.ctx.lineTo(this.xLocation+this.width+0.5,this.yLocation+0.5);\r\n        this.ctx.lineTo(this.xLocation+this.width+0.5,this.yLocation+this.height+0.5);\r\n        this.ctx.lineTo(this.xLocation+0.5,this.yLocation+this.height+0.5);\r\n        this.ctx.lineTo(this.xLocation+0.5,this.yLocation+0.5);\r\n        this.ctx.stroke();\r\n        this.ctx.font = \"12px Arial\";\r\n        this.ctx.fillStyle = this.colorLabels;\r\n        this.ctx.textAlign = \"center\";\r\n        this.ctx.fillText(this.componentName,x+(this.width*0.5),y+12);\r\n        this.ctx.textAlign = \"right\";\r\n        this.ctx.fillText(\"Comp. ID:\",this.xLocation+78,this.yLocation+24);\r\n        this.ctx.fillText(\"Start Time:\",this.xLocation+78,this.yLocation+36);\r\n        this.ctx.fillText(\"Current Time:\",this.xLocation+78,this.yLocation+48);\r\n        this.ctx.fillText(\"End Time:\",this.xLocation+78,this.yLocation+60);\r\n        this.ctx.fillText(\"# Entities:\",this.xLocation+78,this.yLocation+72);\r\n        this.ctx.fillText(\"# Remaining:\",this.xLocation+78,this.yLocation+84);\r\n        this.ctx.fillText(\"Entity ID:\",this.xLocation+78,this.yLocation+96);\r\n        this.ctx.fillText(\"Activity:\",this.xLocation+78,this.yLocation+108);\r\n        this.ctx.fillStyle = this.colorValues;\r\n        this.ctx.textAlign = \"left\";\r\n        this.ctx.fillText(this.componentID,this.xLocation+83,this.yLocation+24);\r\n        this.ctx.fillText(this.startBlockTime.toFixed(5),this.xLocation+83,this.yLocation+36);\r\n        this.ctx.fillText(globalSimClock.toFixed(5),this.xLocation+83,this.yLocation+48);\r\n        this.ctx.fillText(this.endBlockTime.toFixed(0),this.xLocation+83,this.yLocation+60);\r\n        this.ctx.fillText(this.entitiesScheduled.toFixed(0),this.xLocation+83,this.yLocation+72);\r\n        this.ctx.fillText(this.entitiesRemaining,this.xLocation+83,this.yLocation+84);\r\n        this.ctx.fillText(this.currentEntityID,this.xLocation+83,this.yLocation+96);\r\n        this.ctx.fillText(activity,this.xLocation+83,this.yLocation+108);\r\n      };\r\n      this.entityStatus = function(entity) {\r\n        this.currentEntityID = entity.entityID;\r\n        this.activity = \"activate\";\r\n        this.entitiesRemaining--;\r\n        \/\/this.basicDisplay(ctx);  \/\/set global redraw flag instead\r\n      };\r\n      this.blockIncrement = function() {  \/\/should be called at the beginning of every time block\r\n        \/\/get arrival count per array index\r\n        this.entitiesScheduled = scheduleArray[this.scheduleIndex];\r\n        if (this.entitiesScheduled > 0) {\r\n          var arrivalArray = [];\r\n          for (var i=0; i<this.entitiesScheduled; i++) {\r\n            arrivalArray[i] = Math.random() * scheduleBlockMinutes;\r\n          } \r\n          \/\/sort the array\r\n          arrivalArray.sort(compareNumeric);\r\n          \/\/generate the arrivals          \r\n          for (var i=0; i<this.entitiesScheduled; i++) {\r\n            var arrivalBump = arrivalArray[i];\r\n            this.generateNewEntity(this,globalSimClock + arrivalBump);\r\n          } \r\n          \/\/set global redraw flag\r\n        }\r\n        this.scheduleIndex++;\r\n        displayProgressText(\"Entry component \"+this.componentID+\" generates \"+this.entitiesScheduled+\" new entities at time \"+globalSimClock);\r\n        \/\/set values for display-------------\r\n        this.startBlockTime = globalSimClock;\r\n        this.endBlockTime = globalSimClock + this.incrementTime;\r\n        this.entitiesRemaining = this.entitiesScheduled;\r\n        this.currentEntityID = \"\";\r\n        this.activity = \"generate\";\r\n        \/\/----------------------------------\r\n        if (globalSimClock + this.incrementTime >= this.endTime) {\r\n          this.nextState = \"destroy\";\r\n        }\r\n        advance(this.incrementTime);\r\n      }\r\n      this.destroy = function() {\r\n        displayProgressText(\"Entry component \"+this.entityID+\" terminated at time \"+globalSimClock);\r\n        \/\/do something to take this element out of the global element list - setOfEntities\r\n      };\r\n      this.activate = function() {\r\n        if (this.nextState == \"increment\") {\r\n          this.blockIncrement();\r\n        } else if (this.nextState == \"destroy\") {\r\n          this.destroy();\r\n        } else {\r\n          errorUndefinedAdvanceState(this.entityID,this.nextState);\r\n        }      \r\n      }\r\n    };  \/\/arrivalComponent\r\n\r\n    \/\/schedule for six hours of arrivals in half-hour blocks\r\n    var arrivalSchedule = [0,0,1,3,4,4,5,6,3,2,1,0]; \r\n    \r\n    var arrival1 = new arrivalComponent(30.0,arrivalSchedule);\r\n    arrival1.basicDefine(20,20,\"#00FFFF\",\"#8888FF\",\"#FF0000\",globalCTX);\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>After defining things more clearly yesterday I offer this version of an arrivals component. Here&#8217;s how it&#8217;s supposed to work. The component is created using an external call. The graphic properties are initialized using a separate call to this.basicDefine. Most &hellip; <a href=\"https:\/\/rpchurchill.com\/wordpress\/posts\/2016\/10\/05\/a-simple-discrete-event-simulation-part-20\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[60],"tags":[121,49],"_links":{"self":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts\/1047"}],"collection":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/comments?post=1047"}],"version-history":[{"count":1,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts\/1047\/revisions"}],"predecessor-version":[{"id":1048,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts\/1047\/revisions\/1048"}],"wp:attachment":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/media?parent=1047"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/categories?post=1047"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/tags?post=1047"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}