#include "sim.hpp"
#include ...
#define nmbrOfPhysicians	4
#define openingHours		480.0
#define openPeriod		480.0
#define consultationLow		5.0
#define consultationHigh	20.0
#define arrivalsExpected	0.25

float treatmentPeriod(void)
{	return(fUniform(consultationLow,consultationHigh)); }

float periodBeforeNextArrival(void)
{	return(fNegexp(arrivalsExpected)); }

class clinic : public process
{public:chain lunchRoom,waitingRoom;
	float closingTime,totalWaitingTime;
	int totalNmbrOfPatients;
	clinic(int nrOfPhysicians,float Period);
	void main(void);
};

class physician : public process
{	clinic* theClinic;
public: physician(clinic* cl)	{theClinic=cl;}
	void main(void);
};

class patient : public process
{	clinic *theClinic;
public:	float startWaitingAt,startTreatmentAt,
	finishedAt;
	patient(clinic* cl)	{theClinic=cl;}
	void main(void);
};

clinic::clinic(int nrOfPhysicians, float Period)
{	int i;
	totalWaitingTime=0.0;
	totalNmbrOfPatients=0;
	closingTime=currentTime() + Period;
	for (i=0;i<nrOfPhysicians;i++)
	  activate(new physician(this),currentTime());
}

void clinic::main(void)
{	patient* ptnt;
	physician* phsn;
	hold(periodBeforeNextArrival());
	while (currentTime() < closingTime)
	{   ptnt=new patient(this);
	    totalNmbrOfPatients++;
	    waitingRoom.append(ptnt);
	    activate(ptnt,currentTime());
	    if (!lunchRoom.empty())
		{   phsn=(physician*)lunchRoom.
			getfirst();
		    activate(phsn,currentTime());
		}
	    hold(periodBeforeNextArrival());
	}
}

void physician::main(void)
{	patient *ptnt;
	while(1)
	{   if (theClinic->waitingRoom.empty())
	    {  	theClinic->lunchRoom.append(this);
		passivate();
	    }
	    else
	    {	ptnt=(patient*)theClinic->waitingRoom.
	            getfirst();
		activate(ptnt,currentTime());
		hold(treatmentPeriod());
		activate(ptnt,currentTime());
	    }
	}
}

void patient::main(void)
{
	startWaitingAt=currentTime();
	passivate();
	startTreatmentAt=currentTime();
	passivate();
	finishedAt=currentTime();
	theClinic->totalWaitingTime+=
	    (startTreatmentAt-startWaitingAt);
}

void main(void)
{	clinic *clnc;
	initRandom();
	initProcesses();
	hold(openingHours - currentTime());
	activate(clnc=new clinic(
	    nmbrOfPhysicians,openPeriod),
	    currentTime());
	hold(10000.0);
	cout << "Total number of patients = "
	     << clnc->totalNmbrOfPatients << endl;
	cout << "Average waiting time     = "
	     << clnc->totalWaitingTime/
	            clnc->totalNmbrOfPatients << endl;
}

