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());
}
}
}