home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / modula2 / library / queuem2 / quedsply.mod < prev    next >
Text File  |  1989-08-30  |  15KB  |  474 lines

  1. (* source: h:\modula\code\queues\QueDsply.MOD   v1.0a       revised: 88.07.22
  2.    author: G.Greene, AGCS D/429 (NS/TS), 312/681-7783       created: 88.07.22
  3.  
  4.    function:
  5.     Implementation code for procedures used by main program module
  6.     QueueExample to create and update a graphic display of queue and server
  7.     status.
  8.  
  9.    history:
  10.     88.07.22  1.0a  initial release
  11. *)
  12.  
  13.  
  14. IMPLEMENTATION MODULE QueDsply;
  15.  
  16.  
  17. FROM  IO        IMPORT  (*PROC*)  WrStr,  WrCard,  WrChar,  WrLngCard,
  18.                                   KeyPressed,  RdKey;
  19.  
  20. (* note name change from JPI distribution:  my WinOpen == Window .Open *)
  21. FROM  Window    IMPORT  (*CONST*) ScreenWidth,  ScreenDepth,
  22.                         (*TYPE*)  WinType,    WinDef,  Color,
  23.                         (*PROC*)  WinOpen,    Use,     Clear,
  24.                                   PutOnTop,   GotoXY,
  25.                                   TextColor,  TextBackground;
  26.  
  27. FROM  Lib       IMPORT  (*PROC*)  Delay;
  28.  
  29. FROM  QueueADT  IMPORT  (*PROC*)  QueueSize;
  30.  
  31. FROM  QueData   IMPORT  (*CONST*) MaxQueues,  MaxServers,
  32.                         (*TYPE*)  ServiceFunctions,  ProcessTimes,
  33.                                   QueueEntryData,
  34.                                   QueueListIndices,  ServerListIndices,
  35.                                   QueueInfo,   ServerInfo,
  36.                                   QueueLists,  ServerLists;
  37.  
  38. VAR
  39.   SpecWindow,
  40.   GrafWindow,
  41.   StatWindow:    WinType;
  42.  
  43.   SpecWindowDef,
  44.   GrafWindowDef,
  45.   StatWindowDef: WinDef;
  46.  
  47. (*                                                                         [2]
  48.  source: h:\modula\code\queues\QueDsply.MOD  v1.0a        revised: 88.07.22 *)
  49.  
  50.  
  51. PROCEDURE  DisplayStatusMatrix ( );
  52.  
  53.   VAR
  54.     QueueNumber,
  55.     QueueRow:    CARDINAL;
  56.  
  57.  
  58. (*  Write the pattern of characters specified by the first parameter the
  59.     number of times specified by the second parameter.  The starting point
  60.     for the write is the current screen position.
  61. *)
  62.  
  63.   PROCEDURE  WritePattern (
  64.                    (*in*)  Pattern:  ARRAY  OF CHAR;
  65.                    (*in*)  Repeats:  CARDINAL );
  66.  
  67.     VAR
  68.       RepeatCount,
  69.       CharIndex:    CARDINAL;
  70.  
  71.     BEGIN
  72.       FOR  RepeatCount := 1  TO  Repeats  DO
  73.         FOR  CharIndex := 0  TO  HIGH ( Pattern )  DO
  74.           WrChar ( Pattern [ CharIndex ] );
  75.         END;
  76.       END;
  77.     END  WritePattern;
  78.  
  79. (*                                                                         [3]
  80.  source: h:\modula\code\queues\QueDsply.MOD  v1.0a        revised: 88.07.22 *)
  81.  
  82.  
  83. (* Write the text specified by the first parameter vertically on the screen,
  84.    starting with the column and row on the screen specified by the second and
  85.    third parameters, respectively.
  86. *)
  87.  
  88.   PROCEDURE  WriteVertically (
  89.                       (*in*)  text:      ARRAY  OF CHAR;
  90.                       (*in*)  inColumn:  CARDINAL;
  91.                       (*in*)  StartRow:  CARDINAL );
  92.     VAR
  93.       RowIndex,
  94.       textIndex: CARDINAL;
  95.  
  96.     BEGIN
  97.       RowIndex := StartRow;
  98.  
  99.       FOR  textIndex := 0  TO  HIGH ( text )  DO
  100.         GotoXY ( inColumn, RowIndex );   WrChar ( text [ textIndex ] );
  101.         INC  ( RowIndex );
  102.       END;
  103.     END  WriteVertically;
  104.  
  105.  
  106.   BEGIN   (* DisplayStatusMatrix *)
  107.     Use ( GrafWindow );    Clear;
  108.  
  109.     GotoXY ( 1, 1 );  WrStr ( "╔═══╦═╤═╤═╤═╤═╦" );
  110.         WritePattern ( "══", 28 );   WrStr ( '╦═════╗' );
  111.  
  112.     GotoXY ( 1, 2 );  WrStr ( "║   ║ SERVERS ║ WARNINGS:" );
  113.         GotoXY ( 72, 2 );  WrStr ( "║TIME:║" );
  114.  
  115.     GotoXY ( 1, 3 );  WrStr ( "║   ║1│2│3│4│5║   ERRORS:" );
  116.         GotoXY ( 72, 3 );  WrStr ( "║     ║" );
  117.  
  118.     GotoXY ( 1, 4 );  WrStr ( "╠═══╬═╪═╪═╪═╪═╬" );
  119.         WritePattern ( "════╤════╦", 5 );
  120.         WrStr  ( "════╤═╩══╦══╣" );
  121.  
  122.     FOR  QueueNumber := 1  TO  10  DO
  123.       QueueRow := QueueNumber * 2 + 3;
  124.  
  125.       GotoXY ( 1, QueueRow );   WrChar ( '║' );
  126.           WrCard ( QueueNumber, 3 );   WrStr ( "║ │ │ │ │ ║" );
  127.           GotoXY ( 78, QueueRow );   WrChar ( '║' );
  128.  
  129.       GotoXY ( 1, QueueRow + 1 );  WrStr ( "╟  ─╫─┼─┼─┼─┼─╫" );
  130.           WritePattern ( "────┼────╫", 6 );   WrStr ( "──╢" );
  131.     END;
  132.  
  133.     GotoXY ( 1, 24 );  WrStr ( "╚═══╩═╧═╧═╧═╧═╩" );
  134.         WritePattern ( "════╧════╩", 6 );   WrStr ( "══╝" );
  135.  
  136.     WriteVertically ( "QUEUES",  2, 11 );
  137.   END  DisplayStatusMatrix;
  138.  
  139. (*                                                                         [4]
  140.  source: h:\modula\code\queues\QueDsply.MOD  v1.0a        revised: 88.07.22 *)
  141.  
  142.  
  143. (* To allow display of as many queue entries as possible, we use the graphics
  144.    characters to squeeze two "pseudo-columns" into each screen display column.
  145.    Set the pseudo-column position on the display for the queue specified by
  146.    the first parameter that corresponds to the value of queue length specified
  147.    by the second parameter.  If the third parameter is Mark, that pseudo-
  148.    column is filled; otherwise it is blanked.  A special character is used at
  149.    the end of the row to indicate overflow.
  150. *)
  151.  
  152. PROCEDURE  ChangeQueueDisplay (
  153.                        (*in*)  Queue:  CARDINAL;
  154.                        (*in*)  Length: CARDINAL;
  155.                        (*in*)  Action: DisplayActions );
  156.   CONST
  157.     LastColumn = 76;   (* last available column for a queue element display *)
  158.  
  159.   VAR
  160.     QueueRow,
  161.     QueueCol:  CARDINAL;
  162.  
  163.   BEGIN
  164.     Use ( GrafWindow );
  165.     QueueRow := Queue * 2 + 3;
  166.  
  167.     IF  Length > 0  THEN
  168.       QueueCol := ( Length - 1 ) DIV 2 + 16;
  169.  
  170.       IF  QueueCol > LastColumn  THEN
  171.         GotoXY  ( LastColumn, QueueRow );
  172.         WrChar ( '' );
  173.  
  174.       ELSE
  175.         GotoXY ( QueueCol, QueueRow );
  176.  
  177.         CASE  Action  OF
  178.           Mark:
  179.               IF  ODD ( Length )
  180.                 THEN   WrChar ( '▌' );
  181.                 ELSE   WrChar ( '█' );
  182.               END;
  183.         |
  184.           Unmark:
  185.               IF  ODD ( Length )
  186.                 THEN   WrChar ( ' ' );
  187.                 ELSE   WrChar ( '▌' );
  188.               END;
  189.         END;   (* CASE Action *)
  190.       END;   (* IF QueueCol <= LastColumn *)
  191.     END;   (* IF Length > 0 *)
  192.  
  193.     PutOnTop ( GrafWindow );
  194.   END  ChangeQueueDisplay;
  195.  
  196. (*                                                                         [5]
  197.  source: h:\modula\code\queues\QueDsply.MOD  v1.0a        revised: 88.07.22 *)
  198.  
  199.  
  200. (* Display the active status of the server specified by the second parameter
  201.    for the queue specified by the first parameter.  If the server is active,
  202.    the third parameter value is Mark;  if it is idle, the value is Unmark.
  203.    The happy-face symbol "lights up" on a screen with reverse video (e.g.
  204.    white on blue) when a customer arrives (obviously not one of the servers I
  205.    ever get).  The alternative display characters are suggested in case you
  206.    don't want the display to be quite so cutesy.
  207. *)
  208.  
  209. PROCEDURE  ChangeServerDisplay (
  210.                         (*in*)  Queue:  CARDINAL;
  211.                         (*in*)  Server: CARDINAL;
  212.                         (*in*)  Action: DisplayActions );
  213.   VAR
  214.     QueueRow,
  215.     ServerCol:  CARDINAL;
  216.  
  217.   BEGIN
  218.     Use ( GrafWindow );
  219.     QueueRow  := Queue  * 2  +  3;
  220.     ServerCol := Server * 2  +  4;
  221.  
  222.     GotoXY ( ServerCol, QueueRow );
  223.  
  224.     CASE  Action  OF
  225.       Mark:   WrChar ( '' );    (* alternatively, '█' *)
  226.     |
  227.       Unmark: WrChar ( '' );    (* alternatively, '░' *)
  228.     END;   (* CASE Action *)
  229.   END  ChangeServerDisplay;
  230.  
  231. (*                                                                         [6]
  232.  source: h:\modula\code\queues\QueDsply.MOD  v1.0a        revised: 88.07.22 *)
  233.  
  234.  
  235. (* Display the current relative emulated time (in whatever time units the
  236.    user has chosen) in the proper space on the screen (upper left corner).
  237. *)
  238.  
  239. PROCEDURE  DisplayCurrentTime (
  240.                        (*in*)  Time: CARDINAL );
  241.  
  242.   BEGIN
  243.     Use ( GrafWindow );
  244.     GotoXY (73, 3);
  245.     WrCard ( Time, 5 );
  246.   END  DisplayCurrentTime;
  247.  
  248.  
  249.  
  250. (* Display a status message in the message box on the top center of the
  251.    screen.  There are two classes of message, warning and error;  each has
  252.    its own line so they don't step on each other.  The type of message we
  253.    are to display is specified by the first parameter.  The message itself
  254.    is specified by the second parameter.
  255. *)
  256.  
  257. PROCEDURE  DisplayMessage (
  258.                    (*in*)  MessageType: MessageTypes;
  259.                    (*in*)  Message:  ARRAY  OF CHAR );
  260.   CONST
  261.     MaxMessageSize = 44;
  262.  
  263.   VAR
  264.     MessageIndex,
  265.     UsableLength: CARDINAL;
  266.  
  267.   BEGIN
  268.     Use ( GrafWindow );
  269.  
  270.     CASE  MessageType  OF
  271.       WarningMessage:   GotoXY (27, 2);
  272.     |
  273.       ErrorMessage:     GotoXY (27, 3);
  274.     END;   (*CASE*)
  275.  
  276.     IF  HIGH ( Message ) >= MaxMessageSize
  277.       THEN  UsableLength := MaxMessageSize;
  278.       ELSE  UsableLength := HIGH ( Message );
  279.     END;
  280.  
  281.     FOR  MessageIndex := 0  TO  UsableLength  DO
  282.       WrChar ( Message [ MessageIndex ] );
  283.     END;
  284.   END  DisplayMessage;
  285.  
  286. (*                                                                         [7]
  287.  source: h:\modula\code\queues\QueDsply.MOD  v1.0a        revised: 88.07.22 *)
  288.  
  289.  
  290. (*  Report the results of the queue simulation.  The report is designed to
  291.     fit on a 25-line PC screen.  That report is generated in a separate
  292.     window from the one that was used to display the dynamic status.  The
  293.     two windows are alternately displayed, for an initial period of 5 seconds
  294.     each.  The operator can change the display period to x seconds, where
  295.     x is from 1 to 10 by pressing '1' through '0'.  Pressing '+' or '-'
  296.     respectively increases or decreases the period by 1/2 second.  To stop
  297.     the display, press 'X' (must be a capital letter).
  298. *)
  299.  
  300. PROCEDURE  DisplaySummary (
  301.                            QueueList:  QueueLists;
  302.                            ServerList: ServerLists;
  303.                            NumberOfQueues: QueueListIndices );
  304.  
  305.  
  306.   VAR
  307.     ScrollIndex: CARDINAL;
  308.     QueueIndex:  QueueListIndices;
  309.     ServerIndex: ServerListIndices;
  310.     Customers:   CARDINAL;
  311.     MeanWait:    LONGCARD;
  312.  
  313. (*                                                                         [8]
  314.  source: h:\modula\code\queues\QueDsply.MOD  v1.0a        revised: 88.07.22 *)
  315.  
  316.  
  317. (* Switch between the dynamic queue display and the final summary display on
  318.    a time interval selected by the operator.  Stop, when the operator types
  319.    'X'.  This is a trivial use of the JPI Window module, but I learned quite
  320.    a bit from writing it.
  321. *)
  322.  
  323. PROCEDURE  AlternateWindows ( );
  324.  
  325.   VAR
  326.     ShowingStat: BOOLEAN;
  327.     DelayPeriod: CARDINAL;
  328.     KeyChar:     CHAR;
  329.  
  330.   BEGIN  (* AlternateWindows *)
  331.     ShowingStat := FALSE;  (* initially we display the dynamic display *)
  332.     DelayPeriod := 5000;   (* initial value in ms (nominal) *)
  333.  
  334.     LOOP
  335.       Delay ( DelayPeriod );
  336.  
  337.       IF  KeyPressed ( )  THEN
  338.         KeyChar := RdKey ( );
  339.  
  340.         CASE  KeyChar  OF
  341.           '1' .. '9':  DelayPeriod := 1000 * ( ORD ( KeyChar ) - ORD ( '0' ) );
  342.         |
  343.           '+':         INC ( DelayPeriod, 500 );
  344.         |
  345.           '-':         IF  DelayPeriod > 1000  THEN  (* minimum is 1 second *)
  346.                          DEC ( DelayPeriod, 500 );
  347.                        END;
  348.         |
  349.  
  350.           'X':         EXIT;
  351.         |
  352.           ELSE         WrChar ( CHR ( 7 ) );
  353.         END;   (* CASE KeyChar *)
  354.       END;   (* IF KeyPressed *)
  355.  
  356.       IF  ShowingStat
  357.         THEN  PutOnTop ( GrafWindow );
  358.         ELSE  PutOnTop ( StatWindow );
  359.       END;
  360.  
  361.       ShowingStat := NOT ShowingStat;
  362.     END;   (* LOOP *)
  363.   END AlternateWindows;
  364.  
  365. (*                                                                         [9]
  366.  source: h:\modula\code\queues\QueDsply.MOD  v1.0a        revised: 88.07.22 *)
  367.  
  368.  
  369.   BEGIN  (* DisplaySummary *)
  370.     Use ( StatWindow );
  371.  
  372.     FOR  QueueIndex := 1  TO  NumberOfQueues  DO
  373.       GotoXY ( 0, QueueIndex * 2 + 2 );
  374.       WrCard ( QueueIndex, 2 );
  375.  
  376.       IF  QueueList [ QueueIndex ] .ExternalInput
  377.         THEN  WrStr ( "E" );
  378.         ELSE  WrStr ( "I" );
  379.       END;
  380.  
  381.       WrCard ( QueueList [ QueueIndex ] .SinkOutputTo,  3 );
  382.       WrCard ( QueueList [ QueueIndex ] .CurrentSize,   6 );
  383.  
  384.       IF  QueueList [ QueueIndex ] .CurrentSize =
  385.                             QueueSize ( QueueList [ QueueIndex ] .theQueue )
  386.         THEN  WrStr ( " " );
  387.         ELSE  WrStr ( "*" );
  388.       END;   (* IF *)
  389.  
  390.       WrLngCard ( QueueList [ QueueIndex ] .TotalWait,  9 );
  391.  
  392.       Customers := 0;
  393.  
  394.       FOR  ServerIndex := 1  TO  MaxServers  DO
  395.         IF  ServerIndex > QueueList [ QueueIndex ] .ServerCount  THEN
  396.           WrStr ( "  (N/A)" );
  397.  
  398.         ELSE
  399.           WITH  ServerList [ QueueIndex, ServerIndex ]  DO
  400.             WrCard ( TotIdleTime,  6 );
  401.  
  402.             IF  IdleNow
  403.               THEN  WrStr ( "" );
  404.               ELSE  WrStr ( "" );
  405.             END;   (* IF IdleNow *)
  406.  
  407.             Customers := Customers + CustomerCnt;
  408.           END;   (* WITH ServerList[QueueIndex,ServerIndex] *)
  409.         END;   (* IF server exists *)
  410.       END;   (* FOR each server *)
  411.  
  412.       MeanWait := QueueList [ QueueIndex ] .TotalWait  DIV
  413.                                                       LONGCARD ( Customers );
  414.       WrCard ( Customers, 7 );
  415.       WrLngCard ( MeanWait, 6 );
  416.     END;   (* FOR each queue *)
  417.  
  418.     AlternateWindows;
  419.   END  DisplaySummary;
  420.  
  421. (*                                                                        [10]
  422.  source: h:\modula\code\queues\QueDsply.MOD  v1.0a        revised: 88.07.22 *)
  423.  
  424.  
  425. BEGIN   (* initialization *)
  426.   WITH  SpecWindowDef  DO
  427.     X1 := 0;  Y1 := 0;   X2 := ScreenWidth - 1;  Y2 := ScreenDepth - 1;
  428.     Foreground := White;   Background := Black;
  429.     CursorOn   := TRUE;    WrapOn     := FALSE;
  430.     Hidden     := FALSE;   FrameOn    := FALSE;
  431.   END;
  432.  
  433.   SpecWindow := WinOpen ( SpecWindowDef );
  434.  
  435.   WITH  GrafWindowDef  DO
  436.     X1 := 0;  Y1 := 0;   X2 := ScreenWidth - 1;  Y2 := ScreenDepth - 1;
  437.     Foreground := Black;   Background := LightGray;
  438.     CursorOn   := FALSE;   WrapOn     := FALSE;
  439.     Hidden     := TRUE;   FrameOn    := FALSE;
  440.   END;
  441.  
  442.   GrafWindow := WinOpen ( GrafWindowDef );
  443.  
  444.   Use ( GrafWindow );
  445.     DisplayStatusMatrix;
  446.  
  447.   WITH  StatWindowDef  DO
  448.     X1 := 0;  Y1 := 0;   X2 := ScreenWidth - 1;  Y2 := ScreenDepth - 1;
  449.     Foreground := White;   Background := Black;
  450.     CursorOn   := FALSE;   WrapOn     := FALSE;
  451.     Hidden     := TRUE;    FrameOn    := FALSE;
  452.   END;
  453.  
  454.   StatWindow := WinOpen ( StatWindowDef );
  455.  
  456.   Use ( StatWindow );
  457.     GotoXY ( 0, 0 );
  458.     WrStr ( "                   ---  FINAL STATUS SUMMARY  ---" );
  459.     GotoXY ( 0, 1 );
  460.     WrStr ( "QUEUE   FINAL  TOTAL    ╒═══════════ SERVERS ═══════════╕" );
  461.         WrStr ( "  CUST.  MEAN" );
  462.     GotoXY ( 0, 2 );
  463.     WrStr ( "NR/>TO  SIZE   WAIT     ▒▒1▒▒  ▒▒2▒▒  ▒▒3▒▒  ▒▒4▒▒  ▒▒5▒▒" );
  464.         WrStr ( "  COUNT  WAIT" );
  465.     GotoXY ( 0, 3 );
  466.     WrStr ( "--- --  -----  -------  -----  -----  -----  -----  -----" );
  467.         WrStr ( "  -----  ----" );
  468.  
  469.   Use ( SpecWindow );
  470.     Clear;   GotoXY ( 0, 0 );
  471.     PutOnTop ( SpecWindow );
  472.  
  473. END  QueDsply.
  474.