Today I ticked one item off the To Do list and generally streamlined other parts of the code. The list item involved modifying the Queue component so it would smoothly handle situations when the traversal time is set to zero. If you don’t recall, this is the case when modeling abstract queues like those in data processing or business systems. Even if the time isn’t technically zero in those cases an entity is theoretically ready to be retrieved from a queue the instant it’s put in there. It takes a finite amount of time to traverse a physical queue in the real world. The solution involved calling the traverseComplete
function directly in the receiveEntity
function rather than putting the event into the future events queue.
You can tell it’s working as intended by noticing that the first entities drop right through the big, common Queue component (Q0) and never show a red waiting-to-traverse status even when they stack up during the run.
1 2 3 4 5 6 |
if (this.traversalTime > 0) { //set timer for the new entity to wait through its traversal time advance(this.traversalTime, this, "traverseComplete"); } else if (this.traversalTime == 0.0) { this.traverseComplete(); } |
I originally thought this was going to be more complicated but once I recognized that I had a nicely compartmentalized traverseComplete
function with all of the requisite logic the fix was obvious.
The things I cleaned up started with rationalizing the way I defined the display and movement parameters for Path components. I originally had two ways of generating the path displays: one based on each component’s built-in dataGroup
object and one for each component’s graphics
object. It turns out that the initialization process was using a goofy mix of techniques so I changed things so the locations are all specified in the graphics
object and then transferred to the core component object. The last part is important because the actual movement is calculated in the core component object.
Another thing I streamlined was the definition of the graphics
objects in the form of the DisplayElements
constructor. I modified it so it obviated the need to supply flags for whether the incoming and outgoing nodes exist, since this can be determined automatically based on the parent component’s type, and I also added an automatic call to its defineGlobalDefaultColors
method so it doesn’t have to be invoked externally every time.
I turned off the display of the Arrivals component to save some space and sped up a couple of other items that aren’t otherwise interesting enough to describe.
Here’s the new setup code. Not that you’d notice, but it is a little shorter and cleaner.
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 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
//schedule for seven hours of arrivals in half-hour blocks var arrivalSchedule = [0, 1, 2, 6, 7, 7, 8, 9, 7, 6, 4, 2, 1, 0]; var entryDistribution = [[1.0], [1.0], [1.0], [1.0], [1.0], [1.0], [1.0], [1.0], [1.0], [1.0], [1.0], [1.0], [1.0], [1.0]]; var arrival1 = new ArrivalsComponent(30.0, arrivalSchedule, entryDistribution); arrival1.defineDataGroup(2.0, 61, 2, 70, globalNeutralColor, globalValueColor, globalLabelColor); //leave in place var tempGraphic; var routingTable = [[1.0],[1.0],[1.0]]; var entry1 = new EntryComponent(routingTable); entry1.defineDataGroup(2.0, 90, 105, 80, globalNeutralColor, globalValueColor, globalLabelColor); //displayDelay, x,y,valuewidth,border,value,label entry1.setRoutingMethod(3); //1 single connection, 2 distribution logic, 3 model logic entry1.setComponentName("Entry1"); tempGraphic = new DisplayElement(entry1, 100, 5, 68, 20, 0.0, false, false, []); entry1.defineGraphic(tempGraphic); arrival1.assignNextComponent(entry1); var pathE1Q0A = new PathComponent(); pathE1Q0A.setSpeedTime(10.0, 1.0); tempGraphic = new DisplayElement(pathE1Q0A, 0, 0, 160, 37, 0.0, false, false, []); pathE1Q0A.defineGraphic(tempGraphic); entry1.assignNextComponent(pathE1Q0A); var pathE1Q0B = new PathComponent(); pathE1Q0B.setSpeedTime(10.0, 1.0); tempGraphic = new DisplayElement(pathE1Q0B, 160, 37, 0, 0, 0.0, false, false, []); pathE1Q0B.defineGraphic(tempGraphic); var routingTableQ0 = [[1.0],[1.0],[1.0]]; //not actually needed since routingMethod is 2 here var queue0 = new QueueComponent(0.0, Infinity, routingTableQ0); queue0.defineDataGroup(2.0, 90, 205, 80, globalNeutralColor, globalValueColor, globalLabelColor); queue0.setRoutingMethod(2); //1 single connection, 2 distribution logic, 3 model logic queue0.setComponentName("Q0"); queue0.setComponentGroup("Primary"); tempGraphic = new DisplayElement(queue0, 90, 50, 88, 56, 0.0, false, false, []); var tgBaseY = 25; //49; tempGraphic.addXYLoc(44, tgBaseY + 24); tempGraphic.addXYLoc(32, tgBaseY + 24); tempGraphic.addXYLoc(20, tgBaseY + 24); tempGraphic.addXYLoc(8, tgBaseY + 24); tempGraphic.addXYLoc(8, tgBaseY + 12); tempGraphic.addXYLoc(20, tgBaseY + 12); tempGraphic.addXYLoc(32, tgBaseY + 12); tempGraphic.addXYLoc(44, tgBaseY + 12); tempGraphic.addXYLoc(56, tgBaseY + 12); tempGraphic.addXYLoc(68, tgBaseY + 12); tempGraphic.addXYLoc(80, tgBaseY + 12); tempGraphic.addXYLoc(80, tgBaseY); tempGraphic.addXYLoc(68, tgBaseY); tempGraphic.addXYLoc(56, tgBaseY); tempGraphic.addXYLoc(44, tgBaseY); tempGraphic.addXYLoc(32, tgBaseY); tempGraphic.addXYLoc(20, tgBaseY); tempGraphic.addXYLoc(8, tgBaseY); queue0.defineGraphic(tempGraphic); pathE1Q0B.assignNextComponent(queue0); pathE1Q0A.assignNextComponent(pathE1Q0B); var pathQ0Q1A = new PathComponent(); pathQ0Q1A.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathQ0Q1A, 0, 0, 20, 118, 0.0, false, false, []); pathQ0Q1A.defineGraphic(tempGraphic); queue0.assignNextComponent(pathQ0Q1A); var pathQ0Q1B = new PathComponent(); pathQ0Q1B.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathQ0Q1B, 20, 118, 0, 0, 0.0, false, false, []); pathQ0Q1B.defineGraphic(tempGraphic); var pathQ0Q2 = new PathComponent(); pathQ0Q2.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathQ0Q2, 0, 0, 0, 0, 0.0, false, false, []); pathQ0Q2.defineGraphic(tempGraphic); queue0.assignNextComponent(pathQ0Q2); var pathQ0Q3 = new PathComponent(); pathQ0Q3.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathQ0Q3, 0, 0, 0, 0, 0.0, false, false, []); pathQ0Q3.defineGraphic(tempGraphic); queue0.assignNextComponent(pathQ0Q3); var routingTableQ123 = [[1.0],[1.0],[1.0]]; //not actually needed since routingMethod is 1 here var queue1 = new QueueComponent(3.0, 3, routingTableQ123); queue1.defineDataGroup(2.0, 5, 341, 80, globalNeutralColor, globalValueColor, globalLabelColor); queue1.setRoutingMethod(1); //1 single connection, 2 distribution logic, 3 model logic queue1.setExclusive(true); queue1.setComponentName("Q1"); queue1.setComponentGroup("Primary"); tempGraphic = new DisplayElement(queue1, 5, 131, 64, 36, 0.0, false, false, []); tgBaseY = 29; //53 tempGraphic.addXYLoc(32, tgBaseY); tempGraphic.addXYLoc(20, tgBaseY); tempGraphic.addXYLoc(8, tgBaseY); queue1.defineGraphic(tempGraphic); pathQ0Q1B.assignNextComponent(queue1); pathQ0Q1A.assignNextComponent(pathQ0Q1B); var queue2 = new QueueComponent(3.0, 3, routingTableQ123); queue2.defineDataGroup(2.0, 175, 341, 80, globalNeutralColor, globalValueColor, globalLabelColor); queue2.setRoutingMethod(1); //1 single connection, 2 distribution logic, 3 model logic queue2.setExclusive(true); queue2.setComponentName("Q2"); queue2.setComponentGroup("Primary"); tempGraphic = new DisplayElement(queue2, 102, 131, 64, 36, 0.0, false, false, []); tgBaseY = 29; //53; tempGraphic.addXYLoc(32, tgBaseY); tempGraphic.addXYLoc(20, tgBaseY); tempGraphic.addXYLoc(8, tgBaseY); queue2.defineGraphic(tempGraphic); pathQ0Q2.assignNextComponent(queue2); var queue3 = new QueueComponent(3.0, 3, routingTableQ123); queue3.defineDataGroup(2.0, 175, 341, 80, globalNeutralColor, globalValueColor, globalLabelColor); queue3.setRoutingMethod(1); //1 single connection, 2 distribution logic, 3 model logic queue3.setExclusive(true); queue3.setComponentName("Q3"); queue3.setComponentGroup("Primary"); tempGraphic = new DisplayElement(queue3, 199, 131, 64, 36, 0.0, false, false, []); tgBaseY = 29; //53; tempGraphic.addXYLoc(32, tgBaseY); tempGraphic.addXYLoc(20, tgBaseY); tempGraphic.addXYLoc(8, tgBaseY); queue3.defineGraphic(tempGraphic); pathQ0Q3.assignNextComponent(queue3); var pathQ1P1 = new PathComponent(); pathQ1P1.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathQ1P1, 0, 0, 0, 0, 0.0, false, false, []); pathQ1P1.defineGraphic(tempGraphic); queue1.assignNextComponent(pathQ1P1); var pathQ2P2 = new PathComponent(); pathQ2P2.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathQ2P2, 0, 0, 0, 0, 0.0, false, false, []); pathQ2P2.defineGraphic(tempGraphic); queue2.assignNextComponent(pathQ2P2); var pathQ3P3 = new PathComponent(); pathQ3P3.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathQ3P3, 0, 0, 0, 0, 0.0, false, false, []); pathQ3P3.defineGraphic(tempGraphic); queue3.assignNextComponent(pathQ3P3); var routingTableP123 = [[0.92, 1.0],[0.85,1.0],[0.548,1.0]]; //citizen, LPR, visitor / exit, secondary var processTimeP123 = [10.0,20.8,13.0]; //fast, slow visitor, slow citizen or LPR var process1 = new ProcessComponent(processTimeP123, 1, routingTableP123); process1.defineDataGroup(2.0, 5, 477, 80, globalNeutralColor, globalValueColor, globalLabelColor); process1.setExclusive(true); process1.setRoutingMethod(3); //1 single connection, 2 distribution logic, 3 model logic process1.setComponentName("P1"); process1.setComponentGroup("Primary"); tempGraphic = new DisplayElement(process1, 5, 192, 64, 36, 0.0, false, false, []); tgBaseY = 29; //53; tempGraphic.addXYLoc(32, tgBaseY); process1.defineGraphic(tempGraphic); pathQ1P1.assignNextComponent(process1); var process2 = new ProcessComponent(processTimeP123, 1, routingTableP123); process2.defineDataGroup(2.0, 175, 477, 80, globalNeutralColor, globalValueColor, globalLabelColor); process2.setExclusive(true); process2.setRoutingMethod(3); //1 single connection, 2 distribution logic, 3 model logic process2.setComponentName("P2"); process2.setComponentGroup("Primary"); tempGraphic = new DisplayElement(process2, 102, 192, 64, 36, 0.0, false, false, []); tgBaseY = 29; //53; tempGraphic.addXYLoc(32, tgBaseY); process2.defineGraphic(tempGraphic); pathQ2P2.assignNextComponent(process2); var process3 = new ProcessComponent(processTimeP123, 1, routingTableP123); process3.defineDataGroup(2.0, 175, 477, 80, globalNeutralColor, globalValueColor, globalLabelColor); process3.setExclusive(true); process3.setRoutingMethod(3); //1 single connection, 2 distribution logic, 3 model logic process3.setComponentName("P3"); process3.setComponentGroup("Primary"); tempGraphic = new DisplayElement(process3, 199, 192, 64, 36, 0.0, false, false, []); tgBaseY = 29; //53; tempGraphic.addXYLoc(32, tgBaseY); process3.defineGraphic(tempGraphic); pathQ3P3.assignNextComponent(process3); var pathP1X1 = new PathComponent(); pathP1X1.setSpeedTime(30, 1.0); tempGraphic = new DisplayElement(pathP1X1, 0, 0, 0, 0, 0.0, false, false, []); pathP1X1.defineGraphic(tempGraphic); process1.assignNextComponent(pathP1X1); var pathP2X1 = new PathComponent(); pathP2X1.setSpeedTime(30, 1.0); tempGraphic = new DisplayElement(pathP2X1, 0, 0, 0, 0, 0.0, false, false, []); pathP2X1.defineGraphic(tempGraphic); process2.assignNextComponent(pathP2X1); var pathP3X1 = new PathComponent(); pathP3X1.setSpeedTime(30, 1.0); tempGraphic = new DisplayElement(pathP3X1, 0, 0, 0, 0, 0.0, false, false, []); pathP3X1.defineGraphic(tempGraphic); process3.assignNextComponent(pathP3X1); var exit1 = new ExitComponent(); exit1.defineDataGroup(2.0, 90, 576, 80, globalNeutralColor, globalValueColor, globalLabelColor); exit1.setComponentName("Exit1"); tempGraphic = new DisplayElement(exit1, 100, 383, 68, 20, 0.0, false, false, []); exit1.defineGraphic(tempGraphic); pathP1X1.assignNextComponent(exit1); pathP2X1.assignNextComponent(exit1); pathP3X1.assignNextComponent(exit1); var pathP1Q10 = new PathComponent(); pathP1Q10.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathP1Q10, 0, 0, 0, 0, 0.0, false, false, []); pathP1Q10.defineGraphic(tempGraphic); process1.assignNextComponent(pathP1Q10); var pathP2Q10 = new PathComponent(); pathP2Q10.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathP2Q10, 0, 0, 0, 0, 0.0, false, false, []); pathP2Q10.defineGraphic(tempGraphic); process2.assignNextComponent(pathP2Q10); var pathP3Q10 = new PathComponent(); pathP3Q10.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathP3Q10, 0, 0, 0, 0, 0.0, false, false, []); pathP3Q10.defineGraphic(tempGraphic); process3.assignNextComponent(pathP3Q10); var routingTableQ10 = [[1.0],[1.0],[1.0]]; //not actually needed since routingMethod is 2 here var queue10 = new QueueComponent(3.0, Infinity, routingTableQ10); queue10.defineDataGroup(2.0, 230, 353, 80, globalNeutralColor, globalValueColor, globalLabelColor); queue10.setRoutingMethod(2); //1 single connection, 2 distribution logic, 3 model logic queue10.setExclusive(false); queue10.setComponentName("Q10"); queue10.setComponentGroup("Secondary"); tempGraphic = new DisplayElement(queue10, 230, 253, 64, 48, 0.0, false, false, []); tgBaseY = 29; //53 tempGraphic.addXYLoc(32, tgBaseY + 12); tempGraphic.addXYLoc(20, tgBaseY + 12); tempGraphic.addXYLoc(8, tgBaseY + 12); tempGraphic.addXYLoc(8, tgBaseY); tempGraphic.addXYLoc(20, tgBaseY); tempGraphic.addXYLoc(32, tgBaseY); tempGraphic.addXYLoc(44, tgBaseY); tempGraphic.addXYLoc(56, tgBaseY); queue10.defineGraphic(tempGraphic); pathP1Q10.assignNextComponent(queue10); pathP2Q10.assignNextComponent(queue10); pathP3Q10.assignNextComponent(queue10); var pathQ10P10 = new PathComponent(); pathQ10P10.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathQ10P10, 0, 0, 0, 0, 0.0, false, false, []); pathQ10P10.defineGraphic(tempGraphic); queue10.assignNextComponent(pathQ10P10); var pathQ10P11 = new PathComponent(); pathQ10P11.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathQ10P11, 0, 0, 0, 0, 0.0, false, false, []); pathQ10P11.defineGraphic(tempGraphic); queue10.assignNextComponent(pathQ10P11); var routingTableP1011 = [[0.8,1.0],[0.8,1.0],[0.8, 1.0]]; var processTimeP1011 = [40.0,40.0,40.0]; var process10 = new ProcessComponent(processTimeP1011, 1, routingTableP1011); process10.defineDataGroup(2.0, 5, 477, 80, globalNeutralColor, globalValueColor, globalLabelColor); process10.setExclusive(true); process10.setRoutingMethod(3); //1 single connection, 2 distribution logic, 3 model logic process10.setComponentName("P10"); process10.setComponentGroup("Secondary"); tempGraphic = new DisplayElement(process10, 190, 326, 64, 36, 0.0, false, false, []); tgBaseY = 29; //53; tempGraphic.addXYLoc(32, tgBaseY); process10.defineGraphic(tempGraphic); pathQ10P10.assignNextComponent(process10); var pathP10X1 = new PathComponent(); pathP10X1.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathP10X1, 0, 0, 0, 0, 0.0, false, false, []); pathP10X1.defineGraphic(tempGraphic); process10.assignNextComponent(pathP10X1); pathP10X1.assignNextComponent(exit1); var process11 = new ProcessComponent(processTimeP1011, 1, routingTableP1011); process11.defineDataGroup(2.0, 5, 477, 80, globalNeutralColor, globalValueColor, globalLabelColor); process11.setExclusive(true); process11.setRoutingMethod(3); //1 single connection, 2 distribution logic, 3 model logic process11.setComponentName("P11"); process11.setComponentGroup("Secondary"); tempGraphic = new DisplayElement(process11, 266, 326, 64, 36, 0.0, false, false, []); tgBaseY = 29; //53; tempGraphic.addXYLoc(32, tgBaseY); process11.defineGraphic(tempGraphic); pathQ10P11.assignNextComponent(process11); var pathP11X1 = new PathComponent(); pathP11X1.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathP11X1, 0, 0, 0, 0, 0.0, false, false, []); pathP11X1.defineGraphic(tempGraphic); process11.assignNextComponent(pathP11X1); pathP11X1.assignNextComponent(exit1); var pathP10X2 = new PathComponent(); pathP10X2.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathP10X2, 0, 0, 0, 0, 0.0, false, false, []); pathP10X2.defineGraphic(tempGraphic); process10.assignNextComponent(pathP10X2); var pathP11X2 = new PathComponent(); pathP11X2.setSpeedTime(20, 1.0); tempGraphic = new DisplayElement(pathP11X2, 0, 0, 0, 0, 0.0, false, false, []); pathP11X2.defineGraphic(tempGraphic); process11.assignNextComponent(pathP11X2); var exit2 = new ExitComponent(); exit2.defineDataGroup(2.0, 230, 576, 80, globalNeutralColor, globalValueColor, globalLabelColor); exit2.setComponentName("Exit2"); tempGraphic = new DisplayElement(exit2, 230, 383, 68, 20, 0.0, false, false, []); exit2.defineGraphic(tempGraphic); pathP10X2.assignNextComponent(exit2); pathP11X2.assignNextComponent(exit2); addToGroupStatsNameListWrapper("System"); function initGraphics3DEntities() { for (var i = 0; i < global3DMaxEntityCount; i++) { define3DEntity(10000, 10000, 5, global3DEntityHeight, 8, globalReadyColor, globalReadyVertexColor); } normalize3DEntities(0); //parameter is starting index } |
I noticed that the arrival schedule and entry distribution arrays are only defined for seven hours (14 x 30 min or 420 min total) while the simulations is allowed to run for ten hours (20 x 30 min or 600 min total). This doesn’t apear to be an issue since all entities are injected into the system within the first seven hours, but I’ll add a To Do item to review it.
Right now we have array parameters with multiple dimensions defined by time (schedule intervals) for the arrival items and for processing time and diversion percentage based on entity type. It’s possible to do both things but it’s only practical to implement if good data can be collected to drive the process. For now we’ll keep things simple and be satisfied that we’ve demonstrated the capability.
Here’s the updated To Do List:
- Review handling of arrival schedule and entry distribution arrays beyond period where they’re defined
Standardize linking and exclusivity processResolve and standardize new vs. advance issueRework drawing of Path components so correct elements are always on top- New property for forward exclusivity as opposed to receiving exclusivity.
Formalize and implement method of receiving from multiple upstream components in turn.Implementing and observing this may illuminate the behaviors that will need to be implemented for the general path solution described in one or more previous posts.Rework the Queue mechanism to flexibly handle finite-traversal time and zero-traversal time configurationsRevisit distribution logic to make sure it’s cycling the way it should be.- Learn JavaScript’s prototype object pattern and re-implement everything in that in place of the closure pattern I’ve been using; I’ll want to bite that bullet before this thing goes much farther
- Add Control, Bag, and Stack components
- Expand function of Process components to handle multiple entities in parallel, in effect making a single component function as if it were multiple, associated ones
- Discrete-event simulation frameworks often include the concept of sets (logical containers that that be iterated and compared for intersection and so on, so that idea should be implemented; this would expand on things were doing now with lists of components and entities; the need for this was inspired by thinking about the bag data structure in general
- Ponder the idea of implementing a combined Queue-Process component
- Expand Path component representation so it can incorporate multiple line segments
- Add ability to sense reaching tail end of FIFO queue based on stopping to wait on a Path component; collect statistics accordingly (possibly add wait flag to entities so they can test against the next entity in line)
- Look into creating a zero-duration, zero-queue decision component
- Create standardized routing mechanism (to components of different types) based on process logic (vs. distribution logic to multiple components of the same type)
- Add a test to verify that valid routes exist to support all required paths that may be taken by different types of entities.
- Add a test to automatically assign downstream distribution mechanisms. See if the need for this isn’t actually obviated at some point.
Implement mechanism to identify combinations of related components into groups (e.g., a group of tollbooths represent a single toll plaza)Gather and report system-,component-,and group-level statistics- Add ability to stream large volumes of output information which can be post-processed and quantified via a parsing mechanism; this is necessary for advanced statistical characterization
Streamline the process of defining the endpoints of Path components (i.e., attach standard nodes to other components and connect to those automatically, which will greatly save on the number of x,y locations the designer must specify manually)- Add an edit mode that allows designers to change component properties interactively (ultimately including being able to drag them)
- Use the new, completely external mechanism for displaying component data
- Describe how abstract representation can be used to represent detailed layouts and interactions; include ability to flag or alarm situations which would cause conflicts in the real world that would not necessarily be captured in a model unless specifically tested for
- Add the ability to graph outputs as part of reporting
- Add scrolling, animated graphs to illustrate progress as simulations run
- Include ability for users to call up component and entity status by written or graphical display interactively while runs are in progress
Create streamlined graphical representations of all component types;create data display for Path componentsAdd ability to display entities inside relevant non-path components- Abstract the current x,y locations of all elements and scale them to the screen so the user can zoom in and out
Employ three.js framework to render models in 3D. Also consider piping this output through the associated VR framework.- Improve how type is displayed for 2D entities
- Improve how status is displayed for 2D entities
- Modify 3D entities to reflect entity type as well as status
- Add ability for users to interactively change things during runs
- Add Monte Carlo mechanisms to various timing and routing events (beyond what’s already been demonstrated)
- Allow designer to build Monte Carlo and other distributions from acquired data using standardized tools
- Incorporate Monte Carlo dithering or explicit curve shape for distributions
- Add ability to perform multiple runs and statistically quantify generated outputs
Make simulation display update at regular intervals of simulated time rather than intervals defined by individual events; also make this “speed” scalable- Include ability to add arbitrary graphic elements to models (labels, keys, tables, etc.)
- Include ability to display an underlay “below” the model display (e.g., a floor plan of a modeled process)
- Allow user to turn off display and run model in “fire-and-forget” mode where it generates results without wasting time redrawing graphics.
- Allow user to selectively turn different display elements on and off
- Create suite of test configurations to exercise every combination of connections and support regression testing.
- Add ability to assign open/close schedules for components and groups
Add ability to introduce multiple types of entities in model with different processing rules for routing and timingAdd ability to combine multiple queues into a single, logical unit- Add ability to adapt standard base components to represent varied and specialized things (this applies mostly to Process components)
- Add ability to save and restore model definitions (in files/XML and in databases, requires PHP/MySql, Node.js or other back end capability)
- Add ability to represent more abstract processes:
- Reintroduce wait..until mechanism that uses the current events queue
- Include pools of resources that are needed by different processes
- Implement non-FIFO queues or collections that receive and forward entities based on arbitrary (user-defined) criteria
- Include ability to accept events that happen according to fixed schedules rather than random ones (e.g., to match observed data)
- Include the ability to change representation of entities and components to represent state changes (by
color, shape, labels, flags, etc.) - Support input and editing of modular packages of information used to define and drive models
- Add ability to represent BPM processes using standard BPMN notation
- Really complex stuff
- Develop more complex, arbitrary node-and-link representation of model, which brings up worlds of complications on its own!
- Polish related sections of code and break them into modules which can be included on a modular basis
- Make modules and examples distributable for use by a wider community
- Make entities be active rather than passive, retain some intelligence in the components
- Write documentation for modules as needed
- Share on GitHub
- Create dedicated project page on my website
- Update and enhance my custom Graph component as well as the simulation framework
- Re-implement this system in a more appropriate language like C++ or at least Java