PROGRAM ServerSim;
{Programmer:	Gregory A. Perkins
				CS 65
	Due:		20 November 1996}
	
{This program simulates an internet server processing outgoing messages
and reports the maximum wait time for messages to be processed}

USES cs65;  {contains the random functions and IntToStr functions}


{Declaration module}
CONST Num = 5600;  {number of elements in array - used mainly for testing phase}
TYPE WaitArray = ARRAY[1..Num] OF REAL;  {Holds value of max wait time for each rate}
	 
CONST NumRot = 50;  {number of run times per rate}
CONST Inc = 1;  {increment value of rate}
VAR WaitY : WaitArray;
VAR MessFile, MessMax : LONGINT;
VAR Tick, Packet, Rate, Rotation, Count : INTEGER;
VAR Wait, WaitSum, WaitAve : REAL;
VAR PlotX, PlotY : INTEGER;
VAR WaitDisplay, TempStr : STRING;

{Subprogram module}
FUNCTION Message(R : INTEGER) : INTEGER;
VAR Event : REAL;
BEGIN
	Message := 0;
	Event := Random;
	IF (Event <= (R / 111111.111111)) THEN
			Message := 50 * (RandomInt(39) + 1)  {average of 1000 characters/message}
	ELSE
			Message := 0;
END;

PROCEDURE Server(VAR PSize : INTEGER; VAR MSize : LONGINT);
BEGIN
	IF PSize = 1000 THEN
		PSize := 0;
	PSize := PSize + 50;
	MSize := MSize - 50;
END;
{----------------------  STOLEN FROM BOWLING PROGRAM  ------------------------------}
FUNCTION DigitToChar(D : INTEGER) : Char;
{Converts a digit to a character (e.g. 3 becomes '3').  
 Numbers other than a single digit become an 'X' }
BEGIN
	IF (D > 9) OR (D < 0) THEN
    	DigitToChar := 'X'
	ELSE
    	DigitToChar := CHR(D+48);
END;

PROCEDURE IntToStr( X, Width:INTEGER; VAR Result:STRING);
{ Convert an Integer into a String suitable for outTextXY.  If X has
  fewer than Width digits, it is padded on the left with blanks.  If
  X has more than Width digits, Result will be whatever length is
  required to store the digits}  
VAR Length,Digit, i, Index : INTEGER;
    tempStr : STRING;
BEGIN {IntToStr}
	{First decode digits into tempStr}
	Length := 0;
	IF X = 0 THEN
    	BEGIN
        	Length := 1;
        	tempStr := "0";
   	 	END
	ELSE
    	WHILE X > 0 DO
        	BEGIN
        		Length := Length + 1;
        		Digit := X MOD 10;
        		TempStr[Length] := DigitToChar(Digit);
        		X := X DIV 10;
        	END; 
	{Pad to appropriate width}
	WHILE Length < Width DO
    	BEGIN
        	Length := Length + 1;
        	TempStr[Length] := ' ';
    	END;
	{Copy into Reslt in reverse order}
	Index := 1;
	FOR i := Length DOWNTO 1 DO
    	BEGIN
        	Result[Index] := tempStr[i];
        	Index := Index + 1;
    	END;
	{Set length of Result}
	Result[0] := CHR(Length);
END; {IntToStr}
{------------------------------------------------------------------------------}

BEGIN  {main program module}

Randomize; {seed the random number generator}

Rate := 1;
FOR Count := 1 TO Num DO
		WaitY[Count] := 0;
		
WHILE (Rate <= 5600) DO  {get max wait time for all values of rate from 100 to 5600 by 100's}

	BEGIN

		{Variable initialization module for each new value of rate}
		WaitSum := 0;  WaitAve := 0;

		FOR Rotation := 1 TO NumRot DO  {do the loop NumRot times for each rate}

			BEGIN

				{Variable initialization module}
				Packet := 0;
				MessFile := 0;
				MessMax := 0;

				{Main loop : simulates 90 seconds of real time}
				FOR Tick := 1 TO 10000 DO

					BEGIN {main loop}
	
						{New message module}
						MessFile := MessFile + Message(Rate);
						IF MessFile > MessMax THEN
							MessMax := MessFile;
			
						{Packet assembly module}
						IF MessFile > 0 THEN
							Server(Packet, MessFile);
			
					END;  {main loop}
	
				{Report module}
				Wait := MessMax/50 * 9/1000;
				{i.e., byte-time * maximum message size, in seconds}
				WaitSum := WaitSum + Wait;  {add to WaitSum for later calc of ave}
	
			END;  {rotation loop}
	
			{Calculate average maximum wait time and display}
			WaitAve := WaitSum / NumRot;
			WRITELN;
			WRITELN('The average maximum wait time for a rate of ', Rate:1, '/cps is: ', WaitAve:3:3);
			
			{Fill the proper element of the arrays}
			WaitY[Rate] := WaitAve;  {Fills the array with the appropriate max wait time}
			
			Rate := Rate + Inc;  {increment to next value of rate}
	
	END; {while loop}

{Graphics module}
SetGraph;
ClrScr;
SetColor(0);
PlotX := 0; PlotY := 0;

{Graph Area Display module}
Line(70, 115, 570, 115);
Line(570, 115, 570, 365);
Line(570, 365, 70, 365);
Line(70, 365, 70, 115);

{Heading Display module}
OUTTEXTXY(196, 395, 'RATE OF INCOMING MESSAGES (cps)');
WaitDisplay := "MAXIMUM WAIT TIME -sec-";
FOR Count := 1 TO 23 DO
	OUTTEXTXY(25, (Count * 10) + 127, WaitDisplay[Count]);
OUTTEXTXY(56, 376, '0');

{Display the 'X' coordinates}
FOR Count := 1 TO 5 DO
	BEGIN
		IntToStr((Count * 1000), 4, TempStr);
		OUTTEXTXY(TRUNC(((Count * 1000) * 0.089) + 54), 376, TempStr);
	END;

{Display the 'Y' coordinates}
FOR Count := 1 TO 10 DO
	BEGIN
		IntToStr((Count * 10), 3, TempStr);
		OUTTEXTXY(43, TRUNC(((Count * 10) * (-2.5)) + 365), TempStr);
	END;
	
{Graph plotting module}
FOR Count := 1 TO Num DO
	BEGIN
		PlotX := TRUNC((Count * 0.089) + 70);
		PlotY := TRUNC((WaitY[Count] * (-2.5)) + 365);
		PutPixel(PlotX, PlotY);
	END;
	
Pause;  {stop execution so user can see the resulting graph}

END. {program}