using System; using System.Collections.Generic; using System.Text; using System.Drawing; using System.Windows.Forms; namespace Simulation { /// /// Actual simulation models subclass SimulationModel. /// Construct GUI for simulation model with eventList, serverNodes and queueNodes. /// A Queue exists for each queueNode and for the eventList. /// Activity() defines behavior of "end of scheduled service". /// In SimDemo Activity() used random to modify display. /// Shows how to update display. /// class SimDemo : SimulationModel { /// number of timer events generated for demo onlt private int TimerCount = 0; /// total number of timer events to demo private int TimerTrials = 100; /// /// Construct model elements: serverNodes, queueNodes, Queues. /// Connect the GUI simNodes with simConnectors. /// public SimDemo () { queue = new Queue[6]; eventList = new Queue(); serverNode = new SimNode[6]; // array of servers in the model queueNode = new SimNode[6]; // array of queues in the model // create queue array to hold entity values for display for (int i = 0; i < 6; i++) { queue[i] = new Queue(); for (int j = 0; j < random.Next(3); j++) queue[i].Enqueue(new Entity(j)); } // List of SimNodes to visually display info for servers and queues nodes = new List(); nodes.Add(eventListNode = new SimNode(" EventList", new Point(50, 25), true, this)); nodes.Add(serverNode[0] = new SimNode(" Loader", new Point(50, 350), leftToRight, this)); nodes.Add(queueNode[0] = new SimNode(" Build Q", new Point(160, 350), leftToRight, this)); nodes.Add(serverNode[1] = new SimNode(" Builder", new Point(310, 350), leftToRight, this)); nodes.Add(queueNode[1] = new SimNode(" Test Q", new Point(410, 350), leftToRight, this)); nodes.Add(serverNode[2] = new SimNode(" Tester", new Point(560, 350), leftToRight, this)); nodes.Add(queueNode[2] = new SimNode(" Fix Q", new Point(310, 150), rightToLeft, this)); nodes.Add(serverNode[3] = new SimNode(" Fixer", new Point(310, 250), leftToRight, this)); nodes.Add(queueNode[3] = new SimNode(" Fixed Q", new Point(410, 250), leftToRight, this)); nodes.Add(queueNode[4] = new SimNode(" Recycle Q", new Point(700, 350), leftToRight, this)); nodes.Add(serverNode[4] = new SimNode(" Recycler", new Point(850, 350), leftToRight, this)); nodes.Add(queueNode[5] = new SimNode(" Ship Q", new Point(700, 450), leftToRight, this)); nodes.Add(serverNode[5] = new SimNode(" Shipper", new Point(850, 450), leftToRight, this)); eventListNode.DisplayLabel1 = "Event Notices:"; for (int i = 0; i < 6; i++) queueNode[i].DisplayLabel1 = "Entities:"; foreach (SimNode snm in nodes) snm.Parent = this; // make nodes visible in Form // List of connectors to show entity flow through the simulation connectors = new List(); connectors.Add(new SimConnector(serverNode[0], queueNode[0], leftToRight)); connectors.Add(new SimConnector(queueNode[0], serverNode[1], leftToRight)); connectors.Add(new SimConnector(serverNode[1], queueNode[1], leftToRight)); connectors.Add(new SimConnector(queueNode[1], serverNode[2], leftToRight)); connectors.Add(new SimConnector(serverNode[2], queueNode[2], rightToLeft)); connectors.Add(new SimConnector(serverNode[2], queueNode[4], leftToRight)); connectors.Add(new SimConnector(serverNode[2], queueNode[5], leftToRight)); connectors.Add(new SimConnector(queueNode[2], serverNode[3], rightToLeft)); connectors.Add(new SimConnector(serverNode[3], queueNode[3], leftToRight)); connectors.Add(new SimConnector(queueNode[3], serverNode[2], leftToRight)); connectors.Add(new SimConnector(queueNode[4], serverNode[4], leftToRight)); connectors.Add(new SimConnector(queueNode[5], serverNode[5], leftToRight)); } /// /// Run the demo to show state changes for servers, queues, and eventList /// /// The object sending the timer tick /// Event Arguments of the timer event protected override void Simulate(object obj, EventArgs ea) { SimNode n; int i; if (++ TimerCount > TimerTrials) { TimerCount = 0; timer.Stop(); } // now should be set to the scheduled time of the current activity. now = TimerCount; // randomly determine what activity to demo switch (random.Next(3)) { case 0 : // simulate server action i = random.Next(6); // select server 0 to 5 n = serverNode[i]; // get server state i = random.Next(3); n.NodeState = (SimNode.state) (i); if ( i == (int) state.IDLE ) { n.DisplayLabel1 = ""; n.DisplayLabel2 = ""; } else { n.DisplayLabel1 = "entity " + TimerCount.ToString(); // display entity id n.DisplayLabel2 = "time " + random.Next(50).ToString(); } // display time to end service break; case 1 : // simulate a queue action i = random.Next(6); // select queueNode 0 to 5 n = queueNode[i]; // select simNode queue // enqueue or dequeue queue? if (random.Next(2) == 0) if (queue[i].Count < 3) { queue[i].Enqueue(new Entity(TimerCount)); n.NodeState = (SimNode.state) state.BUSY; } else n.NodeState = (SimNode.state) state.BLOCKED; else // dequeue if (queue[i].Count > 0) { queue[i].Dequeue(); if (queue[i].Count == 0) // is queue now empty n.NodeState = (SimNode.state) state.IDLE; else // queue is still busy n.NodeState = (SimNode.state) state.BUSY; } else // queue is empty n.NodeState = (SimNode.state) state.IDLE; n.DisplayLabel2 = ""; // display entities that are in the queue foreach (Entity entity in queue[i]) n.DisplayLabel2 = n.DisplayLabel2 + " " + entity.ToString(); break; case 2 : // simulate EventList changes // enqueue or dequeue queue? if (random.Next(2) == 0) eventList.Enqueue(new Entity(random.Next(10))); else if (eventList.Count > 0) eventList.Dequeue(); eventListNode.DisplayLabel2 = ""; foreach (Entity entity in eventList) eventListNode.DisplayLabel2 = eventListNode.DisplayLabel2 + String.Format("{0} @ {1:f0} ", serverNode[random.Next(6)].Text, // a random server's name. now + random.Next(5)); // display time to end service break; } Invalidate(); // redraw the dislay statusBar.Text = "Now = " + now; } /// /// The main entry point for the application. /// [STAThread] static void Main() { // start the application. Application.Run(new SimDemo()); } } }