Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Container.cs @ 17180

Last change on this file since 17180 was 17180, checked in by swagner, 5 years ago

#2875: Removed years in copyrights

File size: 5.6 KB
Line 
1#region License Information
2/* SimSharp - A .NET port of SimPy, discrete event simulation framework
3Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 3 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
17#endregion
18
19using System;
20using System.Collections.Generic;
21
22namespace SimSharp {
23  /// <summary>
24  /// A container holds a variable amount of a single continuous entity, e.g. water, coal, grain, etc.
25  ///
26  /// Put and Get are in FIFO order only when they can be satisfied.
27  /// Any put or get that can be satisfied takes precedence.
28  /// Put events that attempt to add more to the Container than there is capacity for and
29  /// Get events that remove more than there is are backlogged.
30  /// </summary>
31  public class Container {
32
33    public double Capacity { get; protected set; }
34
35    public double Level { get; protected set; }
36
37    protected Simulation Environment { get; private set; }
38
39    protected Queue<ContainerPut> PutQueue { get; private set; }
40    protected Queue<ContainerGet> GetQueue { get; private set; }
41    protected SimplePriorityQueue<Event, double> WhenAtLeastQueue { get; private set; }
42    protected SimplePriorityQueue<Event, double> WhenAtMostQueue { get; private set; }
43    protected List<Event> WhenChangeQueue { get; private set; }
44
45    public Container(Simulation environment, double capacity = double.MaxValue, double initial = 0) {
46      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
47      if (initial < 0) throw new ArgumentException("Initial must be >= 0", "initial");
48      if (initial > capacity) throw new ArgumentException("Initial must be <= capacity", "initial");
49      Environment = environment;
50      Capacity = capacity;
51      Level = initial;
52      PutQueue = new Queue<ContainerPut>();
53      GetQueue = new Queue<ContainerGet>();
54      WhenAtLeastQueue = new SimplePriorityQueue<Event, double>();
55      WhenAtMostQueue = new SimplePriorityQueue<Event, double>(new ReverseComparer<double>());
56      WhenChangeQueue = new List<Event>();
57    }
58
59    public virtual ContainerPut Put(double amount) {
60      if (amount > Capacity) throw new ArgumentException("Cannot put more than capacity", "amount");
61      var put = new ContainerPut(Environment, TriggerGet, amount);
62      PutQueue.Enqueue(put);
63      TriggerPut();
64      return put;
65    }
66
67    public virtual ContainerGet Get(double amount) {
68      if (amount > Capacity) throw new ArgumentException("Cannot get more than capacity", "amount");
69      var get = new ContainerGet(Environment, TriggerPut, amount);
70      GetQueue.Enqueue(get);
71      TriggerGet();
72      return get;
73    }
74
75    public virtual Event WhenAtLeast(double level) {
76      var whenAtLeast = new Event(Environment);
77      WhenAtLeastQueue.Enqueue(whenAtLeast, level);
78      TriggerWhenAtLeast();
79      return whenAtLeast;
80    }
81
82    public virtual Event WhenFull() {
83      return WhenAtLeast(Capacity);
84    }
85
86    public virtual Event WhenAtMost(double level) {
87      var whenAtMost = new Event(Environment);
88      WhenAtMostQueue.Enqueue(whenAtMost, level);
89      TriggerWhenAtMost();
90      return whenAtMost;
91    }
92
93    public virtual Event WhenEmpty() {
94      return WhenAtMost(0);
95    }
96
97    public virtual Event WhenChange() {
98      var whenChange = new Event(Environment);
99      WhenChangeQueue.Add(whenChange);
100      return whenChange;
101    }
102
103    protected virtual void DoPut(ContainerPut put) {
104      if (Capacity - Level >= put.Amount) {
105        Level += put.Amount;
106        put.Succeed();
107      }
108    }
109
110    protected virtual void DoGet(ContainerGet get) {
111      if (Level >= get.Amount) {
112        Level -= get.Amount;
113        get.Succeed();
114      }
115    }
116
117    protected virtual void TriggerPut(Event @event = null) {
118      while (PutQueue.Count > 0) {
119        var put = PutQueue.Peek();
120        DoPut(put);
121        if (put.IsTriggered) {
122          PutQueue.Dequeue();
123          TriggerWhenAtLeast();
124          TriggerWhenChange();
125        } else break;
126      }
127    }
128
129    protected virtual void TriggerGet(Event @event = null) {
130      while (GetQueue.Count > 0) {
131        var get = GetQueue.Peek();
132        DoGet(get);
133        if (get.IsTriggered) {
134          GetQueue.Dequeue();
135          TriggerWhenAtMost();
136          TriggerWhenChange();
137        } else break;
138      }
139    }
140
141    protected virtual void TriggerWhenAtLeast() {
142      while (WhenAtLeastQueue.Count > 0 && Level >= WhenAtLeastQueue.Peek) {
143        var whenAtLeast = WhenAtLeastQueue.Dequeue();
144        whenAtLeast.Succeed();
145      }
146    }
147
148    protected virtual void TriggerWhenAtMost() {
149      while (WhenAtMostQueue.Count > 0 && Level <= WhenAtMostQueue.Peek) {
150        var whenAtMost = WhenAtMostQueue.Dequeue();
151        whenAtMost.Succeed();
152      }
153    }
154
155    protected virtual void TriggerWhenChange() {
156      if (WhenChangeQueue.Count == 0) return;
157      foreach (var evt in WhenChangeQueue)
158        evt.Succeed();
159      WhenChangeQueue.Clear();
160    }
161  }
162}
Note: See TracBrowser for help on using the repository browser.