home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
modula2
/
library
/
queuem2
/
quedsply.mod
< prev
next >
Wrap
Text File
|
1989-08-30
|
15KB
|
474 lines
(* source: h:\modula\code\queues\QueDsply.MOD v1.0a revised: 88.07.22
author: G.Greene, AGCS D/429 (NS/TS), 312/681-7783 created: 88.07.22
function:
Implementation code for procedures used by main program module
QueueExample to create and update a graphic display of queue and server
status.
history:
88.07.22 1.0a initial release
*)
IMPLEMENTATION MODULE QueDsply;
FROM IO IMPORT (*PROC*) WrStr, WrCard, WrChar, WrLngCard,
KeyPressed, RdKey;
(* note name change from JPI distribution: my WinOpen == Window .Open *)
FROM Window IMPORT (*CONST*) ScreenWidth, ScreenDepth,
(*TYPE*) WinType, WinDef, Color,
(*PROC*) WinOpen, Use, Clear,
PutOnTop, GotoXY,
TextColor, TextBackground;
FROM Lib IMPORT (*PROC*) Delay;
FROM QueueADT IMPORT (*PROC*) QueueSize;
FROM QueData IMPORT (*CONST*) MaxQueues, MaxServers,
(*TYPE*) ServiceFunctions, ProcessTimes,
QueueEntryData,
QueueListIndices, ServerListIndices,
QueueInfo, ServerInfo,
QueueLists, ServerLists;
VAR
SpecWindow,
GrafWindow,
StatWindow: WinType;
SpecWindowDef,
GrafWindowDef,
StatWindowDef: WinDef;
(* [2]
source: h:\modula\code\queues\QueDsply.MOD v1.0a revised: 88.07.22 *)
PROCEDURE DisplayStatusMatrix ( );
VAR
QueueNumber,
QueueRow: CARDINAL;
(* Write the pattern of characters specified by the first parameter the
number of times specified by the second parameter. The starting point
for the write is the current screen position.
*)
PROCEDURE WritePattern (
(*in*) Pattern: ARRAY OF CHAR;
(*in*) Repeats: CARDINAL );
VAR
RepeatCount,
CharIndex: CARDINAL;
BEGIN
FOR RepeatCount := 1 TO Repeats DO
FOR CharIndex := 0 TO HIGH ( Pattern ) DO
WrChar ( Pattern [ CharIndex ] );
END;
END;
END WritePattern;
(* [3]
source: h:\modula\code\queues\QueDsply.MOD v1.0a revised: 88.07.22 *)
(* Write the text specified by the first parameter vertically on the screen,
starting with the column and row on the screen specified by the second and
third parameters, respectively.
*)
PROCEDURE WriteVertically (
(*in*) text: ARRAY OF CHAR;
(*in*) inColumn: CARDINAL;
(*in*) StartRow: CARDINAL );
VAR
RowIndex,
textIndex: CARDINAL;
BEGIN
RowIndex := StartRow;
FOR textIndex := 0 TO HIGH ( text ) DO
GotoXY ( inColumn, RowIndex ); WrChar ( text [ textIndex ] );
INC ( RowIndex );
END;
END WriteVertically;
BEGIN (* DisplayStatusMatrix *)
Use ( GrafWindow ); Clear;
GotoXY ( 1, 1 ); WrStr ( "╔═══╦═╤═╤═╤═╤═╦" );
WritePattern ( "══", 28 ); WrStr ( '╦═════╗' );
GotoXY ( 1, 2 ); WrStr ( "║ ║ SERVERS ║ WARNINGS:" );
GotoXY ( 72, 2 ); WrStr ( "║TIME:║" );
GotoXY ( 1, 3 ); WrStr ( "║ ║1│2│3│4│5║ ERRORS:" );
GotoXY ( 72, 3 ); WrStr ( "║ ║" );
GotoXY ( 1, 4 ); WrStr ( "╠═══╬═╪═╪═╪═╪═╬" );
WritePattern ( "════╤════╦", 5 );
WrStr ( "════╤═╩══╦══╣" );
FOR QueueNumber := 1 TO 10 DO
QueueRow := QueueNumber * 2 + 3;
GotoXY ( 1, QueueRow ); WrChar ( '║' );
WrCard ( QueueNumber, 3 ); WrStr ( "║ │ │ │ │ ║" );
GotoXY ( 78, QueueRow ); WrChar ( '║' );
GotoXY ( 1, QueueRow + 1 ); WrStr ( "╟ ─╫─┼─┼─┼─┼─╫" );
WritePattern ( "────┼────╫", 6 ); WrStr ( "──╢" );
END;
GotoXY ( 1, 24 ); WrStr ( "╚═══╩═╧═╧═╧═╧═╩" );
WritePattern ( "════╧════╩", 6 ); WrStr ( "══╝" );
WriteVertically ( "QUEUES", 2, 11 );
END DisplayStatusMatrix;
(* [4]
source: h:\modula\code\queues\QueDsply.MOD v1.0a revised: 88.07.22 *)
(* To allow display of as many queue entries as possible, we use the graphics
characters to squeeze two "pseudo-columns" into each screen display column.
Set the pseudo-column position on the display for the queue specified by
the first parameter that corresponds to the value of queue length specified
by the second parameter. If the third parameter is Mark, that pseudo-
column is filled; otherwise it is blanked. A special character is used at
the end of the row to indicate overflow.
*)
PROCEDURE ChangeQueueDisplay (
(*in*) Queue: CARDINAL;
(*in*) Length: CARDINAL;
(*in*) Action: DisplayActions );
CONST
LastColumn = 76; (* last available column for a queue element display *)
VAR
QueueRow,
QueueCol: CARDINAL;
BEGIN
Use ( GrafWindow );
QueueRow := Queue * 2 + 3;
IF Length > 0 THEN
QueueCol := ( Length - 1 ) DIV 2 + 16;
IF QueueCol > LastColumn THEN
GotoXY ( LastColumn, QueueRow );
WrChar ( '' );
ELSE
GotoXY ( QueueCol, QueueRow );
CASE Action OF
Mark:
IF ODD ( Length )
THEN WrChar ( '▌' );
ELSE WrChar ( '█' );
END;
|
Unmark:
IF ODD ( Length )
THEN WrChar ( ' ' );
ELSE WrChar ( '▌' );
END;
END; (* CASE Action *)
END; (* IF QueueCol <= LastColumn *)
END; (* IF Length > 0 *)
PutOnTop ( GrafWindow );
END ChangeQueueDisplay;
(* [5]
source: h:\modula\code\queues\QueDsply.MOD v1.0a revised: 88.07.22 *)
(* Display the active status of the server specified by the second parameter
for the queue specified by the first parameter. If the server is active,
the third parameter value is Mark; if it is idle, the value is Unmark.
The happy-face symbol "lights up" on a screen with reverse video (e.g.
white on blue) when a customer arrives (obviously not one of the servers I
ever get). The alternative display characters are suggested in case you
don't want the display to be quite so cutesy.
*)
PROCEDURE ChangeServerDisplay (
(*in*) Queue: CARDINAL;
(*in*) Server: CARDINAL;
(*in*) Action: DisplayActions );
VAR
QueueRow,
ServerCol: CARDINAL;
BEGIN
Use ( GrafWindow );
QueueRow := Queue * 2 + 3;
ServerCol := Server * 2 + 4;
GotoXY ( ServerCol, QueueRow );
CASE Action OF
Mark: WrChar ( '' ); (* alternatively, '█' *)
|
Unmark: WrChar ( '' ); (* alternatively, '░' *)
END; (* CASE Action *)
END ChangeServerDisplay;
(* [6]
source: h:\modula\code\queues\QueDsply.MOD v1.0a revised: 88.07.22 *)
(* Display the current relative emulated time (in whatever time units the
user has chosen) in the proper space on the screen (upper left corner).
*)
PROCEDURE DisplayCurrentTime (
(*in*) Time: CARDINAL );
BEGIN
Use ( GrafWindow );
GotoXY (73, 3);
WrCard ( Time, 5 );
END DisplayCurrentTime;
(* Display a status message in the message box on the top center of the
screen. There are two classes of message, warning and error; each has
its own line so they don't step on each other. The type of message we
are to display is specified by the first parameter. The message itself
is specified by the second parameter.
*)
PROCEDURE DisplayMessage (
(*in*) MessageType: MessageTypes;
(*in*) Message: ARRAY OF CHAR );
CONST
MaxMessageSize = 44;
VAR
MessageIndex,
UsableLength: CARDINAL;
BEGIN
Use ( GrafWindow );
CASE MessageType OF
WarningMessage: GotoXY (27, 2);
|
ErrorMessage: GotoXY (27, 3);
END; (*CASE*)
IF HIGH ( Message ) >= MaxMessageSize
THEN UsableLength := MaxMessageSize;
ELSE UsableLength := HIGH ( Message );
END;
FOR MessageIndex := 0 TO UsableLength DO
WrChar ( Message [ MessageIndex ] );
END;
END DisplayMessage;
(* [7]
source: h:\modula\code\queues\QueDsply.MOD v1.0a revised: 88.07.22 *)
(* Report the results of the queue simulation. The report is designed to
fit on a 25-line PC screen. That report is generated in a separate
window from the one that was used to display the dynamic status. The
two windows are alternately displayed, for an initial period of 5 seconds
each. The operator can change the display period to x seconds, where
x is from 1 to 10 by pressing '1' through '0'. Pressing '+' or '-'
respectively increases or decreases the period by 1/2 second. To stop
the display, press 'X' (must be a capital letter).
*)
PROCEDURE DisplaySummary (
QueueList: QueueLists;
ServerList: ServerLists;
NumberOfQueues: QueueListIndices );
VAR
ScrollIndex: CARDINAL;
QueueIndex: QueueListIndices;
ServerIndex: ServerListIndices;
Customers: CARDINAL;
MeanWait: LONGCARD;
(* [8]
source: h:\modula\code\queues\QueDsply.MOD v1.0a revised: 88.07.22 *)
(* Switch between the dynamic queue display and the final summary display on
a time interval selected by the operator. Stop, when the operator types
'X'. This is a trivial use of the JPI Window module, but I learned quite
a bit from writing it.
*)
PROCEDURE AlternateWindows ( );
VAR
ShowingStat: BOOLEAN;
DelayPeriod: CARDINAL;
KeyChar: CHAR;
BEGIN (* AlternateWindows *)
ShowingStat := FALSE; (* initially we display the dynamic display *)
DelayPeriod := 5000; (* initial value in ms (nominal) *)
LOOP
Delay ( DelayPeriod );
IF KeyPressed ( ) THEN
KeyChar := RdKey ( );
CASE KeyChar OF
'1' .. '9': DelayPeriod := 1000 * ( ORD ( KeyChar ) - ORD ( '0' ) );
|
'+': INC ( DelayPeriod, 500 );
|
'-': IF DelayPeriod > 1000 THEN (* minimum is 1 second *)
DEC ( DelayPeriod, 500 );
END;
|
'X': EXIT;
|
ELSE WrChar ( CHR ( 7 ) );
END; (* CASE KeyChar *)
END; (* IF KeyPressed *)
IF ShowingStat
THEN PutOnTop ( GrafWindow );
ELSE PutOnTop ( StatWindow );
END;
ShowingStat := NOT ShowingStat;
END; (* LOOP *)
END AlternateWindows;
(* [9]
source: h:\modula\code\queues\QueDsply.MOD v1.0a revised: 88.07.22 *)
BEGIN (* DisplaySummary *)
Use ( StatWindow );
FOR QueueIndex := 1 TO NumberOfQueues DO
GotoXY ( 0, QueueIndex * 2 + 2 );
WrCard ( QueueIndex, 2 );
IF QueueList [ QueueIndex ] .ExternalInput
THEN WrStr ( "E" );
ELSE WrStr ( "I" );
END;
WrCard ( QueueList [ QueueIndex ] .SinkOutputTo, 3 );
WrCard ( QueueList [ QueueIndex ] .CurrentSize, 6 );
IF QueueList [ QueueIndex ] .CurrentSize =
QueueSize ( QueueList [ QueueIndex ] .theQueue )
THEN WrStr ( " " );
ELSE WrStr ( "*" );
END; (* IF *)
WrLngCard ( QueueList [ QueueIndex ] .TotalWait, 9 );
Customers := 0;
FOR ServerIndex := 1 TO MaxServers DO
IF ServerIndex > QueueList [ QueueIndex ] .ServerCount THEN
WrStr ( " (N/A)" );
ELSE
WITH ServerList [ QueueIndex, ServerIndex ] DO
WrCard ( TotIdleTime, 6 );
IF IdleNow
THEN WrStr ( "" );
ELSE WrStr ( "" );
END; (* IF IdleNow *)
Customers := Customers + CustomerCnt;
END; (* WITH ServerList[QueueIndex,ServerIndex] *)
END; (* IF server exists *)
END; (* FOR each server *)
MeanWait := QueueList [ QueueIndex ] .TotalWait DIV
LONGCARD ( Customers );
WrCard ( Customers, 7 );
WrLngCard ( MeanWait, 6 );
END; (* FOR each queue *)
AlternateWindows;
END DisplaySummary;
(* [10]
source: h:\modula\code\queues\QueDsply.MOD v1.0a revised: 88.07.22 *)
BEGIN (* initialization *)
WITH SpecWindowDef DO
X1 := 0; Y1 := 0; X2 := ScreenWidth - 1; Y2 := ScreenDepth - 1;
Foreground := White; Background := Black;
CursorOn := TRUE; WrapOn := FALSE;
Hidden := FALSE; FrameOn := FALSE;
END;
SpecWindow := WinOpen ( SpecWindowDef );
WITH GrafWindowDef DO
X1 := 0; Y1 := 0; X2 := ScreenWidth - 1; Y2 := ScreenDepth - 1;
Foreground := Black; Background := LightGray;
CursorOn := FALSE; WrapOn := FALSE;
Hidden := TRUE; FrameOn := FALSE;
END;
GrafWindow := WinOpen ( GrafWindowDef );
Use ( GrafWindow );
DisplayStatusMatrix;
WITH StatWindowDef DO
X1 := 0; Y1 := 0; X2 := ScreenWidth - 1; Y2 := ScreenDepth - 1;
Foreground := White; Background := Black;
CursorOn := FALSE; WrapOn := FALSE;
Hidden := TRUE; FrameOn := FALSE;
END;
StatWindow := WinOpen ( StatWindowDef );
Use ( StatWindow );
GotoXY ( 0, 0 );
WrStr ( " --- FINAL STATUS SUMMARY ---" );
GotoXY ( 0, 1 );
WrStr ( "QUEUE FINAL TOTAL ╒═══════════ SERVERS ═══════════╕" );
WrStr ( " CUST. MEAN" );
GotoXY ( 0, 2 );
WrStr ( "NR/>TO SIZE WAIT ▒▒1▒▒ ▒▒2▒▒ ▒▒3▒▒ ▒▒4▒▒ ▒▒5▒▒" );
WrStr ( " COUNT WAIT" );
GotoXY ( 0, 3 );
WrStr ( "--- -- ----- ------- ----- ----- ----- ----- -----" );
WrStr ( " ----- ----" );
Use ( SpecWindow );
Clear; GotoXY ( 0, 0 );
PutOnTop ( SpecWindow );
END QueDsply.