Form1.Gauge1.Progress: = 100; p>
// RedrawDiagram; p>
finally p>
FreeEmulation; p>
end; p>
end; p>
function TQSheme.NewParcel: Pointer; p>
var P: Pointer; p>
begin p>
P: = FParcelsClass.Create; p>
FParcels.Add (P); p>
Result: = P; p>
end; p>
procedure TQSheme.NewEvent (AEvent: Integer; ASender, ASource: TObject; AInfo: TInfo); p>
var P: PEventRec; p>
begin p>
GetMem (P, SizeOf (TEventRec )); p>
with P ^ do begin p>
Event: = AEvent; p>
Sender: = ASender; p>
Source: = ASource; p>
Info: = AInfo; p>
SysTime: = FSysTime; p>
end; p>
FEventQueue.Add (P); p>
end; p>
function TQSheme.GetCounts (Index: integer): integer; p>
var i: integer; p>
begin p>
Result: = 0; p>
for i: = 0 to FParcels.Count-1 do p>
if Ord (TParcel (FParcels [i]). State) = Index then Inc (Result); p>
end; p>
function TQSheme.GetParcelCount: integer; p>
begin p>
Result: = FParcels.Count; p>
end; p>
const// DrawConstants p>
Top = 20; p>
Left = 20; p>
Interval = 20; p>
procedure TQSheme.DrawElementLines; p>
var i: integer; p>
Y: integer; p>
begin p>
for i: = 0 to ElementCount-1 do begin p>
Y: = Top + interval * i; p>
with Diagram.Canvas do begin p>
TextOut (0, Y + Font.Height, Elements [i]. Name); p>
MoveTo (0, Y); p>
LineTo (Diagram.ClientWidth, Y) p>
end; p>
end; p>
end; p>
procedure TQSheme.DisplayEvents; p>
(var i: integer; p>
s: string;) p>
begin p>
(Form1.mResults.Items.Clear; p>
for i: = 0 to FEventQueue.Count - 1 do begin p>
with TEventRec (FEventQueue [i] ^) do begin p>
case Event of p>
EV_TAKE: S: ='+++:'; p>
EV_REFUSE: S: ='------:'; p>
EV_PASS: S: = 'PASS :'; p>
end; p>
S: = S + IntToStr (Info); p>
S: = S + '[' + IntToStr (SysTime) + ']'; p>
if Assigned (Source) then S: = S + TElement (Source). Name p>
else S: = S + 'nil'; p>
S: = S +'->'; p>
if Assigned (Sender) then S: = S + TElement (Sender). Name p>
else S: = S + 'nil'; p>
end; p>
Form1.mResults.Items.Add (S); p>
end;) p>
end; p>
procedure TQSheme.RedrawDiagram; p>
// var i: integer; p>
begin p>
// Diagram.Canvas.FillRect (Rect (0,0, Diagram.Width, Diagram.Height )); p>
// DrawElementLines; p>
DisplayEvents; p>
end; p>
initialization p>
Randomize; p>
end. p>
unit QSObjs; p>
interface p>
uses Classes, QSTypes, SysUtils, Utils; p>
type p>
TElement = class; p>
TIsRightElement = function (Element: TElement): Boolean of object;// far; p>
TBeforeAfterAction = procedure (Sender: TElement) of object; p>
TElement class = p>
private p>
FId: integer; p>
FName: string; p>
FSources: TList; p>
FSheme: TObject; p>
FContainer: TParcel; p>
FOnSourceValidate: TIsRightElement; p>
FOnDestinationValidate: TIsRightElement; p>
FBeforeTake: TBeforeAfterAction; p>
FAfterTake: TBeforeAfterAction; p>
FBeforeDrop: TBeforeAfterAction; p>
FAfterDrop: TBeforeAfterAction; p>
procedure SetSheme (ASheme: TObject); p>
function GetSourceCount: integer; p>
function GetSource (Index: integer): TElement; p>
function GetParcelPresent: Boolean; p>
function GetCanDropParcelFor (Destination: TElement): Boolean; p>
function GetCanTakeParcelFrom (Source: TElement): Boolean; p>
procedure Pass (SourceIndex: integer); virtual; p>
protected p>
function GetCanTake: Boolean; virtual; abstract; p>
function GetCanDrop: Boolean; virtual; abstract; p>
public p>
constructor Create; virtual; p>
destructor Destroy; override; p>
procedure AddSource (Element: TElement); p>
procedure DelSource (Element: TElement); p>
procedure AskForParcel; virtual; p>
procedure ClearContainer; virtual; p>
procedure RefuseParcel (SourceIndex: integer); p>
procedure DropParcel; virtual; p>
procedure TakeParcel (SourceIndex: integer); virtual; p>
procedure DoBeforeDrop (Sender: TElement); p>
procedure DoBeforeTake (Sender: TElement); p>
procedure DoAfterDrop (Sender: TElement); p>
procedure DoAfterTake (Sender: TElement); p>
property CanDropParcelFor [Destination: TElement]: Boolean read GetCanDropParcelFor; p>
property CanTakeParcelFrom [Source: TElement]: Boolean read GetCanTakeParcelFrom; p>
property Container: TParcel read FContainer write FContainer; p>
property ParcelPresent: Boolean read GetParcelPresent; p>
property CanTake: Boolean read GetCanTake; p>
property CanDrop: Boolean read GetCanDrop; p>
property Id: integer read FId write FId; p>
published p>
property Name: string read FName write FName; p>
property Sheme: TObject read FSheme write SetSheme; p>
property SourceCount: integer read GetSourceCount; p>
property Sources [Index: integer]: TElement read GetSource; p>
property OnSourceValidate: TIsRightElement read FOnSourceValidate write FOnSourceValidate; p>
property OnDestinationValidate: TIsRightElement read FOnDestinationValidate write FOnDestinationValidate; p>
property BeforeTake: TBeforeAfterAction read FBeforeTake write FBeforeTake; p>
property AfterTake: TBeforeAfterAction read FAfterTake write FAfterTake; p>
property BeforeDrop: TBeforeAfterAction read FBeforeDrop write FBeforeDrop; p>
property AfterDrop: TBeforeAfterAction read FAfterDrop write FAfterDrop; p>
end; p>
TElementClass = class of TElement; p>
TGenerator class = p>
private p>
FMean: TCustTime; p>
FDisp: TCustTime; p>
FRandomType: TRandomType; p>
function GetRandom: TCustTime; p>
public p>
constructor Create; p>
property Mean: TCustTime read FMean write FMean; p>
property Disp: TCustTime read FDisp write FDisp; p>
property RandomType: TRandomType read FRandomType write FRandomType; p>
property Time: TCustTime read GetRandom; p>
end; p>
TShop = class (TElement) p>
private p>
FGenerator: TGenerator; p>
FEndWorkTime: TCustTime; p>
procedure Pass (SourceIndex: integer); override; p>
function GetProcessed: Boolean; p>
protected p>
function GetCanTake: Boolean; override; p>
function GetCanDrop: Boolean; override; p>
property EndWorkTime: TCustTime read FEndWorkTime write FEndWorkTime; p>
public p>
constructor Create; override; p>
destructor Destroy; override; p>
procedure DropParcel; override; p>
property Generator: TGenerator read FGenerator; p>
property Processed: Boolean read GetProcessed; p>
procedure Work; virtual; p>
end; p>
TChannel = class (TShop) p>
public p>
procedure Pass (SourceIndex: integer); override; p>
end; p>
TSource = class (TShop) p>
private p>
procedure TakeParcel (SourceIndex: integer); override; p>
public p>
procedure Pass (SourceIndex: integer); override; p>
procedure AskForParcel; override; p>
end; p>
TAccumulator = class (TElement) p>
private p>
FParcels: TList; p>
FLimited: Boolean; p>
FCapacity: integer; p>
function GetParcel (Index: integer): TParcel; p>
function GetFreeSpacePresent: Boolean; p>
function GetEmpty: Boolean; p>
procedure SetCapacity (Value: integer); p>
function GetCapacity: integer; p>
function GetParcelCount: integer; p>
procedure Pass (SourceIndex: integer); override; p>
function GetCanTake: Boolean; override; p>
function GetCanDrop: Boolean; override; p>
public p>
constructor Create; override; p>
destructor Destroy; override; p>
procedure ClearContainer; override; p>
procedure DropParcel; override; p>
property ParcelCount: integer read GetParcelCount; p>
property Parcels [Index: integer]: TParcel read GetParcel; p>
property FreeSpacePresent: Boolean read GetFreeSpacePresent; p>
property Empty: Boolean read GetEmpty; p>
procedure TakeParcel (Index: integer); override; p>
published p>
property Capacity: integer read GetCapacity write SetCapacity; p>
property Limited: Boolean read FLimited write FLimited; p>
end; p>
TAccumulatorClass = class of TAccumulator; p>
implementation p>
uses QSheme; p>
constructor TElement.Create; p>
begin p>
FSources: = TList.Create; p>
end; p>
destructor TElement.Destroy; p>
begin p>
FSources.Free; p>
inherited; p>
end; p>
procedure TElement.SetSheme (ASheme: TObject); p>
begin p>
if Assigned (ASheme) then FSheme: = ASheme; p>
end; p>
procedure TElement.AddSource (Element: TElement); p>
begin p>
if Assigned (Element) then FSources.Add (Element); p>
end; p>
procedure TElement.DelSource (Element: TELement); p>
begin p>
if Assigned (Element) then FSources.Remove (Element); p>
end; p>
function TElement.GetSourceCount: integer; p>
begin p>
Result: = FSources.Count; p>
end; p>
function TElement.GetSource (Index: integer): TElement; p>
begin p>
Result: = FSources [Index]; p>
end; p>
procedure TElement.TakeParcel (SourceIndex: integer); p>
begin p>
FContainer: = Sources [SourceIndex]. FContainer; p>
TQSheme (Sheme). NewEvent (EV_TAKE, Self, Sources [SourceIndex], FContainer.Info); p>
Sources [SourceIndex]. DropParcel; p>
end; p>
procedure TElement.Pass (SourceIndex: integer); p>
var Source: TElement; p>
begin p>
if SourceIndex <> -1 then Source: = Sources [SourceIndex]; p>
DoBeforeTake (Self); p>
if SourceIndex <> -1 then Source.DoBeforeDrop (Source); p>
TakeParcel (SourceIndex); p>
DoAfterTake (Self); p>
if SourceIndex <> -1 then Source.DoAfterDrop (Source); p>
end; p>
function TElement.GetCanDropParcelFor (Destination: TElement): Boolean; p>
begin p>
Result: = CanDrop; p>
if Assigned (OnDestinationValidate) then p>
Result: = Result and OnDestinationValidate (Destination) p>
end; p>
function TElement.GetCanTakeParcelFrom (Source: TElement): Boolean; p>
begin p>
if Assigned (OnSourceValidate) then p>
Result: = OnSourceValidate (Source) p>
else Result: = True; p>
end; p>
procedure TElement.AskForParcel; p>
var i: integer; p>
Source: TElement; p>
begin p>
for i: = 0 to SourceCount - 1 do begin p>
Source: = Sources [i]; p>
if Source.CanDropParcelFor [Self] and CanTakeParcelFrom [Source] then p>
if CanTake then begin p>
Pass (i); p>
if Self is TShop then Exit; p>
end p>
else p>
if not (Source is TAccumulator) then RefuseParcel (i); p>
end;// for p>
end; p>
function TElement.GetParcelPresent: Boolean; p>
begin p>
Result: = FContainer <> nil; p>
end; p>
procedure TElement.ClearContainer; p>
begin p>
DropParcel; p>
end; p>
procedure TElement.RefuseParcel (SourceIndex: integer); p>
begin p>
Sources [SourceIndex]. Container.State: = psRefused; p>
TQSheme (Sheme). NewEvent (EV_REFUSE, Self, Sources [SourceIndex], Sources [SourceIndex]. Container.Info); p>
Sources [SourceIndex]. DropParcel; p>
end; p>
procedure TElement.DropParcel; p>
begin p>
Container: = nil; p>
end; p>
procedure TElement.DoBeforeDrop (Sender: TElement); p>
begin p>
if Assigned (FBeforeDrop) then FBeforeDrop (Sender); p>
end; p>
procedure TElement.DoAfterDrop (Sender: TElement); p>
begin p>
if Assigned (FAfterDrop) then FAfterDrop (Sender); p>
end; p>
procedure TElement.DoBeforeTake (Sender: TElement); p>
begin p>
if Assigned (FBeforeTake) then FBeforeTake (Sender); p>
end; p>
procedure TElement.DoAfterTake (Sender: TElement); p>
begin p>
if Assigned (FAfterTake) then FAfterTake (Sender); p>
end; p>
constructor TGenerator.Create; p>
begin p>
inherited; p>
FRandomType: = rtPlane; p>
end; p>
function TGenerator.GetRandom: TCustTime; p>
var R: single; p>
begin p>
case FRandomType of p>
rtPlane: R: = PlaneRND; p>
rtNormal: R: = NormRND; p>
rtExponent: R: = ExpRND p>
else p>
R: = Random; p>
end; p>
Result: = FMean - FDisp + Round (R * 2 * FDisp); p>
end; p>
constructor TShop.Create; p>
begin p>
inherited; p>
FGenerator: = TGenerator.Create; p>
end; p>
destructor TShop.Destroy; p>
begin p>
FGenerator.Free; p>
inherited; p>
end; p>
procedure TShop.DropParcel; p>
begin p>
inherited; p>
FEndWorkTime: = 0; p>
end; p>
procedure TShop.Pass (SourceIndex: integer); p>
begin p>
inherited; p>
Work; p>
end; p>
function TShop.GetProcessed: Boolean; p>
begin p>
Result: = (TQSheme (Sheme). SysTime> = FEndWorkTime); p>
end; p>
function TShop.GetCanTake: Boolean; p>
begin p>
Result: = not ParcelPresent and Processed; p>
end; p>
function TShop.GetCanDrop: Boolean; p>
begin p>
Result: = ParcelPresent and Processed; p>
end; p>
procedure TShop.Work; p>
begin p>
FEndWorkTime: = TQSheme (Sheme). SysTime + FGenerator.GetRandom; p>
end; p>
procedure TChannel.Pass (SourceIndex: integer); p>
begin p>
inherited; p>
Container.State: = psWork; p>
end; p>
procedure TSource.TakeParcel (SourceIndex: integer); p>
begin p>
Container: = TQSheme (Sheme). NewParcel; p>
end; p>
procedure TSource.Pass (SourceIndex: integer); p>
begin p>
inherited; p>
Container.State: = psBorn; p>
end; p>
procedure TSource.AskForParcel; p>
begin p>
if CanTake then Pass (-1); p>
end; p>
constructor TAccumulator.Create; p>
begin p>
FLimited: = False; p>
FParcels: = TList.Create; p>
inherited; p>
end; p>
destructor TAccumulator.Destroy; p>
begin p>
FParcels.Free; p>
end; p>
function TAccumulator.GetParcel (Index: integer): TParcel; p>
begin p>
Result: = FParcels [Index]; p>
end; p>
function TAccumulator.GetCanDrop: Boolean; p>
begin p>
if Empty then AskForParcel; p>
if not Empty then Container: = FParcels.First; p>
Result: = not Empty; p>
end; p>
function TAccumulator.GetCanTake: Boolean; p>
begin p>
Result: = FreeSpacePresent; p>
end; p>
function TAccumulator.GetFreeSpacePresent: Boolean; p>
begin p>
Result: = (Capacity <> FParcels.Count) or (not Limited); p>
end; p>
function TAccumulator.GetEmpty: Boolean; p>
begin p>
Result: = FParcels.Count = 0; p>
// if not Result then Container: = FParcels.First; p>
end; p>
procedure TAccumulator.DropParcel; p>
begin p>
if not Empty then FParcels.Delete (0); p>
inherited; p>
end; p>
function TAccumulator.GetCapacity: integer; p>
begin p>
Result: = FCapacity; p>
end; p>
function TAccumulator.GetParcelCount: integer; p>
begin p>
Result: = FParcels.Count; p>
end; p>
procedure TAccumulator.SetCapacity (Value: integer); p>
begin p>
FLimited: = True; p>
FCapacity: = Value; p>
end; p>
procedure TAccumulator.ClearContainer; p>
begin p>
FParcels.Clear; p>
inherited; p>
end; p>
procedure TAccumulator.Pass (SourceIndex: integer); p>
begin p>
inherited; p>
Container.State: = psStore; p>
end; p>
procedure TAccumulator.TakeParcel (Index: integer); p>
begin p>
FParcels.Add (Sources [Index]. Container); p>
TQSheme (Sheme). NewEvent (EV_TAKE, Self, Sources [Index], Sources [Index]. Container.Info); p>
Container: = FParcels.Last; p>
Sources [Index]. DropParcel; p>
end; p>
end. p>