3 using System.Collections.Generic;
17 private Random random;
28 private int validToken = 0;
35 private object eventsLock =
new object();
40 private DateTime dateTimeOfLastAction;
45 private TimeSpan currentModelTime;
49 public TimeSpan CurrentModelTime {
get {
return currentModelTime; } }
54 private TimeSpan modelTimeToPause = TimeSpan.MaxValue;
58 public TimeSpan ModelTimeToPause
60 get {
return modelTimeToPause; }
61 set { modelTimeToPause = value; }
101 private int usedSeed;
105 public int UsedSeed {
get {
return usedSeed; } }
110 private const double MinimumSimulationSpeed = 0.001;
114 private const double MaximumSimulationSpeed = 10000.0;
118 private double simulationSpeed = 1.0;
122 public double SimulationSpeed
124 get {
return simulationSpeed; }
127 if (value < MinimumSimulationSpeed || value > MaximumSimulationSpeed)
131 double oldSimulationSpeed = simulationSpeed;
138 simulationSpeed = value;
141 StartOrResumeTimer();
144 if (oldSimulationSpeed != simulationSpeed)
145 OnSimulationSpeedChange(oldSimulationSpeed, simulationSpeed);
152 private bool isMaxSimulationSpeed;
156 public bool IsMaxSimulationSpeed
158 get {
return isMaxSimulationSpeed; }
161 if (isMaxSimulationSpeed != value)
163 isMaxSimulationSpeed = value;
164 if (isMaxSimulationSpeed)
176 StartOrResumeTimer();
180 OnIsMaxSimulationSpeedChange();
188 private bool IsModelTimeToPauseReached
192 if (simulationActions.Count == 0)
195 return simulationActions.Top.Key.Time >= modelTimeToPause;
208 private List<ISimulationEventsGenerator> simulationActionGenerators =
209 new List<ISimulationEventsGenerator>();
216 internal Simulation(List<ISimulationEventsGenerator> simulationEventGenerators)
218 this.simulationActionGenerators = simulationEventGenerators;
225 private void PushNewActionToCalendarForCurrentActionGenerator(
229 if (timeToNextAction != TimeSpan.MaxValue)
231 simulationActions.Push(
new SimulationEventGeneratorKey(currentModelTime + timeToNextAction,
232 simulationEventsGenerator.
Priority), simulationEventsGenerator);
242 private void InitializeSimulationRun(
int? seed)
244 Debug.Assert(simulationActions.Count == 0);
245 Debug.Assert(currentModelTime == TimeSpan.Zero);
248 PushNewActionToCalendarForCurrentActionGenerator(i);
250 usedSeed = (int)(DateTime.Now.Ticks & 0x0000FFFF);
252 usedSeed = seed.Value;
253 random =
new Random(usedSeed);
260 internal void Run(
int? seed = null)
266 InitializeSimulationRun(seed);
269 ResetModelTimeToPauseIfReached();
270 StartOrResumeTimer();
278 internal void StepForward(
int? seed = null)
284 InitializeSimulationRun(seed);
287 ResetModelTimeToPauseIfReached();
294 internal void Pause()
302 "Possible simultaneous call of Pause command and scheduled pause or bug in code.");
320 "Possible simultaneous call of Stop command and scheduled pause or bug in code.");
325 simulationActions.Clear();
326 ResetModelTimeToPause();
335 private void StartOrResumeTimer()
337 TimeSpan timeToBeSetInTimer = TimeSpan.Zero;
338 if (!isMaxSimulationSpeed && simulationActions.Count > 0)
340 dateTimeOfLastAction = DateTime.Now;
341 timeToBeSetInTimer = (simulationActions.Top.Key.Time - currentModelTime).Divide(simulationSpeed);
342 if (timeToBeSetInTimer < TimeSpan.Zero)
343 timeToBeSetInTimer = TimeSpan.Zero;
345 timer =
new Timer(Tick, validToken, timeToBeSetInTimer, Timeout.InfiniteTimeSpan);
355 if (simulationActions.Count == 0)
357 var currentEvent = simulationActions.Pop();
358 currentModelTime = currentEvent.Key.Time;
359 PushNewActionToCalendarForCurrentActionGenerator(currentEvent.Value);
360 return currentEvent.Value;
366 private void RunStep()
372 var currentActionGenerator = GetGeneratorToPerformAnActionAndStoreNewOne();
373 if (currentActionGenerator == null)
375 currentActionGenerator.PerformAction(random);
376 currentModelTime = simulationActions.Top.Key.Time;
377 OnModelTimeChanged();
378 OnSingleSimulationActionPerformed();
389 private void Tick(
object state)
393 if ((
int)state != validToken || simulationActions.Count == 0)
397 if (IsModelTimeToPauseReached || simulationActions.Top.Value.IsPauseScheduled)
400 OnSimulationPaused();
403 var currentActionGenerator = GetGeneratorToPerformAnActionAndStoreNewOne();
404 StartOrResumeTimer();
405 OnModelTimeChanged();
406 currentActionGenerator.PerformAction(random);
414 private void ResetModelTimeToPauseIfReached()
416 if (IsModelTimeToPauseReached)
418 ResetModelTimeToPause();
425 private void ResetModelTimeToPause()
427 modelTimeToPause = TimeSpan.MaxValue;
433 private void UpdateTimes()
435 if ((isMaxSimulationSpeed || IsModelTimeToPauseReached) && simulationActions.Count > 0)
436 currentModelTime = simulationActions.Top.Key.Time;
438 currentModelTime += (DateTime.Now - dateTimeOfLastAction).Multiply(simulationSpeed);
444 private void PauseTimer()
447 OnModelTimeChanged();
454 private void StopTimer()
456 currentModelTime = TimeSpan.Zero;
457 OnModelTimeChanged();
464 private void OnModelTimeChanged()
466 if (ModelTimeChanged != null)
467 ModelTimeChanged(
this, EventArgs.Empty);
474 private void OnSimulationPaused()
476 if (SimulationPaused != null)
477 SimulationPaused(
this, EventArgs.Empty);
483 private void OnSingleSimulationActionPerformed()
485 if (SingleSimulationActionPerformed != null)
486 SingleSimulationActionPerformed(
this, EventArgs.Empty);
494 private void OnSimulationSpeedChange(
double oldSimulationSpeed,
double newSimulationSpeed)
496 if (SimulationSpeedChanged != null)
500 OldSimulationSpeed = oldSimulationSpeed,
501 NewSimulationSpeed = newSimulationSpeed
509 private void OnIsMaxSimulationSpeedChange()
511 if (IsMaxSimulationSpeedChange != null)
512 IsMaxSimulationSpeedChange(
this, EventArgs.Empty);
519 protected virtual void Dispose(
bool disposing)
537 GC.SuppressFinalize(
this);
EventHandler ModelTimeChanged
An event informing about changing of model time.
EventHandler< SimulationSpeedChangeEventArgs > SimulationSpeedChanged
Event of simulation speed change.
TimeSpan GetTimeToNextAction(Random random)
Method for getting time to next action from the implementing class
EventHandler IsMaxSimulationSpeedChange
Event of activation or deactivation of maximum simulation speed.
SimulationState
Current state of the simulation.
EventHandler SimulationPaused
An event informing about applying of pause by the simulation control.
int Priority
Priority determining the rank of the events which have the same time.
Event args containing old and new simulation speed.
Heap data structure where values of items are ordered by their keys.
void Dispose()
Disposes cellular topology resources.
EventHandler SingleSimulationActionPerformed
An event informing about finishing of simulation action.
Class controlling performing simulation actions by simulation calendar.
Every class which performs some repeating action should implement this interface
virtual void Dispose(bool disposing)
Dispose disposable fields.