program ManuelsShop ;
{ A single queue, single or multiple server queueing model }
{ the PROCESS-oriented version  using the process manager toolbox ! }
{ one customer STARTs, each starts the next.  uses a SEMAPHORE for queuing}

{Adapted from 
          Wolfgang Kreutzer,
          System Simulation, programming styles and Languages, 1986,
          ISBN 0-201-12914-0, p 245 ff.}
{the OOP version for turbo Pascal 6.0 and up,
 Adapted by Lin Jensen, October 1996.
 New Features: All objects are implemented as objects.
               Global Reset and Report implemented in SIMOBJ.
 }

USES clock, queue,simobj, mcobj, statobj, qnetobj, coproc, proc_man, usebios;

  const
    NoDelay               =        0.0;
    AlongNumber           =     MAXINT;
    PreSimulationSamples  =        500;
    ExperimentSamples     =       1000;

 type
   PosIntType  = WORD;              {UNsigned numbers}
   custptr = ^ customer;
   customer  = object (procdescr)
      procedure lifecycle;  virtual;
   end;

var
   numberServers : integer;        {vary the number of clerks in shop}

{          Declared and initialized in units:
   TheClock   -- in CLock
   TheMonitor -- in Proc_man  
   Reporter         : ReportList;   -- in SIMOBJ
 }

  Arrivals, Service : RandomNegExp;
                                   {source and sink are really counters!}
  Source         : Counter;
  Sink           : Counter;
{ Q              : aQueueType;  -- replaced by semaphore }
{               this type had statistics which are similar to a MEASURE }
  Q              : SEMQUEUE;          { processes wait for service here }
  Manuel         : aServerType;       { gathers utilization statistics  }
  FlowTime       : Histogram;         { bar graph of time spent in shop }

{-------------  CUSTOMER LIFE CYCLE -----------------------------}

procedure customer.lifecycle;
var
    birthTime : REAL;
    romeo : custptr;
{creates incoming customers and puts them in a queue in front of Manuel}
  begin
     {random   arrival}
     SLEEP_FOR ( Arrivals.NegExp );
     birthTime := theClock.TellTime;    {record time of entry into shop}
    { create next customer}
     NEW (romeo, Init('ROMEO',GetNumber+1));
     resume(romeo);
     Source.Update;
     {put him into the Q and schedule a start event}
     Q.WAIT;
          Manuel.SeizeServer (1);
          { turn attention to waiting customer}
          {diagnose degree of lovesickness, mix, and hand over remedy;
          accept donation }
          SLEEP_FOR ( Service.NegExp );        {time required for service}
          Manuel.ReleaseServer  (1);
     Q.SIGNAL;
    FlowTime.Update (TheClock.TellTime - BirthTime);  {time in shop}
    Sink.Update ;
    Monitor.RecordSample;
   { TERMINATE;}              {This Customer dissappears}
  end; { of Customer Life Cycle -------------------------------------------}



procedure ReadAndInitialize;
{ initiates the model's entities  ! }
var
  romeo : custptr;
  begin
    ClrScr;
    prompt ('Manuel''s shop. How many servers? '); readln (numberServers);
    Arrivals.Init               (12345, 0.8*numberServers);
    Service.Init                (67891, 1.0 );
    Source.Init;
    Source.SpecificLabel ('Source Creation');
    Sink.Init;
    Sink.SpecificLabel ('Sink Departure');
    Q.Init                      (numberServers);    {how many at a time!}
    Manuel.Init                 (numberServers);
    Manuel.SpecificLabel   ('Manuel''s performance');
    FlowTime.Init          ( 0, 25, 10 );
    FlowTime.SpecificLabel ('Customers'' Time in Shop');
{   ScheduleEvent   -- first hello  }
         {ready first customer}
     NEW (romeo, Init('ROMEO', 0));
     resume(romeo);
 end;

{Procedure RunModelForSamples -- replaced by RUNSIMULATION }

begin { * * * * * Body of MAIN program * * * * * }
  ReadAndInitialize;
  Monitor.RunSIMULATION (aLongNumber, PreSimulationSamples);
    Monitor.Report;          {see processes at reset}
          WaitKeyPress;
    Reporter.ResetALL;
  Monitor.RunSIMULATION (aLongNumber, ExperimentSamples);
          WaitKeyPress;
    Reporter.ReportALL;
          WaitKeyPress;
end.
