home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / manage / pplanner.src < prev    next >
Encoding:
Text File  |  1988-05-03  |  384.8 KB  |  13,293 lines

  1. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2. --simutil.ada
  3. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4. with TEXT_IO;
  5.  
  6. ---------------------------------------------------------
  7. -- Author : T. C. Bryan
  8. -- Source:     Division Software Technology and Support
  9. --             Western Development Laboratories
  10. --             Ford Aerospace & Communications Corporation
  11. --             ATTN:  Ada Tools Group
  12. -- Date   : June 1985
  13. -- Summary:  procedure stops a running screen
  14. --           to allow user reading error msgs.
  15. ---------------------------------------------------------
  16. procedure PRESS_RETURN_TO_CONTINUE is
  17.  
  18.         A_RETURN  : string (1..8);
  19.         LAST_CHAR : natural;
  20.  
  21. begin 
  22.     TEXT_IO.NEW_LINE (2);
  23.         TEXT_IO.PUT_LINE ("Please PRESS return to continue ....");
  24.         TEXT_IO.GET_LINE (A_RETURN, LAST_CHAR);
  25. end PRESS_RETURN_TO_CONTINUE;
  26.  
  27.  
  28. with TEXT_IO, PRESS_RETURN_TO_CONTINUE;
  29.  
  30. procedure FATAL (UNIT : STRING) is
  31. -- Author : M. K. McNair
  32. -- Source:     Division Software Technology and Support
  33. --             Western Development Laboratories
  34. --             Ford Aerospace & Communications Corporation
  35. --             ATTN:  Ada Tools Group
  36. -- Date   : 8 March 1985
  37. -- Summary: This procedure provides a centralized error reporting
  38. --          facility. The main use for it is to provide a call
  39. --          traceback facility.
  40.  
  41. begin
  42.     TEXT_IO.NEW_LINE;
  43.     TEXT_IO.PUT_LINE
  44.        ("********************************************************************************");
  45.     TEXT_IO.PUT_LINE ("An internal error occured in the ");
  46.     TEXT_IO.PUT_LINE (UNIT & " unit.");
  47.     TEXT_IO.PUT_LINE ("Please notify your System Manager.");
  48.     TEXT_IO.PUT_LINE
  49.        ("********************************************************************************");
  50.     PRESS_RETURN_TO_CONTINUE;
  51. end FATAL;
  52.  
  53.  
  54.  
  55.  
  56. --  The following is a series of complete and machine-independent,
  57. --  but not necessarily efficient, packages which, if compiled in order,
  58. --  will provide the elementary functions required by some benchmarks
  59.  
  60. --  This specific file was prepared for the VAX/VMS Telesoft 1.3d Oct84 release
  61. --  This is an unvalidated system 
  62.  
  63.  
  64. package FLOATING_CHARACTERISTICS is
  65. --  This package is a floating mantissa definition of a binary FLOAT 
  66. --  It was first used on the DEC-10 and the VAX but should work for any
  67. --  since the parameters are obtained by initializing on the actual hardware
  68. --  Otherwise the parameters could be set in the spec if known
  69. --  This is a preliminary package that defines the properties 
  70. --  of the particular floating point type for which we are going to
  71. --  generate the math routines
  72. --  The constants are those required by the routines described in
  73. --  "Software Manual for the Elementary Functions" W. Cody & W. Waite
  74. --  Prentice-Hall 1980
  75. --  Actually most are needed only for the test programs
  76. --  rather than the functions themselves, but might as well be here
  77. --  Most of these could be in the form of attributes if 
  78. --  all the floating types to be considered were those built into the
  79. --  compiler, but we also want to be able to support user defined types
  80. --  such as software floating types of greater precision than
  81. --  the hardware affords, or types defined on one machine to
  82. --  simulate another
  83. --  So we use the Cody-Waite names and derive them from an adaptation of the
  84. --  MACHAR routine as given by Cody-Waite in Appendix B
  85.  
  86.     IBETA : INTEGER;
  87.     --  The radix of the floating-point representation
  88.  
  89.     IT : INTEGER;
  90.     --  The number of base IBETA digits in the DIS_FLOAT significand
  91.  
  92.     IRND : INTEGER;
  93.     --  TRUE (1) if floating addition rounds, FALSE (0) if truncates
  94.  
  95.     NGRD : INTEGER;
  96.     --  Number of guard digits for multiplication
  97.  
  98.     MACHEP : INTEGER;
  99.     --  The largest negative integer such that
  100.     --    1.0 + FLOAT(IBETA) ** MACHEP /= 1.0
  101.     --  except that MACHEP is bounded below by -(IT + 3)
  102.  
  103.     NEGEP : INTEGER;
  104.     --  The largest negative integer such that
  105.     --    1.0 -0 FLOAT(IBETA) ** NEGEP /= 1.0
  106.     --  except that NEGEP is bounded below by -(IT + 3)
  107.  
  108.     IEXP : INTEGER;
  109.     --  The number of bits (decimal places if IBETA = 10)
  110.     --  reserved for the representation of the exponent (including
  111.     --  the bias or sign) of a floating-point number
  112.  
  113.     MINEXP : INTEGER;
  114.     --  The largest in magnitude negative integer such that
  115.     --  FLOAT(IBETA) ** MINEXP is a positive floating-point number
  116.  
  117.  
  118.     MAXEXP : INTEGER;
  119.     --  The largest positive exponent for a finite floating-point number
  120.  
  121.     EPS : FLOAT;
  122.     --  The smallest positive floating-point number such that
  123.     --                              1.0 + EPS /= 1.0
  124.     --  In particular, if IBETA = 2 or IRND = 0,
  125.     --  EPS = FLOAT(IBETA) ** MACHEP
  126.     --  Otherwise, EPS = (FLOAT(IBETA) ** MACHEP) / 2
  127.  
  128.  
  129.     EPSNEG : FLOAT;
  130.     --  A small positive floating-point number such that 1.0-EPSNEG /= 1.0
  131.  
  132.     XMIN : FLOAT;
  133.     --  The smallest non-vanishing floating-point power of the radix
  134.     --  In particular, XMIN = FLOAT(IBETA) ** MINEXP
  135.  
  136.     XMAX : FLOAT;
  137.     --  The largest finite floating-point number
  138.  
  139. --  Here the structure of the floating type is defined
  140. --  I have assumed that the exponent is always some integer form
  141. --  The mantissa can vary
  142. --  Most often it will be a fixed type or the same floating type
  143. --  depending on the most efficient machine implementation
  144. --  Most efficient implementation may require details of the machine hardware
  145. --  In this version the simplest representation is used
  146. --  The mantissa is extracted into a FLOAT and uses the predefined operations
  147.     type EXPONENT_TYPE is new INTEGER;  --  should be derived  ##########
  148.     subtype MANTISSA_TYPE is FLOAT;   --   range -1.0..1.0;
  149. --  A consequence of the rigorous constraints on MANTISSA_TYPE is that
  150. --  operations must be very carefully examined to make sure that no number
  151. --  greater than one results
  152. --  Actually this limitation is important in constructing algorithms
  153. --  which will also run when MANTISSA_TYPE is a fixed point type
  154.  
  155. --  If we are not using the STANDARD type, we have to define all the 
  156. --  operations at this point
  157. --  We also need PUT for the type if it is not otherwise available
  158.  
  159. --  Now we do something strange
  160. --  Since we do not know in the following routines whether the mantissa
  161. --  will be carried as a fixed or floating type, we have to make some
  162. --  provision for dividing by two
  163. --  We cannot use the literals, since FIXED/2.0 and FLOAT/2 will fail
  164. --  We define a type-dependent factor that will work
  165.     MANTISSA_DIVISOR_2 : constant FLOAT := 2.0;
  166.     MANTISSA_DIVISOR_3 : constant FLOAT := 3.0;
  167. --  This will work for the MANTISSA_TYPE defined above
  168. --  The alternative of defining an operation "/" to take care of it
  169. --  is too sweeping and would allow unAda-like errors
  170.  
  171.     MANTISSA_HALF : constant MANTISSA_TYPE := 0.5;
  172.  
  173.  
  174.     procedure DEFLOAT (X : FLOAT;
  175.                N : in out EXPONENT_TYPE;
  176.                F : in out MANTISSA_TYPE);
  177.     procedure REFLOAT (N : EXPONENT_TYPE;
  178.                F : MANTISSA_TYPE;
  179.                X : in out FLOAT);
  180. --  Since the user may wish to define a floating type by some other name
  181. --  CONVERT_TO_FLOAT is used rather than just FLOAT for explicit coersion
  182.     function CONVERT_TO_FLOAT (K : INTEGER) return FLOAT;
  183.     function CONVERT_TO_FLOAT (N : EXPONENT_TYPE) return FLOAT;
  184.     function CONVERT_TO_FLOAT (F : MANTISSA_TYPE) return FLOAT;
  185.  
  186. end FLOATING_CHARACTERISTICS;
  187.  
  188.  
  189.  
  190. with TEXT_IO;
  191. use TEXT_IO;
  192.  
  193. package body FLOATING_CHARACTERISTICS is
  194. --  This package is a floating mantissa definition of a binary FLOAT
  195.  
  196.     A, B, Y, Z           : FLOAT;
  197.     I, K, MX, IZ         : INTEGER;
  198.     BETA, BETAM1, BETAIN : FLOAT;
  199.     ONE                  : FLOAT := 1.0;
  200.     ZERO                 : FLOAT := 0.0;
  201.  
  202.     procedure DEFLOAT (X : FLOAT;
  203.                N : in out EXPONENT_TYPE;
  204.                F : in out MANTISSA_TYPE) is
  205. --  This is admittedly a slow method - but portable - for breaking down
  206. --  a floating point number into its exponent and mantissa
  207. --  Obviously with knowledge of the machine representation
  208. --  it could be replaced with a couple of simple extractions
  209.     EXPONENT_LENGTH : INTEGER := IEXP;
  210.     M               : EXPONENT_TYPE;
  211.     W, Y, Z         : FLOAT;
  212.     begin
  213.     N := 0;
  214.     F := 0.0;
  215.     Y := abs (X);
  216.  
  217.     if Y = 0.0 then
  218.         return;
  219.  
  220.     elsif Y < 0.5 then
  221.         for J in reverse 0 .. (EXPONENT_LENGTH - 2) loop
  222.         --  Dont want to go all the way to 2.0**(EXPONENT_LENGTH - 1)
  223.         --  Since that (or its reciprocal) will overflow if exponent
  224.         -- biased
  225.         --  Ought to use talbular values rather than compute each time
  226.         M := EXPONENT_TYPE (2 ** J);
  227.         Z := 1.0 / (2.0 ** INTEGER (M));
  228.         W := Y / Z;
  229.  
  230.         if W < 1.0 then
  231.             Y := W;
  232.             N := N - M;
  233.         end if;
  234.         end loop;
  235.     else
  236.         for J in reverse 0 .. (EXPONENT_LENGTH - 2) loop
  237.         M := EXPONENT_TYPE (2 ** J);
  238.         Z := 2.0 ** INTEGER (M);
  239.         W := Y / Z;
  240.  
  241.         if W >= 0.5 then
  242.             Y := W;
  243.             N := N + M;
  244.         end if;
  245.         end loop;
  246.         --  And just to clear up any loose ends from biased exponents
  247.     end if;
  248.  
  249.     while Y < 0.5 loop
  250.         Y := Y * 2.0;
  251.         N := N - 1;
  252.     end loop;
  253.  
  254.     while Y >= 1.0 loop
  255.         Y := Y / 2.0;
  256.         N := N + 1;
  257.     end loop;
  258.  
  259.     F := MANTISSA_TYPE (Y);
  260.  
  261.     if X < 0.0 then
  262.         F := -F;
  263.     end if;
  264.  
  265.     return;
  266.     exception
  267.     when others => 
  268.         N := 0;
  269.         F := 0.0;
  270.         return;
  271.     end DEFLOAT;
  272.  
  273.  
  274.     procedure REFLOAT (N : EXPONENT_TYPE;
  275.                F : MANTISSA_TYPE;
  276.                X : in out FLOAT) is
  277. --  Again a brute force method - but portable
  278. --  Watch out near MAXEXP
  279.     M : INTEGER;
  280.     Y : FLOAT;
  281.     begin
  282.     if F = 0.0 then
  283.         X := ZERO;
  284.         return;
  285.     end if;
  286.  
  287.     M := INTEGER (N);
  288.     Y := abs (FLOAT (F));
  289.  
  290.     while Y < 0.5 loop
  291.         M := M - 1;
  292.  
  293.         if M < MINEXP then
  294.         X := ZERO;
  295.         end if;
  296.  
  297.         Y := Y + Y;
  298.         exit when M <= MINEXP;
  299.     end loop;
  300.  
  301.     if M = MAXEXP then
  302.         M := M - 1;
  303.         X := Y * 2.0 ** M;
  304.         X := X * 2.0;
  305.  
  306.     elsif M <= MINEXP + 2 then
  307.         M := M + 3;
  308.         X := Y * 2.0 ** M;
  309.         X := ((X / 2.0) / 2.0) / 2.0;
  310.     else
  311.         X := Y * 2.0 ** M;
  312.     end if;
  313.  
  314.     if F < 0.0 then
  315.         X := -X;
  316.     end if;
  317.  
  318.     return;
  319.     end REFLOAT;
  320.  
  321.     function CONVERT_TO_FLOAT (K : INTEGER) return FLOAT is
  322.     begin
  323.     return FLOAT (K);
  324.     end CONVERT_TO_FLOAT;
  325.  
  326.     function CONVERT_TO_FLOAT (N : EXPONENT_TYPE) return FLOAT is
  327.     begin
  328.     return FLOAT (N);
  329.     end CONVERT_TO_FLOAT;
  330.  
  331.     function CONVERT_TO_FLOAT (F : MANTISSA_TYPE) return FLOAT is
  332.     begin
  333.     return FLOAT (F);
  334.     end CONVERT_TO_FLOAT;
  335.  
  336.  
  337. begin
  338.     --  Initialization for the VAX with values derived by MACHAR
  339. --  In place of running MACHAR as the actual initialization
  340.  
  341. --  IBETA :=    2;
  342. --  IT :=    24;
  343. --  IRND :=    1;
  344. --  NEGEP :=    -24;
  345. --  EPSNEG :=    5.9604644E-008;
  346. --  MACHEP :=    -24;
  347. --  EPS :=    5.9604644E-008;
  348. --  NGRD :=    0;
  349. --  XMIN := 5.9E-39;
  350. --  MINEXP :=    -126;
  351. --  IEXP :=    8;
  352. --  MAXEXP :=    127;
  353. --  XMAX :=    8.5E37 * 2.0;
  354.  
  355.  
  356. ----  This initialization is the MACHAR routine of Cody and Waite Appendix B.
  357.     PUT ("INITIALIZATING WITH MACHAR     -     ");
  358.     A := ONE;
  359.  
  360.     while (((A + ONE) - A) - ONE) = ZERO loop
  361.     A := A + A;
  362.     end loop;
  363.  
  364.     B := ONE;
  365.  
  366.     while ((A + B) - A) = ZERO loop
  367.     B := B + B;
  368.     end loop;
  369.  
  370.     IBETA := INTEGER ((A + B) - A);
  371.     BETA := CONVERT_TO_FLOAT (IBETA);
  372.  
  373.  
  374.     IT := 0;
  375.     B := ONE;
  376.  
  377.     while (((B + ONE) - B) - ONE) = ZERO loop
  378.     IT := IT + 1;
  379.     B := B * BETA;
  380.     end loop;
  381.  
  382.  
  383.     IRND := 0;
  384.     BETAM1 := BETA - ONE;
  385.  
  386.     if ((A + BETAM1) - A) /= ZERO then
  387.     IRND := 1;
  388.     end if;
  389.  
  390.  
  391.     NEGEP := IT + 3;
  392.     BETAIN := ONE / BETA;
  393.     A := ONE;
  394.  
  395.     for I in 1 .. NEGEP loop
  396. --  for I in 1..50  loop
  397. --  exit when I > NEGEP;
  398.     A := A * BETAIN;
  399.     end loop;
  400.  
  401.     B := A;
  402.  
  403.     while ((ONE - A) - ONE) = ZERO loop
  404.     A := A * BETA;
  405.     NEGEP := NEGEP - 1;
  406.     end loop;
  407.  
  408.     NEGEP := -NEGEP;
  409.  
  410.  
  411.     EPSNEG := A;
  412.  
  413.     if (IBETA /= 2) and (IRND /= 0) then
  414.     A := (A * (ONE + A)) / (ONE + ONE);
  415.  
  416.     if ((ONE - A) - ONE) /= ZERO then
  417.         EPSNEG := A;
  418.     end if;
  419.     end if;
  420.  
  421.  
  422.     MACHEP := -IT - 3;
  423.     A := B;
  424.  
  425.     while ((ONE + A) - ONE) = ZERO loop
  426.     A := A * BETA;
  427.     MACHEP := MACHEP + 1;
  428.     end loop;
  429.  
  430.  
  431.     EPS := A;
  432.  
  433.     if (IBETA /= 2) and (IRND /= 0) then
  434.     A := (A * (ONE + A)) / (ONE + ONE);
  435.  
  436.     if ((ONE + A) - ONE) /= ZERO then
  437.         EPS := A;
  438.     end if;
  439.     end if;
  440.  
  441.  
  442.     NGRD := 0;
  443.  
  444.     if ((IRND = 0) and ((ONE + EPS) * ONE - ONE) /= ZERO) then
  445.     NGRD := 1;
  446.     end if;
  447.  
  448.  
  449.     I := 0;
  450.     K := 1;
  451.     Z := BETAIN;
  452.  
  453.     loop
  454.     Y := Z;
  455.     Z := Y * Y;
  456.     A := Z * ONE;
  457.     exit when ((A + A) = ZERO) or (abs (Z) >= Y);
  458.     I := I + 1;
  459.     K := K + K;
  460.     end loop;
  461.  
  462.     if (IBETA /= 10) then
  463.     IEXP := I + 1;
  464.     MX := K + K;
  465.     else
  466.     IEXP := 2;
  467.     IZ := IBETA;
  468.  
  469.     while (K >= IZ) loop
  470.         IZ := IZ * IBETA;
  471.         IEXP := IEXP + 1;
  472.     end loop;
  473.  
  474.     MX := IZ + IZ - 1;
  475.     end if;
  476.  
  477.     loop
  478.     XMIN := Y;
  479.     Y := Y * BETAIN;
  480.     A := Y * ONE;
  481.     exit when ((A + A) = ZERO) or (abs (Y) >= XMIN);
  482.     K := K + 1;
  483.     end loop;
  484.  
  485.  
  486.     MINEXP := -K;
  487.  
  488.  
  489.     if ((MX <= (K + K - 3)) and (IBETA /= 10)) then
  490.     MX := MX + MX;
  491.     IEXP := IEXP + 1;
  492.     end if;
  493.  
  494.  
  495.     MAXEXP := MX + MINEXP;
  496.     I := MAXEXP + MINEXP;
  497.  
  498.     if ((IBETA = 2) and (I = 0)) then
  499.     MAXEXP := MAXEXP - 1;
  500.     end if;
  501.  
  502.     if (I > 20) then
  503.     MAXEXP := MAXEXP - 1;
  504.     end if;
  505.  
  506.     if (A /= Y) then
  507.     MAXEXP := MAXEXP - 2;
  508.     end if;
  509.  
  510.  
  511.     XMAX := ONE - EPSNEG;
  512.  
  513.     if ((XMAX * ONE) /= XMAX) then
  514.     XMAX := ONE - BETA * EPSNEG;
  515.     end if;
  516.  
  517.     XMAX := XMAX / (BETA * BETA * BETA * XMIN);
  518.     I := MAXEXP + MINEXP + 3;
  519.  
  520.     if I > 0 then
  521.     for J in 1 .. 50 loop
  522.         exit when J > I;
  523.  
  524.         if IBETA = 2 then
  525.         XMAX := XMAX + XMAX;
  526.         else
  527.         XMAX := XMAX * BETA;
  528.         end if;
  529.     end loop;
  530.     end if;
  531.  
  532.     PUT ("INITIALIZED");  NEW_LINE;
  533.  
  534. end FLOATING_CHARACTERISTICS;
  535.  
  536. with TEXT_IO;
  537. use TEXT_IO;
  538.  
  539. package NUMERIC_IO is
  540.  
  541.     procedure GET (FILE : FILE_TYPE; ITEM : out INTEGER);
  542.     procedure GET (ITEM : out INTEGER);
  543.     procedure GET (FILE : FILE_TYPE; ITEM : out FLOAT);
  544.     procedure GET (ITEM : out FLOAT);
  545.     procedure PUT (FILE : FILE_TYPE; ITEM : INTEGER);
  546.     procedure PUT (ITEM : INTEGER; WIDTH : FIELD);
  547.     procedure PUT (ITEM : INTEGER);
  548.     procedure PUT (FILE : FILE_TYPE; ITEM : FLOAT);
  549.     procedure PUT (ITEM : FLOAT);
  550.  
  551. end NUMERIC_IO;
  552.  
  553.  
  554. with TEXT_IO;
  555. use TEXT_IO;
  556.  
  557. package body NUMERIC_IO is
  558. -- This ought to be done by instantiating the FLoaT_IO and INTEGER_IO
  559. --  But if you dont yet have the generic TEXT_IO implemented yet
  560. --  then something like this does the job on the DEC-10 IAPC
  561. --  But it is a kludge
  562. --  No effort has been put into making it pretty or portable
  563.     package INT_IO is new TEXT_IO.INTEGER_IO (INTEGER);
  564.     package FLT_IO is new TEXT_IO.FLOAT_IO (FLOAT);
  565.     use INT_IO;
  566.     use FLT_IO;
  567.  
  568.     procedure GET (FILE : FILE_TYPE; ITEM : out INTEGER) is
  569.     begin
  570.     INT_IO.GET (FILE, ITEM);
  571.     end GET;
  572.  
  573.     procedure GET (ITEM : out INTEGER) is
  574.     begin
  575.     INT_IO.GET (ITEM);
  576.     end GET;
  577.  
  578.     procedure GET (FILE : FILE_TYPE; ITEM : out FLOAT) is
  579.     begin
  580.     FLT_IO.GET (FILE, ITEM);
  581.     end GET;
  582.  
  583.     procedure GET (ITEM : out FLOAT) is
  584.     begin
  585.     FLT_IO.GET (ITEM);
  586.     end GET;
  587.  
  588.     procedure PUT (FILE : FILE_TYPE; ITEM : INTEGER) is
  589.     begin
  590.     INT_IO.PUT (FILE, ITEM);
  591.     end PUT;
  592.  
  593.     procedure PUT (ITEM : INTEGER; WIDTH : FIELD) is
  594.     J, K, M : INTEGER := 0;
  595.     begin
  596.     if WIDTH = 1 then
  597.         case ITEM is
  598.  
  599.         when 0      =>  PUT ('0');
  600.  
  601.         when 1      =>  PUT ('1');
  602.  
  603.         when 2      =>  PUT ('2');
  604.  
  605.         when 3      =>  PUT ('3');
  606.  
  607.         when 4      =>  PUT ('4');
  608.  
  609.         when 5      =>  PUT ('5');
  610.  
  611.         when 6      =>  PUT ('6');
  612.  
  613.         when 7      =>  PUT ('7');
  614.  
  615.         when 8      =>  PUT ('8');
  616.  
  617.         when 9      =>  PUT ('9');
  618.  
  619.         when others =>  PUT ('*');
  620.         end case;
  621.     else
  622.         if ITEM < 0 then
  623.         PUT ('-');
  624.         J := -ITEM;
  625.         else
  626.         PUT (' ');
  627.         J := ITEM;
  628.         end if;
  629.  
  630.         for I in 1 .. WIDTH - 1 loop
  631.         M := 10 ** (WIDTH - 1 - I);
  632.         K := J / M;
  633.         J := J - K * M;
  634.         NUMERIC_IO.PUT (K, 1);
  635.         end loop;
  636.     end if;
  637.     end PUT;
  638.  
  639.     procedure PUT (ITEM : INTEGER) is
  640.     begin
  641.     INT_IO.PUT (ITEM);
  642.     end PUT;
  643.  
  644.     procedure PUT (FILE : FILE_TYPE; ITEM : FLOAT) is
  645.     begin
  646.     FLT_IO.PUT (FILE, ITEM);
  647.     end PUT;
  648.  
  649.     procedure PUT (ITEM : FLOAT) is
  650.     begin
  651.     FLT_IO.PUT (ITEM);
  652.     end PUT;
  653.  
  654. end NUMERIC_IO;
  655.  
  656.  
  657.  
  658. with FLOATING_CHARACTERISTICS;
  659. use FLOATING_CHARACTERISTICS;
  660.  
  661. package NUMERIC_PRIMITIVES is
  662.  
  663. --  This may seem a little much but is put in this form to allow the
  664. --  same form to be used for a generic package
  665. --  If that is not needed, simple litterals could be substituted
  666.     ZERO  : FLOAT := CONVERT_TO_FLOAT (INTEGER (0));
  667.     ONE   : FLOAT := CONVERT_TO_FLOAT (INTEGER (1));
  668.     TWO   : FLOAT := ONE + ONE;
  669.     THREE : FLOAT := ONE + ONE + ONE;
  670.     HALF  : FLOAT := ONE / TWO;
  671.  
  672. --  The following "constants" are effectively deferred to
  673. --  the initialization part of the package body
  674. --  This is in order to make it possible to generalize the floating type
  675. --  If that capability is not desired, constants may be included here
  676.     PI            : FLOAT;
  677.     ONE_OVER_PI   : FLOAT;
  678.     TWO_OVER_PI   : FLOAT;
  679.     PI_OVER_TWO   : FLOAT;
  680.     PI_OVER_THREE : FLOAT;
  681.     PI_OVER_FOUR  : FLOAT;
  682.     PI_OVER_SIX   : FLOAT;
  683.  
  684.  
  685.     function SIGN (X, Y : FLOAT) return FLOAT;
  686.     --  Returns the value of X with the sign of Y
  687.     function MAX (X, Y : FLOAT) return FLOAT;
  688.     --  Returns the algebraicly larger of X and Y
  689.     function TRUNCATE (X : FLOAT) return FLOAT;
  690.     --  Returns the floating value of the integer no larger than X
  691.     --  AINT(X)
  692.     function ROUND (X : FLOAT) return FLOAT;
  693.     --  Returns the floating value nearest X
  694.     --  AINTRND(X)
  695.     function RAN return FLOAT;
  696.     --  This uses a portable algorithm and is included at this point
  697.     --  Algorithms that presume unique machine hardware information
  698.     --  should be initiated in FLOATING_CHARACTERISTICS
  699.  
  700. end NUMERIC_PRIMITIVES;
  701.  
  702.  
  703.  
  704. with FLOATING_CHARACTERISTICS;
  705. use FLOATING_CHARACTERISTICS;
  706.  
  707. package body NUMERIC_PRIMITIVES is
  708.  
  709.  
  710.     function SIGN (X, Y : FLOAT) return FLOAT is
  711. --  Returns the value of X with the sign of Y
  712.     begin
  713.     if Y >= 0.0 then
  714.         return X;
  715.     else
  716.         return -X;
  717.     end if;
  718.     end SIGN;
  719.  
  720.     function MAX (X, Y : FLOAT) return FLOAT is
  721.     begin
  722.     if X >= Y then
  723.         return X;
  724.     else
  725.         return Y;
  726.     end if;
  727.     end MAX;
  728.  
  729.     function TRUNCATE (X : FLOAT) return FLOAT is
  730. --  Optimum code depends on how the system rounds at exact halves
  731.     begin
  732.     if FLOAT (INTEGER (X)) = X then
  733.         return X;
  734.     end if;
  735.  
  736.     if X > ZERO then
  737.         return FLOAT (INTEGER (X - HALF));
  738.  
  739.     elsif X = ZERO then
  740.         return ZERO;
  741.     else
  742.         return FLOAT (INTEGER (X + HALF));
  743.     end if;
  744.     end TRUNCATE;
  745.  
  746.     function ROUND (X : FLOAT) return FLOAT is
  747.     begin
  748.     return FLOAT (INTEGER (X));
  749.     end ROUND;
  750.  
  751.  
  752.     package KEY is
  753.     X : INTEGER := 10_001;
  754.     Y : INTEGER := 20_001;
  755.     Z : INTEGER := 30_001;
  756.     end KEY;
  757.  
  758.     function RAN return FLOAT is
  759. --  This rectangular random number routine is adapted from a report
  760. --  "A Pseudo-Random Number Generator" by B. A. Wichmann and I. D. Hill
  761. --  NPL Report DNACS XX (to be published)
  762. --  In this stripped version, it is suitable for machines supporting 
  763. --  INTEGER at only 16 bits and is portable in Ada
  764.     W : FLOAT;
  765.     begin
  766.  
  767.     KEY.X := 171 * (KEY.X mod 177 - 177) - 2 * (KEY.X / 177);
  768.  
  769.     if KEY.X < 0 then
  770.         KEY.X := KEY.X + 30269;
  771.     end if;
  772.  
  773.     KEY.Y := 172 * (KEY.Y mod 176 - 176) - 35 * (KEY.Y / 176);
  774.  
  775.     if KEY.Y < 0 then
  776.         KEY.Y := KEY.Y + 30307;
  777.     end if;
  778.  
  779.     KEY.Z := 170 * (KEY.Z mod 178 - 178) - 63 * (KEY.Z / 178);
  780.  
  781.     if KEY.Z < 0 then
  782.         KEY.Z := KEY.Z + 30323;
  783.     end if;
  784.  
  785.     --  CONVERT_TO_FLOAT is used instead of FLOAT since the floating
  786.     --  type may be software defined
  787.  
  788.     W := CONVERT_TO_FLOAT (KEY.X) / 30269.0 +
  789.          CONVERT_TO_FLOAT (KEY.Y) / 30307.0 +
  790.          CONVERT_TO_FLOAT (KEY.Z) / 30323.0;
  791.  
  792.     return W - CONVERT_TO_FLOAT (INTEGER (W - 0.5));
  793.  
  794.     end RAN;
  795.  
  796. begin
  797.     PI := CONVERT_TO_FLOAT (INTEGER (3)) +
  798.       CONVERT_TO_FLOAT (MANTISSA_TYPE (0.14159_26535_89793_23846));
  799.     ONE_OVER_PI := CONVERT_TO_FLOAT (MANTISSA_TYPE (0.31830_98861_83790_67154));
  800.     TWO_OVER_PI := CONVERT_TO_FLOAT (MANTISSA_TYPE (0.63661_97723_67581_34308));
  801.     PI_OVER_TWO := CONVERT_TO_FLOAT (INTEGER (1)) +
  802.            CONVERT_TO_FLOAT (MANTISSA_TYPE (0.57079_63267_94896_61923));
  803.     PI_OVER_THREE := CONVERT_TO_FLOAT (INTEGER (1)) +
  804.              CONVERT_TO_FLOAT
  805.             (MANTISSA_TYPE (0.04719_75511_96597_74615));
  806.     PI_OVER_FOUR := CONVERT_TO_FLOAT
  807.                (MANTISSA_TYPE (0.78539_81633_97448_30962));
  808.     PI_OVER_SIX := CONVERT_TO_FLOAT (MANTISSA_TYPE (0.52359_87755_98298_87308));
  809.  
  810. end NUMERIC_PRIMITIVES;
  811.  
  812.  
  813.  
  814.  
  815. with FLOATING_CHARACTERISTICS;
  816. use FLOATING_CHARACTERISTICS;
  817.  
  818. package CORE_FUNCTIONS is
  819.  
  820.     EXP_LARGE : FLOAT;
  821.     EXP_SMALL : FLOAT;
  822.  
  823.     function SQRT  (X : FLOAT) return FLOAT;
  824.     function CBRT  (X : FLOAT) return FLOAT;
  825.     function LOG   (X : FLOAT) return FLOAT;
  826.     function LOG10 (X : FLOAT) return FLOAT;
  827.     function EXP   (X : FLOAT) return FLOAT;
  828.     function "**"  (X, Y : FLOAT) return FLOAT;
  829.  
  830. end CORE_FUNCTIONS;
  831.  
  832.  
  833.  
  834.  
  835. with TEXT_IO;
  836. use TEXT_IO;
  837. with FLOATING_CHARACTERISTICS;
  838. use FLOATING_CHARACTERISTICS;
  839. with NUMERIC_IO;
  840. use NUMERIC_IO;
  841. with NUMERIC_PRIMITIVES;
  842. use NUMERIC_PRIMITIVES;
  843.  
  844. package body CORE_FUNCTIONS is
  845.  
  846. --  The following routines are coded directly from the algorithms and
  847. --  coeficients given in "Software Manual for the Elementry Functions"
  848. --  by William J. Cody, Jr. and William Waite, Prentice_Hall, 1980
  849. --  CBRT by analogy
  850. --  A more general formulation uses MANTISSA_TYPE, etc.
  851. --  The coeficients are appropriate for 25 to 32 bits floating significance
  852. --  They will work for less but slightly shorter versions are possible
  853. --  The routines are coded to stand alone so they need not be compiled together
  854.  
  855. --  These routines have been coded to accept a general MANTISSA_TYPE
  856. --  That is, they are designed to work with a manitssa either fixed of float
  857. --  There are some explicit conversions which are required but these will
  858. --  not cause any extra code to be generated
  859.  
  860. --      16 JULY 1982       W A WHITAKER  AFATL EGLIN AFB FL 32542
  861. --                         T C EICHOLTZ  USAFA
  862.  
  863.  
  864.     function SQRT (X : FLOAT) return FLOAT is
  865.     M, N   : EXPONENT_TYPE;
  866.     F, Y   : MANTISSA_TYPE;
  867.     RESULT : FLOAT;
  868.  
  869.     subtype INDEX is INTEGER range 0 .. 100; --  #########################
  870.     SQRT_L1 : INDEX := 3;
  871.     --  Could get away with SQRT_L1 := 2 for 28 bits
  872.     --  Using the better Cody-Waite coeficients overflows MANTISSA_TYPE
  873.     SQRT_C1 : MANTISSA_TYPE := 8#0.3317777777#;
  874.     SQRT_C2 : MANTISSA_TYPE := 8#0.4460000000#;
  875.     SQRT_C3 : MANTISSA_TYPE := 8#0.55202_36314_77747_36311_0#;
  876.  
  877.     begin
  878.     if X = ZERO then
  879.         RESULT := ZERO;
  880.         return RESULT;
  881.  
  882.     elsif X = ONE then
  883.         --  To get exact SQRT(1.0)
  884.         RESULT := ONE;
  885.         return RESULT;
  886.  
  887.     elsif X < ZERO then
  888.         NEW_LINE;
  889.         PUT ("CALLED SQRT FOR NEGATIVE ARGUMENT   ");
  890.         PUT (X);
  891.         PUT ("   USED ABSOLUTE VALUE");
  892.         NEW_LINE;
  893.         RESULT := SQRT (abs (X));
  894.         return RESULT;
  895.     else
  896.         DEFLOAT (X, N, F);
  897.         Y := SQRT_C1 + MANTISSA_TYPE (SQRT_C2 * F);
  898.  
  899.         for J in 1 .. SQRT_L1 loop
  900.         Y := Y / MANTISSA_DIVISOR_2 +
  901.              MANTISSA_TYPE ((F / MANTISSA_DIVISOR_2) / Y);
  902.         end loop;
  903.  
  904.         if (N mod 2) /= 0 then
  905.         Y := MANTISSA_TYPE (SQRT_C3 * Y);
  906.         N := N + 1;
  907.         end if;
  908.  
  909.         M := N / 2;
  910.         REFLOAT (M, Y, RESULT);
  911.         return RESULT;
  912.     end if;
  913.     exception
  914.     when others => 
  915.         NEW_LINE;  PUT (" EXCEPTION IN SQRT, X = ");  PUT (X);
  916.         PUT ("  RETURNED 1.0");  NEW_LINE;
  917.         return ONE;
  918.     end SQRT;
  919.  
  920.  
  921.     function CBRT (X : FLOAT) return FLOAT is
  922.     M, N   : EXPONENT_TYPE;
  923.     F, Y   : MANTISSA_TYPE;
  924.     RESULT : FLOAT;
  925.  
  926.     subtype INDEX is INTEGER range 0 .. 100; --  #########################
  927.     CBRT_L1 : INDEX := 3;
  928.     CBRT_C1 : MANTISSA_TYPE := 0.5874009;
  929.     CBRT_C2 : MANTISSA_TYPE := 0.4125990;
  930.     CBRT_C3 : MANTISSA_TYPE := 0.62996_05249;
  931.     CBRT_C4 : MANTISSA_TYPE := 0.79370_05260;
  932.  
  933.     begin
  934.     if X = ZERO then
  935.         RESULT := ZERO;
  936.         return RESULT;
  937.     else
  938.         DEFLOAT (X, N, F);
  939.         F := abs (F);
  940.         Y := CBRT_C1 + MANTISSA_TYPE (CBRT_C2 * F);
  941.  
  942.         for J in 1 .. CBRT_L1 loop
  943.         Y := Y -
  944.              (Y / MANTISSA_DIVISOR_3 -
  945.               MANTISSA_TYPE
  946.              ((F / MANTISSA_DIVISOR_3) / MANTISSA_TYPE (Y * Y)));
  947.         end loop;
  948.  
  949.         case (N mod 3) is
  950.         when 0 => 
  951.             null;
  952.  
  953.         when 1 => 
  954.             Y := MANTISSA_TYPE (CBRT_C3 * Y);
  955.             N := N + 2;
  956.  
  957.         when 2 => 
  958.             Y := MANTISSA_TYPE (CBRT_C4 * Y);
  959.             N := N + 1;
  960.  
  961.         when others => 
  962.             null;
  963.         end case;
  964.  
  965.         M := N / 3;
  966.  
  967.         if X < ZERO then
  968.         Y := -Y;
  969.         end if;
  970.  
  971.         REFLOAT (M, Y, RESULT);
  972.         return RESULT;
  973.     end if;
  974.     exception
  975.     when others => 
  976.         RESULT := ONE;
  977.  
  978.         if X < ZERO then
  979.         RESULT := -ONE;
  980.         end if;
  981.  
  982.         NEW_LINE;  PUT ("EXCEPTION IN CBRT, X = ");  PUT (X);
  983.         PUT ("  RETURNED  ");  PUT (RESULT);  NEW_LINE;
  984.         return RESULT;
  985.     end CBRT;
  986.  
  987.     function LOG (X : FLOAT) return FLOAT is
  988. --  Uses fixed formulation for generality
  989.  
  990.     RESULT        : FLOAT;
  991.     N             : EXPONENT_TYPE;
  992.     XN            : FLOAT;
  993.     Y             : FLOAT;
  994.     F             : MANTISSA_TYPE;
  995.     Z, ZDEN, ZNUM : MANTISSA_TYPE;
  996.  
  997.     C0            : constant MANTISSA_TYPE := 0.20710_67811_86547_52440;
  998.     --  SQRT(0.5) - 0.5
  999.     C1 : constant FLOAT := 8#0.543#;
  1000.     C2 : constant FLOAT := -2.12194_44005_46905_82767_9E-4;
  1001.  
  1002.     function R (Z : MANTISSA_TYPE) return MANTISSA_TYPE is
  1003. --  Use fixed formulation here because the float coeficents are > 1.0
  1004. --  and would exceed the limits on a MANTISSA_TYPE
  1005.         A0 : constant MANTISSA_TYPE := 0.04862_85276_587;
  1006.         B0 : constant MANTISSA_TYPE := 0.69735_92187_803;
  1007.         B1 : constant MANTISSA_TYPE := -0.125;
  1008.         C  : constant MANTISSA_TYPE := 0.01360_09546_862;
  1009.     begin
  1010.         return Z +
  1011.            MANTISSA_TYPE
  1012.               (Z *
  1013.                MANTISSA_TYPE
  1014.               (MANTISSA_TYPE (Z * Z) *
  1015.                (C +
  1016.                 MANTISSA_TYPE
  1017.                    (A0 /
  1018.                 (B0 +
  1019.                  MANTISSA_TYPE
  1020.                     (B1 * MANTISSA_TYPE (Z * Z)))))));
  1021.     end R;
  1022.  
  1023.     begin
  1024.  
  1025.     if X < ZERO then
  1026.         NEW_LINE;
  1027.         PUT ("CALLED LOG FOR NEGATIVE ");
  1028.         PUT (X);
  1029.         PUT ("   USE ABS => ");
  1030.         RESULT := LOG (abs (X));
  1031.         PUT (RESULT);
  1032.         NEW_LINE;
  1033.  
  1034.     elsif X = ZERO then
  1035.         NEW_LINE;
  1036.         PUT ("CALLED LOG FOR ZERO ARGUMENT, RETURNED ");
  1037.         RESULT := -XMAX; --  SUPPOSED TO BE -LARGE
  1038.         PUT (RESULT);
  1039.         NEW_LINE;
  1040.     else
  1041.         DEFLOAT (X, N, F);
  1042.         ZNUM := F - MANTISSA_HALF;
  1043.         Y := CONVERT_TO_FLOAT (ZNUM);
  1044.         ZDEN := ZNUM / MANTISSA_DIVISOR_2 + MANTISSA_HALF;
  1045.  
  1046.         if ZNUM > C0 then
  1047.         Y := Y - MANTISSA_HALF;
  1048.         ZNUM := ZNUM - MANTISSA_HALF;
  1049.         ZDEN := ZDEN + MANTISSA_HALF / MANTISSA_DIVISOR_2;
  1050.         else
  1051.         N := N - 1;
  1052.         end if;
  1053.  
  1054.         Z := MANTISSA_TYPE (ZNUM / ZDEN);
  1055.         RESULT := CONVERT_TO_FLOAT (R (Z));
  1056.  
  1057.         if N /= 0 then
  1058.         XN := CONVERT_TO_FLOAT (N);
  1059.         RESULT := (XN * C2 + RESULT) + XN * C1;
  1060.         end if;
  1061.     end if;
  1062.  
  1063.     return RESULT;
  1064.  
  1065.     exception
  1066.     when others => 
  1067.         NEW_LINE;  PUT (" EXCEPTION IN LOG, X = ");  PUT (X);
  1068.         PUT ("  RETURNED 0.0");  NEW_LINE;
  1069.         return ZERO;
  1070.     end LOG;
  1071.  
  1072.  
  1073.     function LOG10 (X : FLOAT) return FLOAT is
  1074.     LOG_10_OF_2 : constant FLOAT :=
  1075.               CONVERT_TO_FLOAT
  1076.              (MANTISSA_TYPE (8#0.33626_75425_11562_41615#));
  1077.     begin
  1078.     return LOG (X) * LOG_10_OF_2;
  1079.     end LOG10;
  1080.  
  1081.     function EXP (X : FLOAT) return FLOAT is
  1082.  
  1083.     RESULT         : FLOAT;
  1084.     N              : EXPONENT_TYPE;
  1085.     XG, XN, X1, X2 : FLOAT;
  1086.     F, G           : MANTISSA_TYPE;
  1087.  
  1088.     BIGX           : FLOAT := EXP_LARGE;
  1089.     SMALLX         : FLOAT := EXP_SMALL;
  1090.  
  1091.     ONE_OVER_LOG_2 : constant FLOAT := 1.4426_95040_88896_34074;
  1092.     C1             : constant FLOAT := 0.69335_9375;
  1093.     C2             : constant FLOAT := -2.1219_44400_54690_58277E-4;
  1094.  
  1095.     function R (G : MANTISSA_TYPE) return MANTISSA_TYPE is
  1096.         Z, GP, Q : MANTISSA_TYPE;
  1097.  
  1098.         P0       : constant MANTISSA_TYPE := 0.24999_99999_9992;
  1099.         P1       : constant MANTISSA_TYPE := 0.00595_04254_9776;
  1100.         Q0       : constant MANTISSA_TYPE := 0.5;
  1101.         Q1       : constant MANTISSA_TYPE := 0.05356_75176_4522;
  1102.         Q2       : constant MANTISSA_TYPE := 0.00029_72936_3682;
  1103.     begin
  1104.         Z := MANTISSA_TYPE (G * G);
  1105.         GP := MANTISSA_TYPE ((MANTISSA_TYPE (P1 * Z) + P0) * G);
  1106.         Q := MANTISSA_TYPE ((MANTISSA_TYPE (Q2 * Z) + Q1) * Z) + Q0;
  1107.         return MANTISSA_HALF + MANTISSA_TYPE (GP / (Q - GP));
  1108.     end R;
  1109.  
  1110.  
  1111.     begin
  1112.  
  1113.     if X > BIGX then
  1114.         NEW_LINE;
  1115.         PUT ("  EXP CALLED WITH TOO BIG A POSITIVE ARGUMENT, ");
  1116.         PUT (X);  PUT ("   RETURNED XMAX");
  1117.         NEW_LINE;
  1118.         RESULT := XMAX;
  1119.  
  1120.     elsif X < SMALLX then
  1121.         NEW_LINE;
  1122.         PUT ("  EXP CALLED WITH TOO BIG A NEGATIVE ARGUMENT,  ");
  1123.         PUT (X);  PUT ("    RETURNED ZERO");
  1124.         NEW_LINE;
  1125.         RESULT := ZERO;
  1126.  
  1127.     elsif abs (X) < EPS then
  1128.         RESULT := ONE;
  1129.     else
  1130.         N := EXPONENT_TYPE (X * ONE_OVER_LOG_2);
  1131.         XN := CONVERT_TO_FLOAT (N);
  1132.         X1 := ROUND (X);
  1133.         X2 := X - X1;
  1134.         XG := ((X1 - XN * C1) + X2) - XN * C2;
  1135.         G := MANTISSA_TYPE (XG);
  1136.         N := N + 1;
  1137.         F := R (G);
  1138.         REFLOAT (N, F, RESULT);
  1139.     end if;
  1140.  
  1141.     return RESULT;
  1142.  
  1143.     exception
  1144.     when others => 
  1145.         NEW_LINE;  PUT (" EXCEPTION IN EXP, X = ");  PUT (X);
  1146.         PUT ("  RETURNED 1.0");  NEW_LINE;
  1147.         return ONE;
  1148.     end EXP;
  1149.  
  1150.     function "**" (X, Y : FLOAT) return FLOAT is
  1151. --  This is the last function to be coded since it appeared that it really
  1152. --  was un-Ada-like and ought not be in the regular package
  1153. --  Nevertheless it was included in this version
  1154. --  It is specific for FLOAT and does not have the MANTISSA_TYPE generality
  1155.     M, N                                           : EXPONENT_TYPE;
  1156.     G                                              : MANTISSA_TYPE;
  1157.     P, TEMP, IW1, I                                : INTEGER;
  1158.     RESULT, Z, V, R, U1, U2, W, W1, W2, W3, Y1, Y2 : FLOAT;
  1159.  
  1160.     K                                              : constant FLOAT :=
  1161.                              0.44269_50408_88963_40736;
  1162.     IBIGX                                          : constant INTEGER :=
  1163.                              INTEGER (TRUNCATE (16.0 *
  1164.                                         LOG (XMAX) -
  1165.                                         1.0));
  1166.     ISMALLX                                        : constant INTEGER :=
  1167.                              INTEGER (TRUNCATE (16.0 *
  1168.                                         LOG (XMIN) +
  1169.                                         1.0));
  1170.  
  1171.     P1                                             : constant FLOAT :=
  1172.                              0.83333_32862_45E-1;
  1173.     P2                                             : constant FLOAT :=
  1174.                              0.12506_48500_52E-1;
  1175.  
  1176.     Q1                                             : constant FLOAT :=
  1177.                              0.69314_71805_56341;
  1178.     Q2                                             : constant FLOAT :=
  1179.                              0.24022_65061_44710;
  1180.     Q3                                             : constant FLOAT :=
  1181.                              0.55504_04881_30765E-1;
  1182.     Q4                                             : constant FLOAT :=
  1183.                              0.96162_06595_83789E-2;
  1184.     Q5                                             : constant FLOAT :=
  1185.                              0.13052_55159_42810E-2;
  1186.  
  1187.     A1                                             : array (1 .. 17)
  1188.                                     of FLOAT :=
  1189.                              (8#1.00000_0000#,
  1190.                               8#0.75222_5750#,
  1191.                               8#0.72540_3067#,
  1192.                               8#0.70146_3367#,
  1193.                               8#0.65642_3746#,
  1194.                               8#0.63422_2140#,
  1195.                               8#0.61263_4520#,
  1196.                               8#0.57204_2434#,
  1197.                               8#0.55202_3631#,
  1198.                               8#0.53254_0767#,
  1199.                               8#0.51377_3265#,
  1200.                               8#0.47572_4623#,
  1201.                               8#0.46033_7602#,
  1202.                               8#0.44341_7233#,
  1203.                               8#0.42712_7017#,
  1204.                               8#0.41325_3033#,
  1205.                               8#0.40000_0000#);
  1206.  
  1207.     A2                                             : array (1 .. 8)
  1208.                                     of FLOAT :=
  1209.                              (8#0.00000_00005_22220_66302_61734_72062#,
  1210.                               8#0.00000_00003_02522_47021_04062_61124#,
  1211.                               8#0.00000_00005_21760_44016_17421_53016#,
  1212.                               8#0.00000_00007_65401_41553_72504_02177#,
  1213.                               8#0.00000_00002_44124_12254_31114_01243#,
  1214.                               8#0.00000_00000_11064_10432_66404_42174#,
  1215.                               8#0.00000_00004_72542_16063_30176_55544#,
  1216.                               8#0.00000_00001_74611_03661_23056_22556#);
  1217.  
  1218.  
  1219.     function REDUCE (V : FLOAT) return FLOAT is
  1220.     begin
  1221.         return FLOAT (INTEGER (16.0 * V)) * 0.0625;
  1222.     end REDUCE;
  1223.  
  1224.     begin
  1225.     if X <= ZERO then
  1226.         if X < ZERO then
  1227.         RESULT := (abs (X)) ** Y;
  1228.         NEW_LINE;
  1229.         PUT ("X**Y CALLED WITH X = ");  PUT (X);  NEW_LINE;
  1230.         PUT ("USED ABS, RETURNED ");  PUT (RESULT);  NEW_LINE;
  1231.         else
  1232.         if Y <= ZERO then
  1233.             if Y = ZERO then
  1234.             RESULT := ZERO;
  1235.             else
  1236.             RESULT := XMAX;
  1237.             end if;
  1238.  
  1239.             NEW_LINE;
  1240.             PUT ("X**Y CALLED WITH X = 0, Y = ");  PUT (Y);  NEW_LINE;
  1241.             PUT ("RETURNED ");  PUT (RESULT);  NEW_LINE;
  1242.         else
  1243.             RESULT := ZERO;
  1244.         end if;
  1245.         end if;
  1246.     else
  1247.         DEFLOAT (X, M, G);
  1248.         P := 1;
  1249.  
  1250.         if G <= A1 (9) then
  1251.         P := 9;
  1252.         end if;
  1253.  
  1254.         if G <= A1 (P + 4) then
  1255.         P := P + 4;
  1256.         end if;
  1257.  
  1258.         if G <= A1 (P + 2) then
  1259.         P := P + 2;
  1260.         end if;
  1261.  
  1262.         Z := ((G - A1 (P + 1)) - A2 ((P + 1) / 2)) / (G + A1 (P + 1));
  1263.         Z := Z + Z;
  1264.         V := Z * Z;
  1265.         R := (P2 * V + P1) * V * Z;
  1266.         R := R + K * R;
  1267.         U2 := (R + Z * K) + Z;
  1268.         U1 := FLOAT (INTEGER (M) * 16 - P) * 0.0625;
  1269.         Y1 := REDUCE (Y);
  1270.         Y2 := Y - Y1;
  1271.         W := U2 * Y + U1 * Y2;
  1272.         W1 := REDUCE (W);
  1273.         W2 := W - W1;
  1274.         W := W1 + U1 * Y1;
  1275.         W1 := REDUCE (W);
  1276.         W2 := W2 + (W - W1);
  1277.         W3 := REDUCE (W2);
  1278.         IW1 := INTEGER (TRUNCATE (16.0 * (W1 + W3)));
  1279.         W2 := W2 - W3;
  1280.  
  1281.         if W > FLOAT (IBIGX) then
  1282.         RESULT := XMAX;
  1283.         PUT ("X**Y CALLED  X =");  PUT (X);  PUT ("   Y =");  PUT (Y);
  1284.         PUT ("   TOO LARGE  RETURNED ");  PUT (RESULT);  NEW_LINE;
  1285.  
  1286.         elsif W < FLOAT (ISMALLX) then
  1287.         RESULT := ZERO;
  1288.         PUT ("X**Y CALLED  X =");  PUT (X);  PUT ("   Y =");  PUT (Y);
  1289.         PUT ("   TOO SMALL  RETURNED ");  PUT (RESULT);  NEW_LINE;
  1290.         else
  1291.         if W2 > ZERO then
  1292.             W2 := W2 - 0.0625;
  1293.             IW1 := IW1 + 1;
  1294.         end if;
  1295.  
  1296.         if IW1 < INTEGER (ZERO) then
  1297.             I := 0;
  1298.         else
  1299.             I := 1;
  1300.         end if;
  1301.  
  1302.         M := EXPONENT_TYPE (I + IW1 / 16);
  1303.         P := 16 * INTEGER (M) - IW1;
  1304.         Z := ((((Q5 * W2 + Q4) * W2 + Q3) * W2 + Q2) * W2 + Q1) * W2;
  1305.         Z := A1 (P + 1) + (A1 (P + 1) * Z);
  1306.  
  1307.         REFLOAT (M, Z, RESULT);
  1308.         end if;
  1309.     end if;
  1310.  
  1311.     return RESULT;
  1312.     end "**";
  1313.  
  1314. begin
  1315.     EXP_LARGE := LOG (XMAX) * (ONE - EPS);
  1316.     EXP_SMALL := LOG (XMIN) * (ONE - EPS);
  1317. end CORE_FUNCTIONS;
  1318.  
  1319.  
  1320.  
  1321.  
  1322. package TRIG_FUNCTIONS is
  1323.     function SIN   (X : FLOAT) return FLOAT;
  1324.     function COS   (X : FLOAT) return FLOAT;
  1325.     function TAN   (X : FLOAT) return FLOAT;
  1326.     function COT   (X : FLOAT) return FLOAT;
  1327.     function ASIN  (X : FLOAT) return FLOAT;
  1328.     function ACOS  (X : FLOAT) return FLOAT;
  1329.     function ATAN  (X : FLOAT) return FLOAT;
  1330.     function ATAN2 (V, U : FLOAT) return FLOAT;
  1331.     function SINH  (X : FLOAT) return FLOAT;
  1332.     function COSH  (X : FLOAT) return FLOAT;
  1333.     function TANH  (X : FLOAT) return FLOAT;
  1334. end TRIG_FUNCTIONS;
  1335.  
  1336.  
  1337.  
  1338.  
  1339.  
  1340. with TEXT_IO;
  1341. use TEXT_IO;
  1342. with FLOATING_CHARACTERISTICS;
  1343. use FLOATING_CHARACTERISTICS;
  1344. with NUMERIC_IO;
  1345. use NUMERIC_IO;
  1346. with NUMERIC_PRIMITIVES;
  1347. use NUMERIC_PRIMITIVES;
  1348. with CORE_FUNCTIONS;
  1349. use CORE_FUNCTIONS;
  1350.  
  1351. package body TRIG_FUNCTIONS is
  1352.  
  1353. --  PRELIMINARY VERSION *********************************
  1354.  
  1355. --  The following routines are coded directly from the algorithms and
  1356. --  coeficients given in "Software Manual for the Elementry Functions"
  1357. --  by William J. Cody, Jr. and William Waite, Prentice_Hall, 1980
  1358. --  This particular version is stripped to work with FLOAT and INTEGER
  1359. --  and uses a mantissa represented as a FLOAT
  1360. --  A more general formulation uses MANTISSA_TYPE, etc.
  1361. --  The coeficients are appropriate for 25 to 32 bits floating significance
  1362. --  They will work for less but slightly shorter versions are possible
  1363. --  The routines are coded to stand alone so they need not be compiled together
  1364.  
  1365. --      16 JULY 1982       W A WHITAKER  AFATL EGLIN AFB FL 32542
  1366. --                         T C EICHOLTZ  USAFA
  1367.  
  1368.  
  1369.     function SIN (X : FLOAT) return FLOAT is
  1370.     SGN, Y       : FLOAT;
  1371.     N            : INTEGER;
  1372.     XN           : FLOAT;
  1373.     F, G, X1, X2 : FLOAT;
  1374.     RESULT       : FLOAT;
  1375.  
  1376.     YMAX         : FLOAT := FLOAT (INTEGER (PI * TWO ** (IT / 2)));
  1377.     BETA         : FLOAT := CONVERT_TO_FLOAT (IBETA);
  1378.     EPSILON      : FLOAT := BETA ** (-IT / 2);
  1379.  
  1380.     C1           : constant FLOAT := 3.140625;
  1381.     C2           : constant FLOAT := 9.6765_35897_93E-4;
  1382.  
  1383.     function R (G : FLOAT) return FLOAT is
  1384.         R1 : constant FLOAT := -0.16666_66660_883;
  1385.         R2 : constant FLOAT := 0.83333_30720_556E-2;
  1386.         R3 : constant FLOAT := -0.19840_83282_313E-3;
  1387.         R4 : constant FLOAT := 0.27523_97106_775E-5;
  1388.         R5 : constant FLOAT := -0.23868_34640_601E-7;
  1389.     begin
  1390.         return ((((R5 * G + R4) * G + R3) * G + R2) * G + R1) * G;
  1391.     end R;
  1392.  
  1393.     begin
  1394.     if X < ZERO then
  1395.         SGN := -ONE;
  1396.         Y := -X;
  1397.     else
  1398.         SGN := ONE;
  1399.         Y := X;
  1400.     end if;
  1401.  
  1402.     if Y > YMAX then
  1403.         NEW_LINE;
  1404.         PUT (" SIN CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1405.         PUT (X);  NEW_LINE;
  1406.     end if;
  1407.  
  1408.     N := INTEGER (Y * ONE_OVER_PI);
  1409.     XN := CONVERT_TO_FLOAT (N);
  1410.  
  1411.     if N mod 2 /= 0 then
  1412.         SGN := -SGN;
  1413.     end if;
  1414.  
  1415.     X1 := TRUNCATE (abs (X));
  1416.     X2 := abs (X) - X1;
  1417.     F := ((X1 - XN * C1) + X2) - XN * C2;
  1418.  
  1419.     if abs (F) < EPSILON then
  1420.         RESULT := F;
  1421.     else
  1422.         G := F * F;
  1423.         RESULT := F + F * R (G);
  1424.     end if;
  1425.  
  1426.     return (SGN * RESULT);
  1427.     end SIN;
  1428.  
  1429.  
  1430.     function COS (X : FLOAT) return FLOAT is
  1431.     SGN, Y       : FLOAT;
  1432.     N            : INTEGER;
  1433.     XN           : FLOAT;
  1434.     F, G, X1, X2 : FLOAT;
  1435.     RESULT       : FLOAT;
  1436.  
  1437.     YMAX         : FLOAT := FLOAT (INTEGER (PI * TWO ** (IT / 2)));
  1438.     BETA         : FLOAT := CONVERT_TO_FLOAT (IBETA);
  1439.     EPSILON      : FLOAT := BETA ** (-IT / 2);
  1440.  
  1441.     C1           : constant FLOAT := 3.140625;
  1442.     C2           : constant FLOAT := 9.6765_35897_93E-4;
  1443.  
  1444.     function R (G : FLOAT) return FLOAT is
  1445.         R1 : constant FLOAT := -0.16666_66660_883;
  1446.         R2 : constant FLOAT := 0.83333_30720_556E-2;
  1447.         R3 : constant FLOAT := -0.19840_83282_313E-3;
  1448.         R4 : constant FLOAT := 0.27523_97106_775E-5;
  1449.         R5 : constant FLOAT := -0.23868_34640_601E-7;
  1450.     begin
  1451.         return ((((R5 * G + R4) * G + R3) * G + R2) * G + R1) * G;
  1452.     end R;
  1453.  
  1454.     begin
  1455.     SGN := 1.0;
  1456.     Y := abs (X) + PI_OVER_TWO;
  1457.  
  1458.     if Y > YMAX then
  1459.         NEW_LINE;
  1460.         PUT (" COS CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1461.         PUT (X);  NEW_LINE;
  1462.     end if;
  1463.  
  1464.     N := INTEGER (Y * ONE_OVER_PI);
  1465.     XN := CONVERT_TO_FLOAT (N);
  1466.  
  1467.     if N mod 2 /= 0 then
  1468.         SGN := -SGN;
  1469.     end if;
  1470.  
  1471.     XN := XN - 0.5;      -- TO FORM COS INSTEAD OF SIN
  1472.     X1 := TRUNCATE (abs (X));
  1473.     X2 := abs (X) - X1;
  1474.     F := ((X1 - XN * C1) + X2) - XN * C2;
  1475.  
  1476.     if abs (F) < EPSILON then
  1477.         RESULT := F;
  1478.     else
  1479.         G := F * F;
  1480.         RESULT := F + F * R (G);
  1481.     end if;
  1482.  
  1483.     return (SGN * RESULT);
  1484.     end COS;
  1485.  
  1486.  
  1487.     function TAN (X : FLOAT) return FLOAT is
  1488.     SGN, Y       : FLOAT;
  1489.     N            : INTEGER;
  1490.     XN           : FLOAT;
  1491.     F, G, X1, X2 : FLOAT;
  1492.     RESULT       : FLOAT;
  1493.  
  1494.     YMAX         : FLOAT := FLOAT (INTEGER (PI * TWO ** (IT / 2))) / 2.0;
  1495.     BETA         : FLOAT := CONVERT_TO_FLOAT (IBETA);
  1496.     EPSILON      : FLOAT := BETA ** (-IT / 2);
  1497.  
  1498.     C1           : constant FLOAT := 8#1.444#;
  1499.     C2           : constant FLOAT := 4.8382_67948_97E-4;
  1500.  
  1501.     function R (G : FLOAT) return FLOAT is
  1502.         P0 : constant FLOAT := 1.0;
  1503.         P1 : constant FLOAT := -0.11136_14403_566;
  1504.         P2 : constant FLOAT := 0.10751_54738_488E-2;
  1505.         Q0 : constant FLOAT := 1.0;
  1506.         Q1 : constant FLOAT := -0.44469_47720_281;
  1507.         Q2 : constant FLOAT := 0.15973_39213_300E-1;
  1508.     begin
  1509.         return ((P2 * G + P1) * G * F + F) /
  1510.            (((Q2 * G + Q1) * G + 0.5) + 0.5);
  1511.     end R;
  1512.  
  1513.     begin
  1514.     Y := abs (X);
  1515.  
  1516.     if Y > YMAX then
  1517.         NEW_LINE;
  1518.         PUT (" TAN CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1519.         PUT (X);  NEW_LINE;
  1520.     end if;
  1521.  
  1522.     N := INTEGER (X * TWO_OVER_PI);
  1523.     XN := CONVERT_TO_FLOAT (N);
  1524.     X1 := TRUNCATE (X);
  1525.     X2 := X - X1;
  1526.     F := ((X1 - XN * C1) + X2) - XN * C2;
  1527.  
  1528.     if abs (F) < EPSILON then
  1529.         RESULT := F;
  1530.     else
  1531.         G := F * F;
  1532.         RESULT := R (G);
  1533.     end if;
  1534.  
  1535.     if N mod 2 = 0 then
  1536.         return RESULT;
  1537.     else
  1538.         return -1.0 / RESULT;
  1539.     end if;
  1540.     end TAN;
  1541.  
  1542.     function COT (X : FLOAT) return FLOAT is
  1543.     SGN, Y       : FLOAT;
  1544.     N            : INTEGER;
  1545.     XN           : FLOAT;
  1546.     F, G, X1, X2 : FLOAT;
  1547.     RESULT       : FLOAT;
  1548.  
  1549.  
  1550.     YMAX     : FLOAT := FLOAT (INTEGER (PI * TWO ** (IT / 2))) / 2.0;
  1551.     BETA     : FLOAT := CONVERT_TO_FLOAT (IBETA);
  1552.     EPSILON  : FLOAT := BETA ** (-IT / 2);
  1553.     EPSILON1 : FLOAT := 1.0 / XMAX;
  1554.  
  1555.     C1       : constant FLOAT := 8#1.444#;
  1556.     C2       : constant FLOAT := 4.8382_67948_97E-4;
  1557.  
  1558.     function R (G : FLOAT) return FLOAT is
  1559.         P0 : constant FLOAT := 1.0;
  1560.         P1 : constant FLOAT := -0.11136_14403_566;
  1561.         P2 : constant FLOAT := 0.10751_54738_488E-2;
  1562.         Q0 : constant FLOAT := 1.0;
  1563.         Q1 : constant FLOAT := -0.44469_47720_281;
  1564.         Q2 : constant FLOAT := 0.15973_39213_300E-1;
  1565.     begin
  1566.         return ((P2 * G + P1) * G * F + F) /
  1567.            (((Q2 * G + Q1) * G + 0.5) + 0.5);
  1568.     end R;
  1569.  
  1570.     begin
  1571.     Y := abs (X);
  1572.  
  1573.     if Y < EPSILON1 then
  1574.         NEW_LINE;
  1575.         PUT (" COT CALLED WITH ARGUMENT TOO NEAR ZERO ");
  1576.         PUT (X);  NEW_LINE;
  1577.  
  1578.         if X < 0.0 then
  1579.         return -XMAX;
  1580.         else
  1581.         return XMAX;
  1582.         end if;
  1583.     end if;
  1584.  
  1585.     if Y > YMAX then
  1586.         NEW_LINE;
  1587.         PUT (" COT CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1588.         PUT (X);  NEW_LINE;
  1589.     end if;
  1590.  
  1591.     N := INTEGER (X * TWO_OVER_PI);
  1592.     XN := CONVERT_TO_FLOAT (N);
  1593.     X1 := TRUNCATE (X);
  1594.     X2 := X - X1;
  1595.     F := ((X1 - XN * C1) + X2) - XN * C2;
  1596.  
  1597.     if abs (F) < EPSILON then
  1598.         RESULT := F;
  1599.     else
  1600.         G := F * F;
  1601.         RESULT := R (G);
  1602.     end if;
  1603.  
  1604.     if N mod 2 /= 0 then
  1605.         return -RESULT;
  1606.     else
  1607.         return 1.0 / RESULT;
  1608.     end if;
  1609.     end COT;
  1610.  
  1611.  
  1612.     function ASIN (X : FLOAT) return FLOAT is
  1613.     G, Y    : FLOAT;
  1614.     RESULT  : FLOAT;
  1615.     BETA    : FLOAT := CONVERT_TO_FLOAT (IBETA);
  1616.     EPSILON : FLOAT := BETA ** (-IT / 2);
  1617.  
  1618.     function R (G : FLOAT) return FLOAT is
  1619.         P1 : constant FLOAT := -0.27516_55529_0596E1;
  1620.         P2 : constant FLOAT := 0.29058_76237_4859E1;
  1621.         P3 : constant FLOAT := -0.59450_14419_3246;
  1622.         Q0 : constant FLOAT := -0.16509_93320_2424E2;
  1623.         Q1 : constant FLOAT := 0.24864_72896_9164E2;
  1624.         Q2 : constant FLOAT := -0.10333_86707_2113E2;
  1625.         Q3 : constant FLOAT := 1.0;
  1626.     begin
  1627.         return (((P3 * G + P2) * G + P1) * G) /
  1628.            (((G + Q2) * G + Q1) * G + Q0);
  1629.     end R;
  1630.  
  1631.     begin
  1632.     Y := abs (X);
  1633.  
  1634.     if Y > HALF then
  1635.         if Y > 1.0 then
  1636.         NEW_LINE;  PUT (" ASIN CALLED FOR ");  PUT (X);
  1637.         PUT (" (> 1)  TRUNCATED TO 1, CONTINUED");  NEW_LINE;
  1638.         Y := 1.0;
  1639.         end if;
  1640.  
  1641.         G := ((0.5 - Y) + 0.5) / 2.0;
  1642.         Y := -2.0 * SQRT (G);
  1643.         RESULT := Y + Y * R (G);
  1644.         RESULT := (PI_OVER_FOUR + RESULT) + PI_OVER_FOUR;
  1645.     else
  1646.         if Y < EPSILON then
  1647.         RESULT := Y;
  1648.         else
  1649.         G := Y * Y;
  1650.         RESULT := Y + Y * R (G);
  1651.         end if;
  1652.     end if;
  1653.  
  1654.     if X < 0.0 then
  1655.         RESULT := -RESULT;
  1656.     end if;
  1657.  
  1658.     return RESULT;
  1659.     end ASIN;
  1660.  
  1661.     function ACOS (X : FLOAT) return FLOAT is
  1662.     G, Y    : FLOAT;
  1663.     RESULT  : FLOAT;
  1664.     BETA    : FLOAT := CONVERT_TO_FLOAT (IBETA);
  1665.     EPSILON : FLOAT := BETA ** (-IT / 2);
  1666.  
  1667.     function R (G : FLOAT) return FLOAT is
  1668.         P1 : constant FLOAT := -0.27516_55529_0596E1;
  1669.         P2 : constant FLOAT := 0.29058_76237_4859E1;
  1670.         P3 : constant FLOAT := -0.59450_14419_3246;
  1671.         Q0 : constant FLOAT := -0.16509_93320_2424E2;
  1672.         Q1 : constant FLOAT := 0.24864_72896_9164E2;
  1673.         Q2 : constant FLOAT := -0.10333_86707_2113E2;
  1674.         Q3 : constant FLOAT := 1.0;
  1675.     begin
  1676.         return (((P3 * G + P2) * G + P1) * G) /
  1677.            (((G + Q2) * G + Q1) * G + Q0);
  1678.     end R;
  1679.  
  1680.     begin
  1681.     Y := abs (X);
  1682.  
  1683.     if Y > HALF then
  1684.         if Y > 1.0 then
  1685.         NEW_LINE;  PUT (" ACOS CALLED FOR ");  PUT (X);
  1686.         PUT (" (> 1)  TRUNCATED TO 1, CONTINUED");  NEW_LINE;
  1687.         Y := 1.0;
  1688.         end if;
  1689.  
  1690.         G := ((0.5 - Y) + 0.5) / 2.0;
  1691.         Y := -2.0 * SQRT (G);
  1692.         RESULT := Y + Y * R (G);
  1693.  
  1694.         if X < 0.0 then
  1695.         RESULT := (PI_OVER_TWO + RESULT) + PI_OVER_TWO;
  1696.         else
  1697.         RESULT := -RESULT;
  1698.         end if;
  1699.  
  1700.     else
  1701.         if Y < EPSILON then
  1702.         RESULT := Y;
  1703.         else
  1704.         G := Y * Y;
  1705.         RESULT := Y + Y * R (G);
  1706.         end if;
  1707.  
  1708.         if X < 0.0 then
  1709.         RESULT := (PI_OVER_FOUR + RESULT) + PI_OVER_FOUR;
  1710.         else
  1711.         RESULT := (PI_OVER_FOUR - RESULT) + PI_OVER_FOUR;
  1712.         end if;
  1713.     end if;
  1714.  
  1715.     return RESULT;
  1716.     end ACOS;
  1717.  
  1718.  
  1719.     function ATAN (X : FLOAT) return FLOAT is
  1720.     F, G : FLOAT;
  1721.  
  1722.     subtype REGION is INTEGER range 0 .. 3; --  ##########
  1723.     N                : REGION;
  1724.     RESULT           : FLOAT;
  1725.  
  1726.     BETA             : FLOAT := CONVERT_TO_FLOAT (IBETA);
  1727.  
  1728.     EPSILON          : FLOAT := BETA ** (-IT / 2);
  1729.  
  1730.     SQRT_3           : constant FLOAT := 1.73205_08075_68877_29353;
  1731.     SQRT_3_MINUS_1   : constant FLOAT := 0.73205_08075_68877_29353;
  1732.     TWO_MINUS_SQRT_3 : constant FLOAT := 0.26794_91924_31122_70647;
  1733.  
  1734.     function R (G : FLOAT) return FLOAT is
  1735.         P0 : constant FLOAT := -0.14400_83448_74E1;
  1736.         P1 : constant FLOAT := -0.72002_68488_98;
  1737.         Q0 : constant FLOAT := 0.43202_50389_19E1;
  1738.         Q1 : constant FLOAT := 0.47522_25845_99E1;
  1739.         Q2 : constant FLOAT := 1.0;
  1740.     begin
  1741.         return ((P1 * G + P0) * G) / ((G + Q1) * G + Q0);
  1742.     end R;
  1743.  
  1744.     begin
  1745.     F := abs (X);
  1746.  
  1747.     if F > 1.0 then
  1748.         F := 1.0 / F;
  1749.         N := 2;
  1750.     else
  1751.         N := 0;
  1752.     end if;
  1753.  
  1754.     if F > TWO_MINUS_SQRT_3 then
  1755.         F := (((SQRT_3_MINUS_1 * F - 0.5) - 0.5) + F) / (SQRT_3 + F);
  1756.         N := N + 1;
  1757.     end if;
  1758.  
  1759.     if abs (F) < EPSILON then
  1760.         RESULT := F;
  1761.     else
  1762.         G := F * F;
  1763.         RESULT := F + F * R (G);
  1764.     end if;
  1765.  
  1766.     if N > 1 then
  1767.         RESULT := -RESULT;
  1768.     end if;
  1769.  
  1770.     case N is
  1771.         when 0 => 
  1772.         RESULT := RESULT;
  1773.  
  1774.         when 1 => 
  1775.         RESULT := PI_OVER_SIX + RESULT;
  1776.  
  1777.         when 2 => 
  1778.         RESULT := PI_OVER_TWO + RESULT;
  1779.  
  1780.         when 3 => 
  1781.         RESULT := PI_OVER_THREE + RESULT;
  1782.     end case;
  1783.  
  1784.     if X < 0.0 then
  1785.         RESULT := -RESULT;
  1786.     end if;
  1787.  
  1788.     return RESULT;
  1789.  
  1790.     end ATAN;
  1791.  
  1792.  
  1793.  
  1794.     function ATAN2 (V, U : FLOAT) return FLOAT is
  1795.     X, RESULT : FLOAT;
  1796.  
  1797.     begin
  1798.  
  1799.     if U = 0.0 then
  1800.         if V = 0.0 then
  1801.         RESULT := 0.0;
  1802.         NEW_LINE;
  1803.         PUT (" ATAN2 CALLED WITH 0/0   RETURNED ");  PUT (RESULT);
  1804.         NEW_LINE;
  1805.  
  1806.         elsif V > 0.0 then
  1807.         RESULT := PI_OVER_TWO;
  1808.         else
  1809.         RESULT := -PI_OVER_TWO;
  1810.         end if;
  1811.  
  1812.     else
  1813.         X := abs (V / U);
  1814.         --  If underflow or overflow is detected, go to the exception
  1815.         RESULT := ATAN (X);
  1816.  
  1817.         if U < 0.0 then
  1818.         RESULT := PI - RESULT;
  1819.         end if;
  1820.  
  1821.         if V < 0.0 then
  1822.         RESULT := -RESULT;
  1823.         end if;
  1824.     end if;
  1825.  
  1826.     return RESULT;
  1827.     exception
  1828.     when NUMERIC_ERROR => 
  1829.         if abs (V) > abs (U) then
  1830.         RESULT := PI_OVER_TWO;
  1831.  
  1832.         if V < 0.0 then
  1833.             RESULT := -RESULT;
  1834.         end if;
  1835.         else
  1836.         RESULT := 0.0;
  1837.  
  1838.         if U < 0.0 then
  1839.             RESULT := PI - RESULT;
  1840.         end if;
  1841.         end if;
  1842.  
  1843.         return RESULT;
  1844.     end ATAN2;
  1845.  
  1846.  
  1847.     function SINH (X : FLOAT) return FLOAT is
  1848.     G, W, Y, Z       : FLOAT;
  1849.     RESULT           : FLOAT;
  1850.     BETA             : FLOAT := CONVERT_TO_FLOAT (IBETA);
  1851.     EPSILON          : FLOAT := BETA ** (-IT / 2);
  1852.  
  1853.     YBAR             : FLOAT := EXP_LARGE;
  1854.     LN_V             : FLOAT := 8#0.542714#;
  1855.     V_OVER_2_MINUS_1 : FLOAT := 0.13830_27787_96019_02638E-4;
  1856.     WMAX             : FLOAT := YBAR - LN_V + 0.69;
  1857.  
  1858.     function R (G : FLOAT) return FLOAT is
  1859.         P0 : constant FLOAT := 0.10622_28883_7151E4;
  1860.         P1 : constant FLOAT := 0.31359_75645_6058E2;
  1861.         P2 : constant FLOAT := 0.34364_14035_8506;
  1862.         Q0 : constant FLOAT := 0.63733_73302_1822E4;
  1863.         Q1 : constant FLOAT := -0.13051_01250_9199E3;
  1864.         Q2 : constant FLOAT := 1.0;
  1865.     begin
  1866.         return (((P2 * G + P1) * G + P0) * G) / ((G + Q1) * G + Q0);
  1867.     end R;
  1868.  
  1869.     begin
  1870.     Y := abs (X);
  1871.  
  1872.     if Y <= 1.0 then
  1873.         if Y < EPSILON then
  1874.         RESULT := X;
  1875.         else
  1876.         G := X * X;
  1877.         RESULT := X + X * R (G);
  1878.         end if;
  1879.  
  1880.     else
  1881.         if Y <= YBAR then
  1882.         Z := EXP (Y);
  1883.         RESULT := (Z - 1.0 / Z) / 2.0;
  1884.         else
  1885.         W := Y - LN_V;
  1886.  
  1887.         if W > WMAX then
  1888.             NEW_LINE;
  1889.             PUT (" SINH CALLED WITH TOO LARGE ARGUMENT  ");  PUT (X);
  1890.             PUT (" RETURN BIG");  NEW_LINE;
  1891.             W := WMAX;
  1892.         end if;
  1893.  
  1894.         Z := EXP (W);
  1895.         RESULT := Z + V_OVER_2_MINUS_1 * Z;
  1896.         end if;
  1897.  
  1898.         if X < 0.0 then
  1899.         RESULT := -RESULT;
  1900.         end if;
  1901.  
  1902.     end if;
  1903.  
  1904.     return RESULT;
  1905.     end SINH;
  1906.  
  1907.  
  1908.     function COSH (X : FLOAT) return FLOAT is
  1909.     G, W, Y, Z       : FLOAT;
  1910.     RESULT           : FLOAT;
  1911.     BETA             : FLOAT := CONVERT_TO_FLOAT (IBETA);
  1912.     EPSILON          : FLOAT := BETA ** (-IT / 2);
  1913.  
  1914.     YBAR             : FLOAT := EXP_LARGE;
  1915.     LN_V             : FLOAT := 8#0.542714#;
  1916.     V_OVER_2_MINUS_1 : FLOAT := 0.13830_27787_96019_02638E-4;
  1917.     WMAX             : FLOAT := YBAR - LN_V + 0.69;
  1918.  
  1919.     function R (G : FLOAT) return FLOAT is
  1920.         P0 : constant FLOAT := 0.10622_28883_7151E4;
  1921.         P1 : constant FLOAT := 0.31359_75645_6058E2;
  1922.         P2 : constant FLOAT := 0.34364_14035_8506;
  1923.         Q0 : constant FLOAT := 0.63733_73302_1822E4;
  1924.         Q1 : constant FLOAT := -0.13051_01250_9199E3;
  1925.         Q2 : constant FLOAT := 1.0;
  1926.     begin
  1927.         return (((P2 * G + P1) * G + P0) * G) / ((G + Q1) * G + Q0);
  1928.     end R;
  1929.  
  1930.     begin
  1931.     Y := abs (X);
  1932.  
  1933.     if Y <= YBAR then
  1934.         Z := EXP (Y);
  1935.         RESULT := (Z + 1.0 / Z) / 2.0;
  1936.     else
  1937.         W := Y - LN_V;
  1938.  
  1939.         if W > WMAX then
  1940.         NEW_LINE;
  1941.         PUT (" COSH CALLED WITH TOO LARGE ARGUMENT  ");  PUT (X);
  1942.         PUT (" RETURN BIG");  NEW_LINE;
  1943.         W := WMAX;
  1944.         end if;
  1945.  
  1946.         Z := EXP (W);
  1947.         RESULT := Z + V_OVER_2_MINUS_1 * Z;
  1948.     end if;
  1949.  
  1950.     return RESULT;
  1951.     end COSH;
  1952.  
  1953.  
  1954.     function TANH (X : FLOAT) return FLOAT is
  1955.     G, W, Y, Z  : FLOAT;
  1956.     RESULT      : FLOAT;
  1957.     BETA        : FLOAT := CONVERT_TO_FLOAT (IBETA);
  1958.     EPSILON     : FLOAT := BETA ** (-IT / 2);
  1959.  
  1960.     XBIG        : FLOAT :=
  1961.               (LOG (2.0) + CONVERT_TO_FLOAT (IT + 1) * LOG (BETA)) /
  1962.               2.0;
  1963.     LN_3_OVER_2 : FLOAT := 0.54930_61443_34054_84570;
  1964.  
  1965.     function R (G : FLOAT) return FLOAT is
  1966.         P0 : constant FLOAT := -0.21063_95800_0245E2;
  1967.         P1 : constant FLOAT := -0.93363_47565_2401;
  1968.         Q0 : constant FLOAT := 0.63191_87401_5582E2;
  1969.         Q1 : constant FLOAT := 0.28077_65347_0471E2;
  1970.         Q2 : constant FLOAT := 1.0;
  1971.     begin
  1972.         return ((P1 * G + P0) * G) / ((G + Q1) * G + Q0);
  1973.     end R;
  1974.  
  1975.     begin
  1976.     Y := abs (X);
  1977.  
  1978.     if Y > XBIG then
  1979.         RESULT := 1.0;
  1980.     else
  1981.         if Y > LN_3_OVER_2 then
  1982.         RESULT := 0.5 - 1.0 / (EXP (Y + Y) + 1.0);
  1983.         RESULT := RESULT + RESULT;
  1984.         else
  1985.         if Y < EPSILON then
  1986.             RESULT := Y;
  1987.         else
  1988.             G := Y * Y;
  1989.             RESULT := Y + Y * R (G);
  1990.         end if;
  1991.         end if;
  1992.     end if;
  1993.  
  1994.     if X < 0.0 then
  1995.         RESULT := -RESULT;
  1996.     end if;
  1997.  
  1998.     return RESULT;
  1999.     end TANH;
  2000.  
  2001.  
  2002. begin
  2003.     null;
  2004. end TRIG_FUNCTIONS;
  2005.  
  2006.  
  2007.  
  2008.  
  2009. with TEXT_IO;
  2010.  
  2011. package SCREEN_IO is
  2012. -- Author   : M. K. McNair
  2013. -- Source:     Division Software Technology and Support
  2014. --             Western Development Laboratories
  2015. --             Ford Aerospace & Communications Corporation
  2016. --             ATTN:  Ada Tools Group
  2017. -- Date     : 8 March 1985
  2018. -- Summary  :
  2019. --   This package provides a localized way of inputting values from
  2020. --   a terminal. If errors occur on input, the function will handle
  2021. --   the error itself - control does not return until a valid value
  2022. --   has been entered.
  2023.  
  2024.     function RETURNED_INTEGER (PROMPT      : STRING := "";
  2025.                    DEFAULT     : INTEGER := 0;
  2026.                    USE_DEFAULT : BOOLEAN := FALSE;
  2027.                    ERROR_TEXT  : STRING := "";
  2028.                    FROM_VALUE  : INTEGER := INTEGER'FIRST;
  2029.                    TO_VALUE    : INTEGER := INTEGER'LAST;
  2030.                    CONFIRM     : BOOLEAN := FALSE) return INTEGER;
  2031.     function RETURNED_FLOAT  
  2032.             (PROMPT                      : STRING := "";
  2033.          DEFAULT                     : FLOAT := 0.0;
  2034.          USE_DEFAULT                 : BOOLEAN := FALSE;
  2035.          DISPLAY_EXPONENT_IN_DEFAULT : BOOLEAN := FALSE;
  2036.          AFT_WIDTH_IN_DEFAULT        : NATURAL := 2;
  2037.          ERROR_TEXT                  : STRING := "";
  2038.          FROM_VALUE                  : FLOAT := FLOAT'FIRST;
  2039.          TO_VALUE                    : FLOAT := FLOAT'LAST;
  2040.          CONFIRM                     : BOOLEAN := FALSE) return FLOAT;
  2041.  
  2042.     function RETURNED_STRING (PROMPT      : STRING := "";
  2043.                   DEFAULT     : STRING := "";
  2044.                   USE_DEFAULT : BOOLEAN := FALSE;
  2045.                   CONFIRM     : BOOLEAN := FALSE) return STRING;
  2046.  
  2047.     generic
  2048.     type ENUM_TYPE is (<>);
  2049.     function RETURNED_ENUMERATION (PROMPT      : STRING := "";
  2050.                    DEFAULT     : ENUM_TYPE := ENUM_TYPE'FIRST;
  2051.                    USE_DEFAULT : BOOLEAN := FALSE;
  2052.                    ERROR_TEXT  : STRING := "";
  2053.                    FROM_VALUE  : ENUM_TYPE := ENUM_TYPE'FIRST;
  2054.                    TO_VALUE    : ENUM_TYPE := ENUM_TYPE'LAST;
  2055.                    CONFIRM     : BOOLEAN := FALSE)
  2056.                     return ENUM_TYPE;
  2057.  
  2058. end SCREEN_IO;
  2059.  
  2060.  
  2061.  
  2062.  
  2063. package body SCREEN_IO is
  2064. -- Author   : M. K. McNair
  2065. -- Source:     Division Software Technology and Support
  2066. --             Western Development Laboratories
  2067. --             Ford Aerospace & Communications Corporation
  2068. --             ATTN:  Ada Tools Group
  2069. -- Date     : 8 March 1985
  2070. -- Summary  :
  2071. --   This is the package body to the SCREEN_IO package.
  2072.  
  2073.     BUFFER_LENGTH : constant POSITIVE := 256;
  2074.  
  2075.  
  2076.  
  2077.     procedure ERROR (MSG : STRING) is
  2078.     begin
  2079.     if MSG'LENGTH > 0 then
  2080.         TEXT_IO.PUT_LINE (MSG);
  2081.     end if;
  2082.     end ERROR;
  2083.  
  2084.  
  2085.  
  2086.     -- Author   : T. C. Bryan
  2087.     -- Source:     Division Software Technology and Support
  2088.     --             Western Development Laboratories
  2089.     --             Ford Aerospace & Communications Corporation
  2090.     --             ATTN:  Ada Tools Group
  2091.     -- Date     : June 1985
  2092.     -- Summary  :
  2093.     --   This function evaluates each character coming from standard
  2094.     --   input for a simulated back space character, the current value
  2095.     --   of this character is"#" sign.  When encountered such character,
  2096.     --   it redraws the current input line to the screen minus the last
  2097.     --   two characters.
  2098.     --   In effect, it allows user to correct miswritten character
  2099.     --   while inputting data.
  2100.  
  2101.     function GET_THE_STRING return STRING is
  2102.  
  2103.     A_BUFF         : STRING (1 .. BUFFER_LENGTH);
  2104.     INDEX          : INTEGER := 0;
  2105.     CURRENT_LETTER : CHARACTER;
  2106.  
  2107.     ---------------------------------------------------------
  2108.     -- the "\" sign can be replaced by any special character
  2109.     -- that is not normally part of the input line.
  2110.     ---------------------------------------------------------
  2111.  
  2112.     BACK_SPACE : constant CHARACTER := '\';
  2113.  
  2114.     begin
  2115.  
  2116.     while not TEXT_IO.END_OF_LINE loop
  2117.         TEXT_IO.GET (CURRENT_LETTER);
  2118.  
  2119.         if (CURRENT_LETTER /= BACK_SPACE) then
  2120.         INDEX := INDEX + 1;
  2121.         A_BUFF (INDEX) := CURRENT_LETTER;
  2122.         else
  2123.         INDEX := INDEX - 1;
  2124.  
  2125.         if INDEX < 0 then
  2126.             INDEX := 0;
  2127.         end if;
  2128.  
  2129.         TEXT_IO.NEW_LINE;
  2130.         TEXT_IO.PUT (A_BUFF (1 .. INDEX));
  2131.         end if;
  2132.     end loop;
  2133.  
  2134.     TEXT_IO.SKIP_LINE;
  2135.  
  2136.     return (A_BUFF (1 .. INDEX));
  2137.  
  2138.     end GET_THE_STRING;
  2139.  
  2140.  
  2141.  
  2142.     function GO_AGAIN return BOOLEAN is
  2143.  
  2144.     type YESNO_TYPE is (Y, YE, YES, N, NO);
  2145.  
  2146.     package YESNO_IO is new TEXT_IO.ENUMERATION_IO (YESNO_TYPE);
  2147.  
  2148.     ANSWER : YESNO_TYPE;
  2149.     BUFFER : STRING (1 .. BUFFER_LENGTH);
  2150.     LAST   : NATURAL;
  2151.     begin
  2152.     TEXT_IO.NEW_LINE;
  2153.     TEXT_IO.PUT ("Would you like to re-enter this value? ");
  2154.  
  2155.     TEXT_IO.GET_LINE (BUFFER, LAST);
  2156.     YESNO_IO.GET (BUFFER (1 .. LAST), ANSWER, LAST);
  2157.     return ANSWER in Y .. YES;
  2158.  
  2159.     exception
  2160.     when TEXT_IO.DATA_ERROR => 
  2161.         TEXT_IO.PUT_LINE ("Please enter either Yes or No.");
  2162.         return GO_AGAIN;
  2163.  
  2164.     when TEXT_IO.END_ERROR => 
  2165.         return FALSE;
  2166.     end GO_AGAIN;
  2167.  
  2168.  
  2169.  
  2170.     function RETURNED_INTEGER (PROMPT      : STRING := "";
  2171.                    DEFAULT     : INTEGER := 0;
  2172.                    USE_DEFAULT : BOOLEAN := FALSE;
  2173.                    ERROR_TEXT  : STRING := "";
  2174.                    FROM_VALUE  : INTEGER := INTEGER'FIRST;
  2175.                    TO_VALUE    : INTEGER := INTEGER'LAST;
  2176.                    CONFIRM     : BOOLEAN := FALSE) return INTEGER is
  2177.  
  2178.  
  2179.     ENCOUNTERED_CONSTRAINT_ERROR : exception;
  2180.     ENCOUNTERED_END_ERROR        : exception;
  2181.     ENCOUNTERED_DATA_ERROR       : exception;
  2182.  
  2183.     LAST : INTEGER;
  2184.  
  2185.     subtype ANSWER_TYPE is INTEGER range FROM_VALUE .. TO_VALUE;
  2186.  
  2187.     ANSWER : ANSWER_TYPE;
  2188.  
  2189.     package INT_IO is new TEXT_IO.INTEGER_IO (INTEGER);
  2190.  
  2191.     function RETURNED_ANSWER (VALUE : STRING) return INTEGER is
  2192.  
  2193.     begin
  2194.  
  2195.         INT_IO.GET (VALUE, ANSWER, LAST);
  2196.         return (ANSWER);
  2197.  
  2198.     exception
  2199.         when CONSTRAINT_ERROR | NUMERIC_ERROR => 
  2200.         raise ENCOUNTERED_CONSTRAINT_ERROR;
  2201.  
  2202.         when TEXT_IO.END_ERROR => 
  2203.         raise ENCOUNTERED_END_ERROR;
  2204.  
  2205.         when TEXT_IO.DATA_ERROR => 
  2206.         raise ENCOUNTERED_DATA_ERROR;
  2207.  
  2208.         when others => 
  2209.         raise ENCOUNTERED_DATA_ERROR;
  2210.  
  2211.     end RETURNED_ANSWER;
  2212.     begin
  2213.  
  2214.     TEXT_IO.PUT (PROMPT);
  2215.  
  2216.     if USE_DEFAULT then
  2217.         TEXT_IO.NEW_LINE;
  2218.         TEXT_IO.SET_COL (4);
  2219.         TEXT_IO.PUT ("(default => ");
  2220.         INT_IO.PUT (DEFAULT);  TEXT_IO.PUT (" ) ");
  2221.     end if;
  2222.  
  2223.     declare
  2224.         BUFFER : constant STRING := GET_THE_STRING;
  2225.  
  2226.     begin
  2227.  
  2228.         if CONFIRM then
  2229.         if GO_AGAIN then
  2230.             return RETURNED_INTEGER
  2231.                   (PROMPT, DEFAULT, USE_DEFAULT, ERROR_TEXT,
  2232.                    FROM_VALUE, TO_VALUE, CONFIRM);
  2233.         end if;
  2234.         end if;
  2235.  
  2236.         return (RETURNED_ANSWER (BUFFER));
  2237.     exception
  2238.         when ENCOUNTERED_CONSTRAINT_ERROR => 
  2239.         if ERROR_TEXT /= "" then
  2240.             ERROR (MSG => ERROR_TEXT);
  2241.         else
  2242.             TEXT_IO.PUT ("Please enter an integer between ");
  2243.             INT_IO.PUT (FROM_VALUE);
  2244.             TEXT_IO.PUT (" and ");
  2245.             INT_IO.PUT (TO_VALUE);  TEXT_IO.NEW_LINE;
  2246.         end if;
  2247.  
  2248.         return RETURNED_INTEGER
  2249.               (PROMPT, DEFAULT, USE_DEFAULT, ERROR_TEXT,
  2250.                FROM_VALUE, TO_VALUE, CONFIRM);
  2251.  
  2252.         when ENCOUNTERED_END_ERROR => 
  2253.         if USE_DEFAULT then
  2254.             TEXT_IO.PUT ("Using default value of => ");
  2255.             INT_IO.PUT (DEFAULT);  TEXT_IO.NEW_LINE;
  2256.             return DEFAULT;
  2257.         else
  2258.             if ERROR_TEXT = "" then
  2259.             TEXT_IO.PUT ("Please enter an integer between ");
  2260.             INT_IO.PUT (FROM_VALUE);
  2261.             TEXT_IO.PUT (" and ");
  2262.             INT_IO.PUT (TO_VALUE);  TEXT_IO.NEW_LINE;
  2263.             else
  2264.             ERROR (MSG => ERROR_TEXT);
  2265.             end if;
  2266.  
  2267.             return RETURNED_INTEGER
  2268.                   (PROMPT, DEFAULT, USE_DEFAULT, ERROR_TEXT,
  2269.                    FROM_VALUE, TO_VALUE, CONFIRM);
  2270.         end if;
  2271.  
  2272.         when ENCOUNTERED_DATA_ERROR => 
  2273.         if ERROR_TEXT /= "" then
  2274.             ERROR (MSG => ERROR_TEXT);
  2275.         else
  2276.             ERROR (MSG => "You must enter an integer.");
  2277.         end if;
  2278.  
  2279.         return RETURNED_INTEGER
  2280.               (PROMPT, DEFAULT, USE_DEFAULT, ERROR_TEXT,
  2281.                FROM_VALUE, TO_VALUE, CONFIRM);
  2282.  
  2283.     end;
  2284.  
  2285.     end RETURNED_INTEGER;
  2286.  
  2287.  
  2288.  
  2289.     function RETURNED_FLOAT
  2290.             (PROMPT                      : STRING := "";
  2291.          DEFAULT                     : FLOAT := 0.0;
  2292.          USE_DEFAULT                 : BOOLEAN := FALSE;
  2293.          DISPLAY_EXPONENT_IN_DEFAULT : BOOLEAN := FALSE;
  2294.          AFT_WIDTH_IN_DEFAULT        : NATURAL := 2;
  2295.          ERROR_TEXT                  : STRING := "";
  2296.          FROM_VALUE                  : FLOAT := FLOAT'FIRST;
  2297.          TO_VALUE                    : FLOAT := FLOAT'LAST;
  2298.          CONFIRM                     : BOOLEAN := FALSE) return FLOAT is
  2299.  
  2300.     LAST : INTEGER;
  2301.  
  2302.     ENCOUNTER_END_ERROR  : exception;
  2303.     END_CONVERT_TO_FLOAT : exception;
  2304.  
  2305.     subtype ANSWER_TYPE is FLOAT range FROM_VALUE .. TO_VALUE;
  2306.  
  2307.     ANSWER : ANSWER_TYPE;
  2308.  
  2309.     package FLT_IO is new TEXT_IO.FLOAT_IO (FLOAT);
  2310.  
  2311.  
  2312.     -- Author   : T. C. Bryan
  2313.     -- Source:     Division Software Technology and Support
  2314.     --             Western Development Laboratories
  2315.     --             Ford Aerospace & Communications Corporation
  2316.     --             ATTN:  Ada Tools Group
  2317.     -- Date     : June 1985
  2318.     -- Summary  :
  2319.     --   This function evaluates a numerical value coming in from standard
  2320.     --   input and converts it, if necessary, to a float number.
  2321.     --   In effect, it allows user to input a float number without being
  2322.     --   restricted to a specific format.
  2323.  
  2324.     function CONVERT_TO_FLOAT (TEMP_NAME : STRING) return FLOAT is
  2325.  
  2326.  
  2327.  
  2328.         FOUND_DOT          : BOOLEAN := FALSE;
  2329.         FOUND_NU_AFTER_DOT : BOOLEAN := FALSE;
  2330.  
  2331.         A_FLOAT_NUMBER     : ANSWER_TYPE;
  2332.         LAST_NU            : POSITIVE;
  2333.  
  2334.     begin
  2335.         if TEMP_NAME = "" then
  2336.         raise ENCOUNTER_END_ERROR;
  2337.         end if;
  2338.  
  2339.         for I in 1 .. TEMP_NAME'LENGTH loop
  2340.         if TEMP_NAME (I) = '.' and not FOUND_DOT then
  2341.             FOUND_DOT := TRUE;
  2342.  
  2343.         elsif FOUND_DOT and TEMP_NAME (I) /= ' ' then
  2344.             FOUND_NU_AFTER_DOT := TRUE;
  2345.         end if;
  2346.  
  2347.         end loop;
  2348.  
  2349.         if FOUND_DOT then
  2350.                 -- case .x
  2351.         if TEMP_NAME (1) = '.' and TEMP_NAME'LENGTH > 1 then
  2352.             FLT_IO.GET
  2353.                (FROM => "0" & TEMP_NAME,
  2354.             ITEM => A_FLOAT_NUMBER,
  2355.             LAST => LAST_NU);
  2356.             -- case x.x
  2357.         elsif FOUND_NU_AFTER_DOT then
  2358.             FLT_IO.GET
  2359.                (FROM => TEMP_NAME,
  2360.             ITEM => A_FLOAT_NUMBER,
  2361.             LAST => LAST_NU);
  2362.             -- case x.
  2363.         else
  2364.             FLT_IO.GET
  2365.                (FROM => TEMP_NAME & "0",
  2366.             ITEM => A_FLOAT_NUMBER,
  2367.             LAST => LAST_NU);
  2368.         end if;
  2369.         -- case x
  2370.         else
  2371.         FLT_IO.GET (FROM => TEMP_NAME & ".0",
  2372.                 ITEM => A_FLOAT_NUMBER,
  2373.                 LAST => LAST_NU);
  2374.         end if;
  2375.  
  2376.         return (A_FLOAT_NUMBER);
  2377.  
  2378.     exception
  2379.         when CONSTRAINT_ERROR | NUMERIC_ERROR | TEXT_IO.DATA_ERROR => 
  2380.         raise END_CONVERT_TO_FLOAT;
  2381.  
  2382.         when TEXT_IO.END_ERROR => 
  2383.         raise ENCOUNTER_END_ERROR;
  2384.  
  2385.     end CONVERT_TO_FLOAT;
  2386.  
  2387.  
  2388.  
  2389.     begin
  2390.  
  2391.     TEXT_IO.PUT (PROMPT);
  2392.  
  2393.     if USE_DEFAULT then
  2394.         TEXT_IO.NEW_LINE;
  2395.         TEXT_IO.SET_COL (4);
  2396.         TEXT_IO.PUT ("(default => ");
  2397.  
  2398.         if not DISPLAY_EXPONENT_IN_DEFAULT then
  2399.         FLT_IO.PUT (DEFAULT, EXP => 0, AFT => AFT_WIDTH_IN_DEFAULT);
  2400.         else
  2401.         FLT_IO.PUT (DEFAULT, AFT => AFT_WIDTH_IN_DEFAULT);
  2402.         end if;
  2403.  
  2404.         TEXT_IO.PUT (" ) ");
  2405.     end if;
  2406.  
  2407.     declare
  2408.         BUFFER : constant STRING := GET_THE_STRING;
  2409.  
  2410.     begin
  2411.  
  2412.         if CONFIRM then
  2413.         if GO_AGAIN then
  2414.             return RETURNED_FLOAT
  2415.                   (PROMPT, DEFAULT, USE_DEFAULT,
  2416.                    DISPLAY_EXPONENT_IN_DEFAULT,
  2417.                    AFT_WIDTH_IN_DEFAULT, ERROR_TEXT, FROM_VALUE,
  2418.                    TO_VALUE, CONFIRM);
  2419.         end if;
  2420.         end if;
  2421.  
  2422.         return (CONVERT_TO_FLOAT (TEMP_NAME => BUFFER));
  2423.     exception
  2424.         when END_CONVERT_TO_FLOAT => 
  2425.         if ERROR_TEXT /= "" then
  2426.             ERROR (MSG => ERROR_TEXT);
  2427.         else
  2428.             TEXT_IO.PUT ("Please enter a float between ");
  2429.             FLT_IO.PUT (FROM_VALUE, EXP => 0);
  2430.             TEXT_IO.PUT (" and ");
  2431.             FLT_IO.PUT (TO_VALUE, EXP => 0);
  2432.             TEXT_IO.NEW_LINE;
  2433.         end if;
  2434.  
  2435.         return RETURNED_FLOAT
  2436.               (PROMPT, DEFAULT, USE_DEFAULT,
  2437.                DISPLAY_EXPONENT_IN_DEFAULT, AFT_WIDTH_IN_DEFAULT,
  2438.                ERROR_TEXT, FROM_VALUE, TO_VALUE, CONFIRM);
  2439.  
  2440.         when ENCOUNTER_END_ERROR => 
  2441.         if USE_DEFAULT then
  2442.             TEXT_IO.PUT ("Using default value of => ");
  2443.             FLT_IO.PUT (DEFAULT, EXP => 0);  TEXT_IO.NEW_LINE;
  2444.             return DEFAULT;
  2445.         else
  2446.             if ERROR_TEXT = "" then
  2447.             TEXT_IO.PUT ("Please enter a float between ");
  2448.             FLT_IO.PUT (FROM_VALUE, EXP => 0);
  2449.             TEXT_IO.PUT (" and ");
  2450.             FLT_IO.PUT (TO_VALUE, EXP => 0);
  2451.             TEXT_IO.NEW_LINE;
  2452.             else
  2453.             ERROR (MSG => ERROR_TEXT);
  2454.             end if;
  2455.  
  2456.             return RETURNED_FLOAT
  2457.                   (PROMPT, DEFAULT, USE_DEFAULT,
  2458.                    DISPLAY_EXPONENT_IN_DEFAULT,
  2459.                    AFT_WIDTH_IN_DEFAULT, ERROR_TEXT, FROM_VALUE,
  2460.                    TO_VALUE, CONFIRM);
  2461.         end if;
  2462.  
  2463.     end;
  2464.  
  2465.     end RETURNED_FLOAT;
  2466.  
  2467.  
  2468.  
  2469.  
  2470.     function RETURNED_STRING (PROMPT      : STRING := "";
  2471.                   DEFAULT     : STRING := "";
  2472.                   USE_DEFAULT : BOOLEAN := FALSE;
  2473.                   CONFIRM     : BOOLEAN := FALSE) return STRING is
  2474.  
  2475.     begin
  2476.  
  2477.     TEXT_IO.PUT (PROMPT);
  2478.  
  2479.     if USE_DEFAULT then
  2480.         TEXT_IO.NEW_LINE;
  2481.         TEXT_IO.SET_COL (4);
  2482.  
  2483.         if DEFAULT = "" then
  2484.         TEXT_IO.PUT ("(default => RETURN) ");
  2485.         else
  2486.         TEXT_IO.PUT ("  (default => " & DEFAULT & " ) ");
  2487.         end if;
  2488.     end if;
  2489.  
  2490.     declare
  2491.         BUFFER : constant STRING := GET_THE_STRING;
  2492.  
  2493.     begin
  2494.  
  2495.         if CONFIRM then
  2496.         if GO_AGAIN then
  2497.             return RETURNED_STRING
  2498.                   (PROMPT, DEFAULT, USE_DEFAULT, CONFIRM);
  2499.         end if;
  2500.         end if;
  2501.  
  2502.         return (BUFFER);
  2503.     exception
  2504.         when TEXT_IO.END_ERROR => 
  2505.         if USE_DEFAULT then
  2506.             if DEFAULT = "" then
  2507.             return RETURNED_STRING
  2508.                   (PROMPT, DEFAULT, USE_DEFAULT, CONFIRM);
  2509.             else
  2510.             TEXT_IO.PUT ("Using default value of => ");
  2511.             TEXT_IO.PUT (DEFAULT);  TEXT_IO.NEW_LINE;
  2512.             return DEFAULT;
  2513.             end if;
  2514.         else
  2515.             return RETURNED_STRING
  2516.                   (PROMPT, DEFAULT, USE_DEFAULT, CONFIRM);
  2517.         end if;
  2518.     end;
  2519.  
  2520.     end RETURNED_STRING;
  2521.  
  2522.  
  2523.  
  2524.  
  2525.     function RETURNED_ENUMERATION
  2526.             (PROMPT      : STRING := "";
  2527.          DEFAULT     : ENUM_TYPE := ENUM_TYPE'FIRST;
  2528.          USE_DEFAULT : BOOLEAN := FALSE;
  2529.          ERROR_TEXT  : STRING := "";
  2530.          FROM_VALUE  : ENUM_TYPE := ENUM_TYPE'FIRST;
  2531.          TO_VALUE    : ENUM_TYPE := ENUM_TYPE'LAST;
  2532.          CONFIRM     : BOOLEAN := FALSE) return ENUM_TYPE is
  2533.  
  2534.     LAST : INTEGER;
  2535.  
  2536.     ENCOUNTERED_CONSTRAINT_ERROR : exception;
  2537.     ENCOUNTERED_END_ERROR        : exception;
  2538.     ENCOUNTERED_DATA_ERROR       : exception;
  2539.  
  2540.     subtype ANSWER_TYPE is ENUM_TYPE range FROM_VALUE .. TO_VALUE;
  2541.  
  2542.     ANSWER : ANSWER_TYPE;
  2543.  
  2544.     package ENUM_IO is new TEXT_IO.ENUMERATION_IO (ENUM_TYPE);
  2545.  
  2546.     function RETURNED_ANSWER (VALUE : STRING) return ENUM_TYPE is
  2547.  
  2548.     begin
  2549.  
  2550.         ENUM_IO.GET (VALUE, ANSWER, LAST);
  2551.         return (ANSWER);
  2552.  
  2553.     exception
  2554.         when CONSTRAINT_ERROR => 
  2555.         raise ENCOUNTERED_CONSTRAINT_ERROR;
  2556.  
  2557.         when TEXT_IO.END_ERROR => 
  2558.         raise ENCOUNTERED_END_ERROR;
  2559.  
  2560.         when TEXT_IO.DATA_ERROR => 
  2561.         raise ENCOUNTERED_DATA_ERROR;
  2562.  
  2563.         when others => 
  2564.         raise ENCOUNTERED_DATA_ERROR;
  2565.  
  2566.     end RETURNED_ANSWER;
  2567.  
  2568.  
  2569.     begin
  2570.  
  2571.     TEXT_IO.PUT (PROMPT);
  2572.  
  2573.     if USE_DEFAULT then
  2574.         TEXT_IO.NEW_LINE;
  2575.         TEXT_IO.SET_COL (4);
  2576.         TEXT_IO.PUT ("(default => ");
  2577.         ENUM_IO.PUT (DEFAULT);  TEXT_IO.PUT (" ) ");
  2578.     end if;
  2579.  
  2580.     declare
  2581.         BUFFER : constant STRING := GET_THE_STRING;
  2582.  
  2583.     begin
  2584.  
  2585.  
  2586.         if CONFIRM then
  2587.         if GO_AGAIN then
  2588.             return RETURNED_ENUMERATION
  2589.                   (PROMPT, DEFAULT, USE_DEFAULT, ERROR_TEXT,
  2590.                    FROM_VALUE, TO_VALUE, CONFIRM);
  2591.         end if;
  2592.         end if;
  2593.  
  2594.         return (RETURNED_ANSWER (VALUE => BUFFER));
  2595.     exception
  2596.         when ENCOUNTERED_CONSTRAINT_ERROR => 
  2597.         if ERROR_TEXT /= "" then
  2598.             ERROR (MSG => ERROR_TEXT);
  2599.         else
  2600.             TEXT_IO.PUT ("Please enter a value between ");
  2601.             ENUM_IO.PUT (FROM_VALUE);
  2602.             TEXT_IO.PUT (" and ");
  2603.             ENUM_IO.PUT (TO_VALUE);  TEXT_IO.NEW_LINE;
  2604.         end if;
  2605.  
  2606.         return RETURNED_ENUMERATION
  2607.               (PROMPT, DEFAULT, USE_DEFAULT, ERROR_TEXT,
  2608.                FROM_VALUE, TO_VALUE, CONFIRM);
  2609.  
  2610.         when ENCOUNTERED_END_ERROR => 
  2611.         if USE_DEFAULT then
  2612.             TEXT_IO.PUT ("Using default value of => ");
  2613.             ENUM_IO.PUT (DEFAULT);  TEXT_IO.NEW_LINE;
  2614.             return DEFAULT;
  2615.         else
  2616.             if ERROR_TEXT = "" then
  2617.             TEXT_IO.PUT ("Please enter a value between ");
  2618.             ENUM_IO.PUT (FROM_VALUE);
  2619.             TEXT_IO.PUT (" and ");
  2620.             ENUM_IO.PUT (TO_VALUE);  TEXT_IO.NEW_LINE;
  2621.             else
  2622.             ERROR (MSG => ERROR_TEXT);
  2623.             end if;
  2624.  
  2625.             return RETURNED_ENUMERATION
  2626.                   (PROMPT, DEFAULT, USE_DEFAULT, ERROR_TEXT,
  2627.                    FROM_VALUE, TO_VALUE, CONFIRM);
  2628.         end if;
  2629.  
  2630.         when ENCOUNTERED_DATA_ERROR => 
  2631.         if ERROR_TEXT /= "" then
  2632.             ERROR (MSG => ERROR_TEXT);
  2633.         else
  2634.             ERROR (MSG => "You entered an invalid value.");
  2635.         end if;
  2636.  
  2637.         return RETURNED_ENUMERATION
  2638.               (PROMPT, DEFAULT, USE_DEFAULT, ERROR_TEXT,
  2639.                FROM_VALUE, TO_VALUE, CONFIRM);
  2640.  
  2641.     end;
  2642.  
  2643.     end RETURNED_ENUMERATION;
  2644.  
  2645. end SCREEN_IO;
  2646.  
  2647.  
  2648.  
  2649.  
  2650. with CALENDAR;
  2651.  
  2652. package DATE_AND_TIME is
  2653. -- Author    : M. K. McNair
  2654. -- Source:     Division Software Technology and Support
  2655. --             Western Development Laboratories
  2656. --             Ford Aerospace & Communications Corporation
  2657. --             ATTN:  Ada Tools Group
  2658. -- Date      : 8 March 1985
  2659. -- Summary   :
  2660. --   This package is built on top of CALENDAR to give the ability to
  2661. --   put a date/time to a string.
  2662.  
  2663.     subtype HOUR_NUMBER   is INTEGER range 0 .. 23;
  2664.     subtype MINUTE_NUMBER is INTEGER range 0 .. 59;
  2665.     subtype SECOND_NUMBER is INTEGER range 0 .. 59;
  2666.  
  2667.     function CURRENT_DATE return STRING;
  2668.     function CURRENT_TIME return STRING;
  2669.  
  2670.     function DATE (DAY   : CALENDAR.DAY_NUMBER;
  2671.            MONTH : CALENDAR.MONTH_NUMBER;
  2672.            YEAR  : CALENDAR.YEAR_NUMBER) return STRING;
  2673.     function TIME (HOUR   : HOUR_NUMBER;
  2674.            MINUTE : MINUTE_NUMBER;
  2675.            SECOND : SECOND_NUMBER) return STRING;
  2676.  
  2677.  
  2678. -- julian functions (relative to 7 Dec 1941)
  2679.  
  2680.     subtype JULIAN_TYPE is INTEGER;
  2681.     subtype DAY_TYPE    is INTEGER range 1 .. 31;
  2682.     subtype MONTH_TYPE  is INTEGER range 1 .. 12;
  2683.     subtype YEAR_TYPE   is INTEGER range 0 .. 2000;
  2684.  
  2685.     type CALENDAR_TYPE is
  2686.     record
  2687.         DAY   : DAY_TYPE;
  2688.         MONTH : MONTH_TYPE;
  2689.         YEAR  : YEAR_TYPE;
  2690.     end record;
  2691.  
  2692.     function DAY_OF_WEEK              (JULIAN_DAY : JULIAN_TYPE) return INTEGER;
  2693.     function NEAREST_PRECEDING_MONDAY (JULIAN_DAY : JULIAN_TYPE)
  2694.                         return JULIAN_TYPE;
  2695.     function JULIAN_DATE              (CALENDAR_DATE : CALENDAR_TYPE)
  2696.                         return JULIAN_TYPE;
  2697.     function CALENDAR_DATE            (JULIAN_DATE : JULIAN_TYPE)
  2698.                         return CALENDAR_TYPE;
  2699. -- misc stuff
  2700.     type MONTH_NAME_TYPE is
  2701.      (JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC);
  2702.  
  2703.     for MONTH_NAME_TYPE use (JAN => 1,
  2704.                  FEB => 2,
  2705.                  MAR => 3,
  2706.                  APR => 4,
  2707.                  MAY => 5,
  2708.                  JUN => 6,
  2709.                  JUL => 7,
  2710.                  AUG => 8,
  2711.                  SEP => 9,
  2712.                  OCT => 10,
  2713.                  NOV => 11,
  2714.                  DEC => 12);
  2715.  
  2716.     type WEEK_NAME_TYPE is
  2717.      (SUNDAY,    MONDAY,    TUESDAY,   WEDNESDAY, THURSDAY,  FRIDAY,
  2718.       SATURDAY);
  2719.  
  2720.     for WEEK_NAME_TYPE use (SUNDAY    => 1,
  2721.                 MONDAY    => 2,
  2722.                 TUESDAY   => 3,
  2723.                 WEDNESDAY => 4,
  2724.                 THURSDAY  => 5,
  2725.                 FRIDAY    => 6,
  2726.                 SATURDAY  => 7);
  2727.     MONTH_NAME         : constant array (1 .. 12) of MONTH_NAME_TYPE :=
  2728.              (1  => JAN,
  2729.               2  => FEB,
  2730.               3  => MAR,
  2731.               4  => APR,
  2732.               5  => MAY,
  2733.               6  => JUN,
  2734.               7  => JUL,
  2735.               8  => AUG,
  2736.               9  => SEP,
  2737.               10 => OCT,
  2738.               11 => NOV,
  2739.               12 => DEC);
  2740.     DAY_NAME           : constant array (1 .. 7) of WEEK_NAME_TYPE :=
  2741.              (1 => SUNDAY,
  2742.               2 => MONDAY,
  2743.               3 => TUESDAY,
  2744.               4 => WEDNESDAY,
  2745.               5 => THURSDAY,
  2746.               6 => FRIDAY,
  2747.               7 => SATURDAY);
  2748.     DAYS_IN            : constant array (MONTH_NAME_TYPE) of POSITIVE :=
  2749.              (JAN => 31,
  2750.               FEB => 28,
  2751.               MAR => 31,
  2752.               APR => 30,
  2753.               MAY => 31,
  2754.               JUN => 30,
  2755.               JUL => 31,
  2756.               AUG => 31,
  2757.               SEP => 30,
  2758.               OCT => 31,
  2759.               NOV => 30,
  2760.               DEC => 31);
  2761.     HOURS_PER_DAY      : constant INTEGER := 24;
  2762.     DAYS_PER_WEEK      : constant INTEGER := 7;
  2763.     WEEKS_PER_YEAR     : constant INTEGER := 52;
  2764.     DAYS_PER_YEAR      : constant FLOAT := 365.25;
  2765.     MINUTES_PER_HOUR   : constant INTEGER := 60;
  2766.     SECONDS_PER_MINUTE : constant INTEGER := 60;
  2767.  
  2768. end DATE_AND_TIME;
  2769.  
  2770.  
  2771.  
  2772.  
  2773. package body DATE_AND_TIME is
  2774. -- Author   : M. K. McNair
  2775. -- Source:     Division Software Technology and Support
  2776. --             Western Development Laboratories
  2777. --             Ford Aerospace & Communications Corporation
  2778. --             ATTN:  Ada Tools Group
  2779. -- Date     : 8 March 1985
  2780. -- Summary  :
  2781. --   This is the package body to the DATE_AND_TIME package.
  2782.  
  2783.  
  2784. -- CHANGE_HISTORY:
  2785. ------------------
  2786.  
  2787. -- May 17, 1985   Ken Lamarche
  2788. --   Change made to the function "calender_date" so that the function uses temp
  2789. --   variables rather than the constrained calender_type variables for
  2790. --   arithmetic work.
  2791.  
  2792. -- May 21, 1985   Ken Lamrche
  2793. --   Change to function "julian_date" so that temp variables are used in the
  2794. --   arithmetic operations, rather than constrained calender_type variables.
  2795.  
  2796.     function CURRENT_DATE return STRING is
  2797.     TIME_NOW : CALENDAR.TIME := CALENDAR.CLOCK;
  2798.     begin
  2799.     return DATE (CALENDAR.DAY (TIME_NOW), CALENDAR.MONTH (TIME_NOW),
  2800.              CALENDAR.YEAR (TIME_NOW));
  2801.     end CURRENT_DATE;
  2802.  
  2803.     function CURRENT_TIME return STRING is
  2804.     TIME_NOW : INTEGER range 0 .. 86400 :=
  2805.            INTEGER (CALENDAR.SECONDS (CALENDAR.CLOCK));
  2806.     HOURS    : HOUR_NUMBER := TIME_NOW / (60 * 60);
  2807.     MINUTES  : MINUTE_NUMBER := (TIME_NOW - (60 * 60 * HOURS)) / 60;
  2808.     SECONDS  : SECOND_NUMBER :=
  2809.            TIME_NOW - (60 * 60 * HOURS) - (60 * MINUTES);
  2810.     begin
  2811.     return TIME (HOURS, MINUTES, SECONDS);
  2812.     end CURRENT_TIME;
  2813.  
  2814.     function DATE (DAY   : CALENDAR.DAY_NUMBER;
  2815.            MONTH : CALENDAR.MONTH_NUMBER;
  2816.            YEAR  : CALENDAR.YEAR_NUMBER) return STRING is
  2817.     begin
  2818.     return INTEGER'IMAGE (DAY) & ' ' &
  2819.            MONTH_NAME_TYPE'IMAGE (MONTH_NAME_TYPE'VAL (MONTH - 1)) &
  2820.            INTEGER'IMAGE (YEAR);
  2821.     end DATE;
  2822.  
  2823.     function TIME (HOUR   : HOUR_NUMBER;
  2824.            MINUTE : MINUTE_NUMBER;
  2825.            SECOND : SECOND_NUMBER) return STRING is
  2826.     begin
  2827.     return INTEGER'IMAGE (HOUR) & ':' & INTEGER'IMAGE (MINUTE) & ':' &
  2828.            INTEGER'IMAGE (SECOND);
  2829.     end TIME;
  2830.  
  2831.     function DAY_OF_WEEK (JULIAN_DAY : JULIAN_TYPE) return INTEGER is
  2832.     begin
  2833.     return JULIAN_DAY mod 7;
  2834.     end DAY_OF_WEEK;
  2835.  
  2836.     function NEAREST_PRECEDING_MONDAY (JULIAN_DAY : JULIAN_TYPE)
  2837.                         return JULIAN_TYPE is
  2838.     begin
  2839.     return JULIAN_DAY - (DAY_OF_WEEK (JULIAN_DAY) - 1);
  2840.     end NEAREST_PRECEDING_MONDAY;
  2841.  
  2842.  
  2843.  
  2844.     function JULIAN_DATE (CALENDAR_DATE : CALENDAR_TYPE) return JULIAN_TYPE is
  2845.     TEMP1, TEMP2, TEMP3 : INTEGER;
  2846.     begin
  2847.     TEMP3 := CALENDAR_DATE.YEAR;
  2848.     TEMP2 := CALENDAR_DATE.MONTH;
  2849.     TEMP1 := CALENDAR_DATE.DAY;
  2850.  
  2851.     if TEMP2 <= 2 then
  2852.         TEMP2 := TEMP2 + 9;
  2853.         TEMP3 := TEMP3 - 1;
  2854.     else
  2855.         TEMP2 := TEMP2 - 3;
  2856.     end if;
  2857.  
  2858.     TEMP3 := TEMP3 * 1461 / 4;
  2859.     return TEMP3 - 15256 + (153 * TEMP2 + 2) / 5 + TEMP1 - 1;
  2860.     end JULIAN_DATE;
  2861.  
  2862.  
  2863.  
  2864.     function CALENDAR_DATE (JULIAN_DATE : JULIAN_TYPE) return CALENDAR_TYPE is
  2865.     RETURN_DATE  : CALENDAR_TYPE;
  2866.     TEMP_JULIAN  : JULIAN_TYPE;
  2867.     TEMP1, TEMP2 : INTEGER; -- used for arithmetic
  2868.     begin
  2869.     TEMP_JULIAN := JULIAN_DATE + 15256;
  2870.     TEMP_JULIAN := 4 * TEMP_JULIAN + 3;
  2871.     RETURN_DATE.YEAR := TEMP_JULIAN / 1461;
  2872.     TEMP1 := TEMP_JULIAN mod 1461;
  2873.     TEMP1 := TEMP1 / 4 + 1;
  2874.     TEMP2 := (5 * TEMP1 - 3) / 153;
  2875.     TEMP1 := (5 * TEMP1 - 3) mod 153;
  2876.     RETURN_DATE.DAY := TEMP1 / 5 + 1;
  2877.  
  2878.     if TEMP2 >= 10 then
  2879.         RETURN_DATE.MONTH := TEMP2 - 9;
  2880.         RETURN_DATE.YEAR := RETURN_DATE.YEAR + 1;
  2881.     else
  2882.         RETURN_DATE.MONTH := TEMP2 + 3;
  2883.     end if;
  2884.  
  2885.     return RETURN_DATE;
  2886.     end CALENDAR_DATE;
  2887.  
  2888. end DATE_AND_TIME;
  2889.  
  2890.  
  2891.  
  2892.  
  2893. package STRING_UTILITIES is
  2894. -- Author   : M. K. McNair
  2895. -- Source:     Division Software Technology and Support
  2896. --             Western Development Laboratories
  2897. --             Ford Aerospace & Communications Corporation
  2898. --             ATTN:  Ada Tools Group
  2899. -- Date     : 8 March 1985
  2900. -- Summary  :
  2901. --   This package provides some simple string manipulation subprograms.
  2902.  
  2903.     function FIRST_NON_BLANK_CHARACTER_POSITION (IN_STRING : STRING)
  2904.                           return NATURAL;
  2905.     function LAST_NON_BLANK_CHARACTER_POSITION  (IN_STRING : STRING)
  2906.                           return NATURAL;
  2907.     function REMOVE_LEADING_AND_TRAILING_BLANKS (FROM_STRING : STRING)
  2908.                           return STRING;
  2909.  
  2910.     -- LOWER_TO_UPPER will return the upper case value of a string. All lower
  2911.     -- case characters in the string are swapped with upper case characters.
  2912.     -- Added by: Ken Lamarche
  2913.     -- Date:     7 May 1985
  2914.     function LOWER_TO_UPPER (OF_STRING : STRING) return STRING;
  2915.  
  2916.  
  2917. end STRING_UTILITIES;
  2918.  
  2919.  
  2920.  
  2921.  
  2922. package body STRING_UTILITIES is
  2923. -- Author  : M. K. McNair
  2924. -- Source:     Division Software Technology and Support
  2925. --             Western Development Laboratories
  2926. --             Ford Aerospace & Communications Corporation
  2927. --             ATTN:  Ada Tools Group
  2928. -- Date    : 8 March 1985
  2929. -- Summary :
  2930. --   This is the package body to the STRING_UTILITIES package.
  2931.  
  2932.  
  2933.     function FIRST_NON_BLANK_CHARACTER_POSITION (IN_STRING : STRING)
  2934.                           return NATURAL is
  2935.     COUNT : NATURAL;
  2936.     begin
  2937.     for INDEX in IN_STRING'RANGE loop
  2938.         COUNT := INDEX;
  2939.         exit when IN_STRING (COUNT) /= ' ';
  2940.     end loop;
  2941.  
  2942.     return COUNT;
  2943.     end FIRST_NON_BLANK_CHARACTER_POSITION;
  2944.  
  2945.  
  2946.  
  2947.     function LAST_NON_BLANK_CHARACTER_POSITION (IN_STRING : STRING)
  2948.                          return NATURAL is
  2949.     COUNT : NATURAL;
  2950.     begin
  2951.     for INDEX in reverse IN_STRING'RANGE loop
  2952.         COUNT := INDEX;
  2953.         exit when IN_STRING (COUNT) /= ' ';
  2954.     end loop;
  2955.  
  2956.     return COUNT;
  2957.     end LAST_NON_BLANK_CHARACTER_POSITION;
  2958.  
  2959.  
  2960.  
  2961.     function REMOVE_LEADING_AND_TRAILING_BLANKS (FROM_STRING : STRING)
  2962.                           return STRING is
  2963.     begin
  2964.     return FROM_STRING
  2965.           (FIRST_NON_BLANK_CHARACTER_POSITION (FROM_STRING) ..
  2966.            LAST_NON_BLANK_CHARACTER_POSITION (FROM_STRING));
  2967.     end REMOVE_LEADING_AND_TRAILING_BLANKS;
  2968.  
  2969.  
  2970.     -- The LOWER_TO_UPPER function returns a string that is the upper case image
  2971.     -- of the string passes it. All lower case characters of the passed string
  2972.     -- are swapped with upper case characters.
  2973.     -- Added by: Ken Lamarche
  2974.     -- Date:     7 May 1985
  2975.     function LOWER_TO_UPPER (OF_STRING : STRING) return STRING is
  2976.  
  2977.     STRING_TO_RETURN : STRING (OF_STRING'RANGE);
  2978.  
  2979.     function LOWER_TO_UPPER_CHAR (CHAR : CHARACTER) return CHARACTER is
  2980.  
  2981.         type LOWER_LETTERS is new CHARACTER range 'a' .. 'z';
  2982.  
  2983.         LITTLE : LOWER_LETTERS;
  2984.     begin
  2985.         -- Convert input character to a LOWER_LETTERS type. If it is not a
  2986.         -- lower case charcater, an exception will be raised and the same
  2987.         -- character will be returned.
  2988.         LITTLE := LOWER_LETTERS (CHAR);
  2989.         return CHARACTER'VAL
  2990.              ((CHARACTER'POS (CHAR) - CHARACTER'POS ('a')) +
  2991.               CHARACTER'POS ('A'));
  2992.     exception
  2993.         when CONSTRAINT_ERROR => 
  2994.         return CHAR;
  2995.     end LOWER_TO_UPPER_CHAR;
  2996.  
  2997.     begin
  2998.     for I in OF_STRING'RANGE loop
  2999.         STRING_TO_RETURN (I) := LOWER_TO_UPPER_CHAR (OF_STRING (I));
  3000.     end loop;
  3001.  
  3002.     return STRING_TO_RETURN;
  3003.  
  3004.     end LOWER_TO_UPPER;
  3005.  
  3006.  
  3007.  
  3008. end STRING_UTILITIES;
  3009.  
  3010.  
  3011.  
  3012.  
  3013. with TEXT_IO;
  3014.  
  3015. package FILE_OPS is
  3016. -- Author   : M. K. McNair
  3017. -- Source:     Division Software Technology and Support
  3018. --             Western Development Laboratories
  3019. --             Ford Aerospace & Communications Corporation
  3020. --             ATTN:  Ada Tools Group
  3021. -- Date     : 8 March 1985
  3022. -- Summary  :
  3023. --   This package provides procedures for handling the opening of
  3024. --   files in an interactive and localized manner.
  3025.  
  3026.     function FILE_EXISTS (WITH_NAME : STRING) return BOOLEAN;
  3027.  
  3028.     procedure OPEN (THE_FILE         : in out TEXT_IO.FILE_TYPE;
  3029.             WITH_NAME        : STRING := "";
  3030.             TO_MODE          : TEXT_IO.FILE_MODE := TEXT_IO.IN_FILE;
  3031.             WITH_OPTIONS     : STRING := "";
  3032.             CREATION_ENABLED : BOOLEAN := FALSE);
  3033.     -- similar to a Fortran OPEN with the CREATION_ENABLED flag
  3034.     -- available
  3035.  
  3036.     procedure CLOSE (THE_FILE : in out TEXT_IO.FILE_TYPE);
  3037.  
  3038.     procedure DELETE (THE_FILE : in out TEXT_IO.FILE_TYPE);
  3039.  
  3040.     procedure USER_OPEN (THE_FILE    : in out TEXT_IO.FILE_TYPE;
  3041.              WITH_PROMPT : STRING;
  3042.              TO_MODE     : TEXT_IO.FILE_MODE := TEXT_IO.IN_FILE);
  3043.     -- get a file name from the user and open the file to the indicated
  3044.     -- mode. If the actual pathname is desired just call
  3045.     -- TEXT_IO.NAME (THE_FILE)
  3046.  
  3047.     FILE_ALREADY_OPEN, ILLEGAL_FILE_NAME, SYSTEM_CANNOT_CREATE_FILE,
  3048.     SYSTEM_CANNOT_OPEN_FILE, FILE_NOT_OPEN, SYSTEM_CANNOT_DELETE_FILE,
  3049.     FILE_ALREADY_EXISTS : exception;
  3050.  
  3051. end FILE_OPS;
  3052.  
  3053.  
  3054.  
  3055.  
  3056. with STRING_UTILITIES,
  3057.      SCREEN_IO;
  3058.  
  3059. package body FILE_OPS is
  3060. -- Author   : M. K. McNair
  3061. -- Source:     Division Software Technology and Support
  3062. --             Western Development Laboratories
  3063. --             Ford Aerospace & Communications Corporation
  3064. --             ATTN:  Ada Tools Group
  3065. -- Date     : 8 March 1985
  3066. -- Summary  :
  3067. --   This is the body to the FILE_OPS package.
  3068.  
  3069.     function FILE_EXISTS (WITH_NAME : STRING) return BOOLEAN is
  3070.     THE_FILE : TEXT_IO.FILE_TYPE;
  3071.     begin
  3072.     OPEN (THE_FILE,
  3073.           STRING_UTILITIES.REMOVE_LEADING_AND_TRAILING_BLANKS (WITH_NAME));
  3074.     CLOSE (THE_FILE);
  3075.     return TRUE;
  3076.     exception
  3077.     when others => 
  3078.         return FALSE;
  3079.     end FILE_EXISTS;
  3080.  
  3081.     procedure OPEN (THE_FILE         : in out TEXT_IO.FILE_TYPE;
  3082.             WITH_NAME        : STRING := "";
  3083.             TO_MODE          : TEXT_IO.FILE_MODE := TEXT_IO.IN_FILE;
  3084.             WITH_OPTIONS     : STRING := "";
  3085.             CREATION_ENABLED : BOOLEAN := FALSE) is
  3086.     use STRING_UTILITIES;
  3087.     begin
  3088.     if CREATION_ENABLED then
  3089.         if FILE_EXISTS (WITH_NAME) then
  3090.         OPEN (THE_FILE, WITH_NAME, TO_MODE, WITH_OPTIONS);
  3091.         else
  3092.         TEXT_IO.CREATE
  3093.            (THE_FILE, TO_MODE,
  3094.             REMOVE_LEADING_AND_TRAILING_BLANKS (WITH_NAME));
  3095.         end if;
  3096.     else
  3097.         TEXT_IO.OPEN (THE_FILE, TO_MODE,
  3098.               REMOVE_LEADING_AND_TRAILING_BLANKS (WITH_NAME));
  3099.     end if;
  3100.     exception
  3101.     when TEXT_IO.STATUS_ERROR => 
  3102.         raise FILE_ALREADY_OPEN;
  3103.  
  3104.     when TEXT_IO.NAME_ERROR => 
  3105.         raise ILLEGAL_FILE_NAME;
  3106.  
  3107.     when TEXT_IO.USE_ERROR => 
  3108.         if CREATION_ENABLED then
  3109.         raise SYSTEM_CANNOT_CREATE_FILE;
  3110.         else
  3111.         raise SYSTEM_CANNOT_OPEN_FILE;
  3112.         end if;
  3113.     end OPEN;
  3114.  
  3115.     procedure CLOSE (THE_FILE : in out TEXT_IO.FILE_TYPE) is
  3116.     begin
  3117.     TEXT_IO.CLOSE (THE_FILE);
  3118.     exception
  3119.     when TEXT_IO.STATUS_ERROR => 
  3120.         raise FILE_NOT_OPEN;
  3121.     end CLOSE;
  3122.  
  3123.     procedure DELETE (THE_FILE : in out TEXT_IO.FILE_TYPE) is
  3124.     begin
  3125.     TEXT_IO.DELETE (THE_FILE);
  3126.     exception
  3127.     when TEXT_IO.STATUS_ERROR => 
  3128.         raise FILE_NOT_OPEN;
  3129.  
  3130.     when TEXT_IO.USE_ERROR => 
  3131.         raise SYSTEM_CANNOT_DELETE_FILE;
  3132.     end DELETE;
  3133.  
  3134.     procedure USER_OPEN (THE_FILE    : in out TEXT_IO.FILE_TYPE;
  3135.              WITH_PROMPT : STRING;
  3136.              TO_MODE     : TEXT_IO.FILE_MODE := TEXT_IO.IN_FILE) is
  3137.     use STRING_UTILITIES;
  3138.  
  3139.     BUFFER : STRING (1 .. 64);
  3140.     LAST   : NATURAL;
  3141.     begin
  3142.     -- get the pathname
  3143.     OPEN (THE_FILE,
  3144.           REMOVE_LEADING_AND_TRAILING_BLANKS
  3145.          (SCREEN_IO.RETURNED_STRING
  3146.              (PROMPT => WITH_PROMPT, CONFIRM => FALSE)), TO_MODE,
  3147.           CREATION_ENABLED => TRUE);
  3148.     exception
  3149.     when FILE_ALREADY_EXISTS => 
  3150.         begin
  3151.         OPEN (THE_FILE,
  3152.               REMOVE_LEADING_AND_TRAILING_BLANKS (BUFFER (1 .. LAST)),
  3153.               TO_MODE);
  3154.         exception
  3155.         when FILE_ALREADY_OPEN => 
  3156.             TEXT_IO.NEW_LINE;
  3157.             TEXT_IO.PUT_LINE
  3158.                ("That file is currently in use. Try again.");
  3159.             USER_OPEN (THE_FILE, WITH_PROMPT, TO_MODE);
  3160.         end;
  3161.  
  3162.     when ILLEGAL_FILE_NAME => 
  3163.         TEXT_IO.NEW_LINE;
  3164.         TEXT_IO.PUT_LINE ("Illegal file name. Try again.");
  3165.         USER_OPEN (THE_FILE, WITH_PROMPT, TO_MODE);
  3166.  
  3167.     when SYSTEM_CANNOT_CREATE_FILE | SYSTEM_CANNOT_OPEN_FILE => 
  3168.         TEXT_IO.NEW_LINE;
  3169.         TEXT_IO.PUT_LINE ("The system cannot handle file operations.");
  3170.         raise;
  3171.     end USER_OPEN;
  3172.  
  3173. end FILE_OPS;
  3174.  
  3175.  
  3176.  
  3177.  
  3178. package MATH_FUNCTIONS is
  3179. -- Author   : M. K. McNair
  3180. -- Source:     Division Software Technology and Support
  3181. --             Western Development Laboratories
  3182. --             Ford Aerospace & Communications Corporation
  3183. --             ATTN:  Ada Tools Group
  3184. -- Date     : 8 March 1985
  3185. -- Summary  :
  3186. --   This package makes use of the two CODY-WAITE implementation
  3187. --   packages to give the functionality listed.
  3188.  
  3189.     type D2_FLOAT_ARRAY is array (POSITIVE range <>, POSITIVE range <>)
  3190.                   of FLOAT;
  3191.  
  3192.  
  3193.     function  "**"                            (X, Y : FLOAT) return FLOAT;
  3194.     function  EXP                             (POWER : FLOAT) return FLOAT;
  3195.     procedure GAUSSIAN_ELIMINATION            (MATRIX : in out D2_FLOAT_ARRAY;
  3196.                            N      : INTEGER);
  3197.     function  INVERSE_NORMAL_FUNCTION         (REQUIRED_PROBABILITY : FLOAT;
  3198.                            TIME_EXPECTED_VALUE  : FLOAT;
  3199.                            TIME_VARIANCE        : FLOAT)
  3200.                             return FLOAT;
  3201.     function  LOG                             (X : FLOAT) return FLOAT;
  3202.     function  LOG10                           (X : FLOAT) return FLOAT;
  3203.     function  NORMAL_FUNCTION                
  3204.          (TIME_DIFFERENCE    : FLOAT;        -- required_time -
  3205.                              -- expected_time
  3206.           STANDARD_DEVIATION : FLOAT) return FLOAT;
  3207.     function  POLYNOMIAL                      (A, B, C, T : FLOAT) return FLOAT;
  3208.     function  TRUNCATE                        (VALUE : FLOAT) return INTEGER;
  3209.     function  TRUNCATE                        (VALUE : FLOAT) return FLOAT;
  3210.     function  TRUNCATED_RAYLEIGH_DISTRIBUTION (Y, T : FLOAT) return FLOAT;
  3211.  
  3212.     NEGATIVE_ARGUMENT_GIVEN, NEGATIVE_VALUE_GIVEN, ARGUMENT_TO_LARGE,
  3213.     ARGUMENT_TO_SMALL, A_ZERO_BASE_WAS_GIVEN, CALCULATED_VALUE_TO_BIG,
  3214.     CALCULATED_VALUE_TO_SMALL : exception;
  3215.  
  3216. end MATH_FUNCTIONS;
  3217.  
  3218.  
  3219.  
  3220.  
  3221. with FLOATING_CHARACTERISTICS,
  3222.      NUMERIC_PRIMITIVES;
  3223. use FLOATING_CHARACTERISTICS, NUMERIC_PRIMITIVES;
  3224.  
  3225. package body MATH_FUNCTIONS is
  3226. -- Author   : M. K. McNair
  3227. -- Source:     Division Software Technology and Support
  3228. --             Western Development Laboratories
  3229. --             Ford Aerospace & Communications Corporation
  3230. --             ATTN:  Ada Tools Group
  3231. -- Date     : 8 March 1985
  3232. -- Summary  :
  3233. --   This is the package body to the MATH_FUNCTIONS package. These
  3234. --   algorithms were originally implemented by Whitaker, et al.
  3235.  
  3236.     EXP_LARGE : FLOAT;
  3237.     EXP_SMALL : FLOAT;
  3238.  
  3239.     function "**" (X, Y : FLOAT) return FLOAT is
  3240.     M, N                                           : EXPONENT_TYPE;
  3241.     G                                              : MANTISSA_TYPE;
  3242.     P, TEMP, IW1, I                                : INTEGER;
  3243.     RESULT, Z, V, R, U1, U2, W, W1, W2, W3, Y1, Y2 : FLOAT;
  3244.     K                                              : constant FLOAT :=
  3245.                              0.44269_50408_88963_40736;
  3246.     IBIGX                                          : constant INTEGER :=
  3247.                              TRUNCATE (16.0 *
  3248.                                    LOG (XMAX) -
  3249.                                    1.0);
  3250.     ISMALLX                                        : constant INTEGER :=
  3251.                              TRUNCATE (16.0 *
  3252.                                    LOG (XMIN) +
  3253.                                    1.0);
  3254.     P1                                             : constant FLOAT :=
  3255.                              0.83333_32862_45e-1;
  3256.     P2                                             : constant FLOAT :=
  3257.                              0.12506_48500_52e-1;
  3258.     Q1                                             : constant FLOAT :=
  3259.                              0.69314_71805_56341;
  3260.     Q2                                             : constant FLOAT :=
  3261.                              0.24022_65061_44710;
  3262.     Q3                                             : constant FLOAT :=
  3263.                              0.55504_04881_30765e-1;
  3264.     Q4                                             : constant FLOAT :=
  3265.                              0.96162_06595_83789e-2;
  3266.     Q5                                             : constant FLOAT :=
  3267.                              0.13052_55159_42810e-2;
  3268.     A1                                             : array (1 .. 17)
  3269.                                     of FLOAT :=
  3270.                              (8#1.00000_0000#,
  3271.                               8#0.75222_5750#,
  3272.                               8#0.72540_3067#,
  3273.                               8#0.70146_3367#,
  3274.                               8#0.65642_3746#,
  3275.                               8#0.63422_2140#,
  3276.                               8#0.61263_4520#,
  3277.                               8#0.57204_2434#,
  3278.                               8#0.55202_3631#,
  3279.                               8#0.53254_0767#,
  3280.                               8#0.51377_3265#,
  3281.                               8#0.47572_4623#,
  3282.                               8#0.46033_7602#,
  3283.                               8#0.44341_7233#,
  3284.                               8#0.42712_7017#,
  3285.                               8#0.41325_3033#,
  3286.                               8#0.40000_0000#);
  3287.  
  3288.     A2                                             : array (1 .. 8)
  3289.                                     of FLOAT :=
  3290.                              (8#0.00000_00005_22220_66302_61734_72062#,
  3291.                               8#0.00000_00003_02522_47021_04062_61124#,
  3292.                               8#0.00000_00005_21760_44016_17421_53016#,
  3293.                               8#0.00000_00007_65401_41553_72504_02177#,
  3294.                               8#0.00000_00002_44124_12254_31114_01243#,
  3295.                               8#0.00000_00000_11064_10432_66404_42174#,
  3296.                               8#0.00000_00004_72542_16063_30176_55544#,
  3297.                               8#0.00000_00001_74611_03661_23056_22556#);
  3298.  
  3299.     function REDUCE (V : FLOAT) return FLOAT is
  3300.     begin
  3301.         return FLOAT (INTEGER (16.0 * V)) * 0.0625;
  3302.     end REDUCE;
  3303.  
  3304.     begin
  3305.     if X <= ZERO then
  3306.         if X < ZERO then
  3307.         RESULT := (abs (X)) ** Y;
  3308.         raise NEGATIVE_ARGUMENT_GIVEN;
  3309.         else
  3310.         if Y <= ZERO then
  3311.             if Y = ZERO then
  3312.             RESULT := ZERO;
  3313.             else
  3314.             RESULT := XMAX;
  3315.             end if;
  3316.  
  3317.             raise A_ZERO_BASE_WAS_GIVEN;
  3318.         else
  3319.             RESULT := ZERO;
  3320.         end if;
  3321.         end if;
  3322.     else
  3323.         DEFLOAT (X, M, G);
  3324.         P := 1;
  3325.  
  3326.         if G <= A1 (9) then
  3327.         P := 9;
  3328.         end if;
  3329.  
  3330.         if G <= A1 (P + 4) then
  3331.         P := P + 4;
  3332.         end if;
  3333.  
  3334.         if G <= A1 (P + 2) then
  3335.         P := P + 2;
  3336.         end if;
  3337.  
  3338.         Z := ((G - A1 (P + 1)) - A2 ((P + 1) / 2)) / (G + A1 (P + 1));
  3339.         Z := Z + Z;
  3340.         V := Z * Z;
  3341.         R := (P2 * V + P1) * V * Z;
  3342.         R := R + K * R;
  3343.         U2 := (R + Z * K) + Z;
  3344.         U1 := FLOAT (INTEGER (M) * 16 - P) * 0.0625;
  3345.         Y1 := REDUCE (Y);
  3346.         Y2 := Y - Y1;
  3347.         W := U2 * Y + U1 * Y2;
  3348.         W1 := REDUCE (W);
  3349.         W2 := W - W1;
  3350.         W := W1 + U1 * Y1;
  3351.         W1 := REDUCE (W);
  3352.         W2 := W2 + (W - W1);
  3353.         W3 := REDUCE (W2);
  3354.         IW1 := TRUNCATE (16.0 * (W1 + W3));
  3355.         W2 := W2 - W3;
  3356.  
  3357.         if W > FLOAT (IBIGX) then
  3358.         RESULT := XMAX;
  3359.         raise CALCULATED_VALUE_TO_BIG;
  3360.  
  3361.         elsif W < FLOAT (ISMALLX) then
  3362.         raise CALCULATED_VALUE_TO_SMALL;
  3363.         else
  3364.         if W2 > ZERO then
  3365.             W2 := W2 - 0.0625;
  3366.             IW1 := IW1 + 1;
  3367.         end if;
  3368.  
  3369.         if IW1 < INTEGER (ZERO) then
  3370.             I := 0;
  3371.         else
  3372.             I := 1;
  3373.         end if;
  3374.  
  3375.         M := EXPONENT_TYPE (I + IW1 / 16);
  3376.         P := 16 * INTEGER (M) - IW1;
  3377.         Z := ((((Q5 * W2 + Q4) * W2 + Q3) * W2 + Q2) * W2 + Q1) * W2;
  3378.         Z := A1 (P + 1) + (A1 (P + 1) * Z);
  3379.         REFLOAT (M, Z, RESULT);
  3380.         end if;
  3381.     end if;
  3382.  
  3383.     return RESULT;
  3384.     end "**";
  3385.  
  3386.     function EXP (POWER : FLOAT) return FLOAT is
  3387.     X              : FLOAT renames POWER;
  3388.     RESULT         : FLOAT;
  3389.     N              : EXPONENT_TYPE;
  3390.     XG, XN, X1, X2 : FLOAT;
  3391.     F, G           : MANTISSA_TYPE;
  3392.     BIGX           : FLOAT := EXP_LARGE;
  3393.     SMALLX         : FLOAT := EXP_SMALL;
  3394.     ONE_OVER_LOG_2 : constant FLOAT := 1.4426_95040_88896_34074;
  3395.     C1             : constant FLOAT := 0.69335_9375;
  3396.     C2             : constant FLOAT := -2.1219_44400_54690_58277e-4;
  3397.  
  3398.  
  3399.     function R (G : MANTISSA_TYPE) return MANTISSA_TYPE is
  3400.         Z, GP, Q : MANTISSA_TYPE;
  3401.         P0       : constant MANTISSA_TYPE := 0.24999_99999_9992;
  3402.         P1       : constant MANTISSA_TYPE := 0.00595_04254_9776;
  3403.         Q0       : constant MANTISSA_TYPE := 0.5;
  3404.         Q1       : constant MANTISSA_TYPE := 0.05356_75176_4522;
  3405.         Q2       : constant MANTISSA_TYPE := 0.00029_72936_3682;
  3406.     begin
  3407.         Z := MANTISSA_TYPE (G * G);
  3408.         GP := MANTISSA_TYPE ((MANTISSA_TYPE (P1 * Z) + P0) * G);
  3409.         Q := MANTISSA_TYPE ((MANTISSA_TYPE (Q2 * Z) + Q1) * Z) + Q0;
  3410.         return MANTISSA_HALF + MANTISSA_TYPE (GP / (Q - GP));
  3411.     end R;
  3412.     begin
  3413.     if X > BIGX then
  3414.         raise ARGUMENT_TO_LARGE;
  3415.  
  3416.     elsif X < SMALLX then
  3417.         raise ARGUMENT_TO_SMALL;
  3418.  
  3419.     elsif abs (X) < EPS then
  3420.         RESULT := ONE;
  3421.     else
  3422.         N := EXPONENT_TYPE (X * ONE_OVER_LOG_2);
  3423.         XN := CONVERT_TO_FLOAT (N);
  3424.         X1 := ROUND (X);
  3425.         X2 := X - X1;
  3426.         XG := ((X1 - XN * C1) + X2) - XN * C2;
  3427.         G := MANTISSA_TYPE (XG);
  3428.         N := N + 1;
  3429.         F := R (G);
  3430.         REFLOAT (N, F, RESULT);
  3431.     end if;
  3432.  
  3433.     return RESULT;
  3434.     exception
  3435.     when others => 
  3436.         return ONE;
  3437.     end EXP;
  3438.  
  3439.     function LOG (X : FLOAT) return FLOAT is
  3440.     RESULT        : FLOAT;
  3441.     N             : EXPONENT_TYPE;
  3442.     XN            : FLOAT;
  3443.     Y             : FLOAT;
  3444.     F             : MANTISSA_TYPE;
  3445.     Z, ZDEN, ZNUM : MANTISSA_TYPE;
  3446.     C0            : constant MANTISSA_TYPE := 0.20710_67811_86547_52440; --sqrt(0.5)
  3447.     C1            : constant FLOAT := 8#0.543#;
  3448.     C2            : constant FLOAT := -2.12194_44005_46905_82767_9e-4;
  3449.  
  3450.  
  3451.     function R (Z : MANTISSA_TYPE) return MANTISSA_TYPE is
  3452.         A0 : constant MANTISSA_TYPE := 0.04862_85276_587;
  3453.         B0 : constant MANTISSA_TYPE := 0.69735_92187_803;
  3454.         B1 : constant MANTISSA_TYPE := -0.125;
  3455.         C  : constant MANTISSA_TYPE := 0.01360_09546_862;
  3456.     begin
  3457.         return Z +
  3458.            MANTISSA_TYPE
  3459.               (Z *
  3460.                MANTISSA_TYPE
  3461.               (MANTISSA_TYPE (Z * Z) *
  3462.                (C +
  3463.                 MANTISSA_TYPE
  3464.                    (A0 /
  3465.                 (B0 +
  3466.                  MANTISSA_TYPE
  3467.                     (B1 * MANTISSA_TYPE (Z * Z)))))));
  3468.     end R;
  3469.     begin
  3470.     if X < ZERO then
  3471.         raise NEGATIVE_VALUE_GIVEN;
  3472.  
  3473.     elsif X = ZERO then
  3474.         RESULT := -XMAX;
  3475.     else
  3476.         DEFLOAT (X, N, F);
  3477.         ZNUM := F - MANTISSA_HALF;
  3478.         Y := CONVERT_TO_FLOAT (ZNUM);
  3479.         ZDEN := ZNUM / MANTISSA_DIVISOR_2 + MANTISSA_HALF;
  3480.  
  3481.         if ZNUM > C0 then
  3482.         Y := Y - MANTISSA_HALF;
  3483.         ZNUM := ZNUM - MANTISSA_HALF;
  3484.         ZDEN := ZDEN + MANTISSA_HALF / MANTISSA_DIVISOR_2;
  3485.         else
  3486.         N := N - 1;
  3487.         end if;
  3488.  
  3489.         Z := MANTISSA_TYPE (ZNUM / ZDEN);
  3490.         RESULT := CONVERT_TO_FLOAT (R (Z));
  3491.  
  3492.         if N /= 0 then
  3493.         XN := CONVERT_TO_FLOAT (N);
  3494.         RESULT := (XN * C2 + RESULT) + XN * C1;
  3495.         end if;
  3496.     end if;
  3497.  
  3498.     return RESULT;
  3499.     end LOG;
  3500.  
  3501.     function LOG10 (X : FLOAT) return FLOAT is
  3502.     begin
  3503.     return 1.0;
  3504.     end LOG10;
  3505.  
  3506.     function TRUNCATED_RAYLEIGH_DISTRIBUTION (Y, T : FLOAT) return FLOAT is
  3507.     VALUE1 : FLOAT := (0.15 * Y) + (0.7 * T);
  3508.     VALUE2 : FLOAT := Y * Y;
  3509.     begin
  3510.     return (VALUE1 / (0.25 * VALUE2)) *
  3511.            EXP (-((VALUE1) ** 2) / (0.5 * VALUE2));
  3512.     end TRUNCATED_RAYLEIGH_DISTRIBUTION;
  3513.  
  3514.     function POLYNOMIAL (A, B, C, T : FLOAT) return FLOAT is
  3515.     begin
  3516.     return A * (T * T) + B * T + C;
  3517.     end POLYNOMIAL;
  3518.  
  3519.     procedure GAUSSIAN_ELIMINATION (MATRIX : in out D2_FLOAT_ARRAY;
  3520.                     N      : INTEGER) is
  3521.     TEMP : FLOAT;
  3522.     A    : D2_FLOAT_ARRAY
  3523.          (1 .. MATRIX'LENGTH (1), 1 .. MATRIX'LENGTH (2)) := MATRIX;
  3524.     begin
  3525.     for KRR in 1 .. N loop
  3526.         for I in 1 .. N loop
  3527.         if A (I, KRR) /= 0.0 then
  3528.             TEMP := A (I, KRR);
  3529.  
  3530.             for J in 1 .. N + 1 loop
  3531.             A (I, J) := A (I, J) / TEMP;
  3532.             end loop;
  3533.         end if;
  3534.         end loop;
  3535.  
  3536.         for L in 1 .. N loop
  3537.         if (L /= KRR) and (A (L, KRR) /= 0.0) then
  3538.             for K in 1 .. N + 1 loop
  3539.             A (L, K) := A (L, K) - A (KRR, K);
  3540.             end loop;
  3541.         end if;
  3542.         end loop;
  3543.     end loop;
  3544.  
  3545.     for I in 1 .. N loop
  3546.         A (I, N + 1) := A (I, N + 1) / A (I, I);
  3547.         A (I, I) := 1.0;
  3548.     end loop;
  3549.  
  3550.     MATRIX := A;
  3551.     end GAUSSIAN_ELIMINATION;
  3552.  
  3553.     function TRUNCATE (VALUE : FLOAT) return INTEGER is
  3554.     begin
  3555.     return INTEGER (NUMERIC_PRIMITIVES.TRUNCATE (VALUE));
  3556.     end TRUNCATE;
  3557.  
  3558.     function TRUNCATE (VALUE : FLOAT) return FLOAT is
  3559.     begin
  3560.     return NUMERIC_PRIMITIVES.TRUNCATE (VALUE);
  3561.     end TRUNCATE;
  3562.  
  3563.     function INVERSE_NORMAL_FUNCTION (REQUIRED_PROBABILITY : FLOAT;
  3564.                       TIME_EXPECTED_VALUE  : FLOAT;
  3565.                       TIME_VARIANCE        : FLOAT)
  3566.                        return FLOAT is
  3567.     X                                                   : constant array (1 .. 6)
  3568.                                           of FLOAT :=
  3569.                                   (1 => 0.5,
  3570.                                    2 => 0.6,
  3571.                                    3 => 0.7,
  3572.                                    4 => 0.8,
  3573.                                    5 => 0.9,
  3574.                                    6 => 0.95);
  3575.     Y                                                   : constant array (1 .. 6)
  3576.                                           of FLOAT :=
  3577.                                   (1 => 0.0,
  3578.                                    2 => 0.253,
  3579.                                    3 => 0.525,
  3580.                                    4 => 0.842,
  3581.                                    5 => 1.282,
  3582.                                    6 => 1.645);
  3583.     ANSWER, COEFFICIENT, TEMP_PROBABILITY, SLOPE, PRINV : FLOAT;
  3584.     I                                                   : INTEGER;
  3585.     begin
  3586.     ANSWER := TIME_EXPECTED_VALUE;
  3587.  
  3588.     if TIME_VARIANCE >= 0.0001 then
  3589.         COEFFICIENT := 1.0;
  3590.         TEMP_PROBABILITY := REQUIRED_PROBABILITY;
  3591.  
  3592.         if REQUIRED_PROBABILITY < 0.5 then
  3593.         COEFFICIENT := -1.0;
  3594.         TEMP_PROBABILITY := 1.0 - REQUIRED_PROBABILITY;
  3595.         end if;
  3596.  
  3597.         if TEMP_PROBABILITY <= 0.95 then
  3598.         I := INTEGER (10.0 * (TEMP_PROBABILITY - 0.39999));
  3599.         SLOPE := (Y (I + 1) - Y (I)) / (X (I + 1) - X (I));
  3600.         PRINV := SLOPE * (TEMP_PROBABILITY - X (I)) + Y (I);
  3601.         else
  3602.         PRINV := (-1.68 * LOG (3.996 * (1.0 - TEMP_PROBABILITY))) **
  3603.              0.5;
  3604.         end if;
  3605.  
  3606.         return (TIME_VARIANCE ** 0.5) * COEFFICIENT * PRINV +
  3607.            TIME_EXPECTED_VALUE;
  3608.     end if;
  3609.  
  3610.     return ANSWER;
  3611.     end INVERSE_NORMAL_FUNCTION;
  3612.  
  3613.     function NORMAL_FUNCTION (TIME_DIFFERENCE    : FLOAT;
  3614. -- required_time - expected_time
  3615.  
  3616.  
  3617.                   STANDARD_DEVIATION : FLOAT) return FLOAT is
  3618.     RATIO, ANSWER : FLOAT;
  3619.     begin
  3620.     RATIO := TIME_DIFFERENCE / STANDARD_DEVIATION;
  3621.  
  3622.     if (RATIO >= -4.0) and (RATIO <= 4.0) then
  3623.         declare
  3624.         P : FLOAT := 0.0;
  3625.         M : INTEGER := 0;
  3626.         W : FLOAT;
  3627.         begin
  3628.         loop
  3629.             P := P + RATIO;
  3630.             M := M + 1;
  3631.             W := RATIO;
  3632.             RATIO := -((TIME_DIFFERENCE / STANDARD_DEVIATION) ** 2 *
  3633.                    FLOAT (2 * M - 1) /
  3634.                    (4.0 * FLOAT (M) ** 2 + FLOAT (2 * M))) * RATIO;
  3635.             exit when abs (W - RATIO) < 0.00001;
  3636.         end loop;
  3637.  
  3638.         ANSWER := 0.39894228 * P + 0.5;
  3639.         end;
  3640.     end if;
  3641.  
  3642.     if RATIO > 4.0 then
  3643.         ANSWER := 1.0;
  3644.  
  3645.     elsif RATIO < -4.0 then
  3646.         ANSWER := 0.0;
  3647.     end if;
  3648.  
  3649.     return ANSWER;
  3650.     end NORMAL_FUNCTION;
  3651.  
  3652. begin
  3653.     EXP_LARGE := LOG (XMAX) * (ONE - EPS);
  3654.     EXP_SMALL := LOG (XMIN) * (ONE - EPS);
  3655. end MATH_FUNCTIONS;
  3656.  
  3657.  
  3658.  
  3659.  
  3660. generic
  3661.     DISPLAY_WIDTH  : INTEGER := 80;
  3662.     DISPLAY_HEIGHT : INTEGER := 24;
  3663. package MENU is
  3664. -- Author : M.K. McNair
  3665. -- Source:     Division Software Technology and Support
  3666. --             Western Development Laboratories
  3667. --             Ford Aerospace & Communications Corporation
  3668. --             ATTN:  Ada Tools Group
  3669. -- Date   : 8 March 1985
  3670. -- Summary: This package provides a means for formatting and then
  3671. --          using menus. The menu constructed must fit into the
  3672. --          display restrictions given by DISPLAY_HEIGHT and
  3673. --          DISPLAY_WIDTH.
  3674.  
  3675.  
  3676.     type STRING_ACCESS_TYPE is access STRING;
  3677.  
  3678.     subtype MENU_LINE_TYPE is STRING_ACCESS_TYPE;
  3679.  
  3680.     type MENU_TYPE is array (POSITIVE range <>) of MENU_LINE_TYPE;
  3681.  
  3682.     NULL_LINE : constant MENU_LINE_TYPE := null;
  3683. -- this is a predefined constant which signifies a blank line upon
  3684. -- menu display
  3685.  
  3686.  
  3687.     procedure GET_MENU_VALUE (MENU_USED     : MENU_TYPE;
  3688.                   TITLE         : STRING_ACCESS_TYPE;
  3689.                   CHOICE_CHOSEN : out POSITIVE);
  3690. -- this is where the menu gets put out to TEXT_IO.STANDARD_OUTPUT
  3691.     MENU_TO_HIGH, MENU_TO_WIDE : exception;
  3692.  
  3693.  
  3694.     generic
  3695.     type MENU_ITEMS_TYPE is (<>);
  3696.     function ENUMERATION_MENU return MENU_TYPE;
  3697. -- This will create a menu from a list of items in an enumeration
  3698. -- type. Note that any underscores in the enumeration literals
  3699. -- will be displayed.
  3700.  
  3701.  
  3702.     type ITEM_ARRAY_TYPE is array (POSITIVE range <>) of STRING_ACCESS_TYPE;
  3703.  
  3704.     function STRING_MENU (ITEMS : ITEM_ARRAY_TYPE) return MENU_TYPE;
  3705. -- this will create a menu from an array of string access types
  3706.  
  3707. end MENU;
  3708.  
  3709.  
  3710.  
  3711.  
  3712. with TEXT_IO;
  3713.  
  3714. package body MENU is
  3715. -- Author : M. K. McNair
  3716. -- Source:     Division Software Technology and Support
  3717. --             Western Development Laboratories
  3718. --             Ford Aerospace & Communications Corporation
  3719. --             ATTN:  Ada Tools Group
  3720. -- Date   : 8 March 1985
  3721. -- Summary: This is the body to the MENU package. There are no global
  3722. --          variables so it is o.k. to use this package in a multi-
  3723. --          tasking environment. There are three procedures here.
  3724.  
  3725.  
  3726.     procedure GET_MENU_VALUE (MENU_USED     : MENU_TYPE;
  3727.                   TITLE         : STRING_ACCESS_TYPE;
  3728.                   CHOICE_CHOSEN : out POSITIVE) is
  3729. -- Summary: This procedure will display a menu with the given title,
  3730. --          all of which is centered on the screen. A prompt will be
  3731. --          given to the user to enter a choice. If an illegal choice
  3732. --          is entered, the menu will be redrawn and the prompt will
  3733. --          be repeated. Control will return only when a legal value
  3734. --          is entered.
  3735.  
  3736.  
  3737.     NUMBER_OF_CHOICES : constant INTEGER :=
  3738.                 MENU_USED'LAST - MENU_USED'FIRST + 1;
  3739.     TEMP_CHOICE       : INTEGER;
  3740.     VERTICAL_SPACING  : INTEGER;
  3741.     begin
  3742.     if NUMBER_OF_CHOICES > DISPLAY_HEIGHT - 2 then
  3743.         raise MENU_TO_HIGH;
  3744.     end if;
  3745.  
  3746.     -- for centering purposes, find the longest menu line
  3747.     declare
  3748.         LONGEST_MENU_LINE : INTEGER := MENU_USED (1).all'LENGTH;
  3749.     begin
  3750.         for INDEX in MENU_USED'FIRST .. MENU_USED'LAST loop
  3751.         if LONGEST_MENU_LINE < MENU_USED (INDEX).all'LENGTH then
  3752.             LONGEST_MENU_LINE := MENU_USED (INDEX).all'LENGTH;
  3753.         end if;
  3754.         end loop;
  3755.  
  3756.         if LONGEST_MENU_LINE > DISPLAY_WIDTH then
  3757.         raise MENU_TO_WIDE;
  3758.         end if;
  3759.     end;
  3760.  
  3761.     -- determine vertical spacing between title and menu and then menu
  3762.     -- and prompt
  3763.     VERTICAL_SPACING := (DISPLAY_HEIGHT - NUMBER_OF_CHOICES - 2) / 2;
  3764.     TEXT_IO.NEW_PAGE;
  3765.  
  3766.     -- if a title was given then put it out
  3767.     declare
  3768.         TITLE_SPACING : INTEGER := (DISPLAY_WIDTH - TITLE.all'LENGTH) / 2;
  3769.     begin
  3770.         TEXT_IO.SET_COL (TEXT_IO.COUNT (TITLE_SPACING));
  3771.         TEXT_IO.PUT_LINE (TITLE.all);
  3772.         TEXT_IO.NEW_LINE (TEXT_IO.COUNT (VERTICAL_SPACING));
  3773.     exception
  3774.         when CONSTRAINT_ERROR => 
  3775.         null;
  3776.     end;
  3777.  
  3778.     -- display the menu
  3779.     declare
  3780.         INDEX    : NATURAL := MENU_USED'FIRST - 1;
  3781.         END_LOOP : BOOLEAN := FALSE;
  3782.     begin
  3783.         loop
  3784.         INDEX := INDEX + 1;
  3785.  
  3786.         begin
  3787.             TEXT_IO.PUT_LINE (MENU_USED (INDEX).all);
  3788.         exception
  3789.             when CONSTRAINT_ERROR => 
  3790.             END_LOOP := TRUE;
  3791.         end;
  3792.  
  3793.         exit when END_LOOP;
  3794.         end loop;
  3795.     end;
  3796.  
  3797.     -- output prompt
  3798.     declare
  3799.         BUFFER         : STRING (1 .. 40) := (1 .. 40 => ' ');
  3800.         LENGTH         : NATURAL;
  3801.         INTEGER_CHOICE : INTEGER;
  3802.     begin
  3803.         begin
  3804.         TEXT_IO.NEW_LINE (TEXT_IO.COUNT (VERTICAL_SPACING));
  3805.         exception
  3806.         when CONSTRAINT_ERROR => 
  3807.             null;
  3808.         end;
  3809.  
  3810.         TEXT_IO.PUT ("What is your choice? ");
  3811.         TEXT_IO.GET_LINE (BUFFER, LENGTH);
  3812.  
  3813.         -- try to interpret prompt
  3814.         declare
  3815.         package INT_IO is new TEXT_IO.INTEGER_IO (INTEGER);
  3816.         begin
  3817.         -- looking for an integer
  3818.         INT_IO.GET (BUFFER, INTEGER_CHOICE, LENGTH);
  3819.         exception
  3820.         when others => 
  3821. -- integer within range not entered
  3822.             declare
  3823.             package FLT_IO is new TEXT_IO.FLOAT_IO (FLOAT);
  3824.  
  3825.             FLOAT_CHOICE : FLOAT;
  3826.             begin
  3827.             -- was a float entered?
  3828.             FLT_IO.GET (BUFFER, FLOAT_CHOICE, LENGTH);
  3829.             -- convert float to integer
  3830.             INTEGER_CHOICE := INTEGER (FLOAT_CHOICE);
  3831.             exception
  3832.             when others => 
  3833. -- nothing meaningful entered
  3834.                 INTEGER_CHOICE := 0;
  3835.             end;
  3836.         end;
  3837.  
  3838.         TEMP_CHOICE := INTEGER_CHOICE;
  3839.  
  3840.         if not (TEMP_CHOICE <= NUMBER_OF_CHOICES and TEMP_CHOICE > 0) then
  3841.         -- this test is used instead of raising CONSTRAINT_ERROR, since
  3842.         -- this makes it easier to use recursion
  3843.         GET_MENU_VALUE (MENU_USED, TITLE, TEMP_CHOICE);
  3844.         end if;
  3845.     end;
  3846.  
  3847.     CHOICE_CHOSEN := TEMP_CHOICE;
  3848.     end GET_MENU_VALUE;
  3849.  
  3850.     function ENUMERATION_MENU return MENU_TYPE is
  3851. -- Summary: Create an "Enumeration - Type Menu"
  3852.  
  3853.     MENU_SIZE : constant POSITIVE :=
  3854.             (MENU_ITEMS_TYPE'POS (MENU_ITEMS_TYPE'LAST) -
  3855.              MENU_ITEMS_TYPE'POS (MENU_ITEMS_TYPE'FIRST) + 1);
  3856.     -- front_spacing + max_item_number_width + between_spacing +
  3857.     --   max_item_length + between_spacing = display_width
  3858.     function SPACING_LENGTH return INTEGER is
  3859. -- Summary: It is assumed that all the spacing parameters are
  3860. --          equal. This provides that spacing value
  3861.         MAX_ITEM_LENGTH : NATURAL := 0;
  3862.         LENGTH          : POSITIVE;
  3863.         ITEM_LENGTH     : INTEGER;
  3864.     begin
  3865.         for ITEM in MENU_ITEMS_TYPE loop
  3866.         ITEM_LENGTH :=
  3867.           MENU_ITEMS_TYPE'IMAGE (ITEM)'LAST -
  3868.           MENU_ITEMS_TYPE'IMAGE (ITEM)'FIRST + 1;
  3869.  
  3870.         if MAX_ITEM_LENGTH < ITEM_LENGTH then
  3871.             MAX_ITEM_LENGTH := ITEM_LENGTH;
  3872.         end if;
  3873.         end loop;
  3874.  
  3875.         LENGTH := (DISPLAY_WIDTH -
  3876.                INTEGER'IMAGE
  3877.              (MENU_ITEMS_TYPE'POS (MENU_ITEMS_TYPE'LAST) + 1)
  3878.             'LENGTH + 1 - MAX_ITEM_LENGTH) / 3;
  3879.         return LENGTH;
  3880.     end SPACING_LENGTH;
  3881.  
  3882.  
  3883.     function ITEM_NUMBER (I : INTEGER) return STRING is
  3884. -- Summary: This converts an integer to a string
  3885.         MAX_ITEM_NUMBER : constant INTEGER := MENU_SIZE;
  3886.         I_STRING        : constant STRING := INTEGER'IMAGE (I);
  3887.     begin
  3888.         declare
  3889.         MAX_ITEM_NUMBER_STRING : constant STRING :=
  3890.                      INTEGER'IMAGE (MAX_ITEM_NUMBER);
  3891.         begin
  3892.         declare
  3893.             TEMP_STRING : STRING
  3894.                     (1 .. MAX_ITEM_NUMBER_STRING'LENGTH - 1) :=
  3895.                   (1 .. MAX_ITEM_NUMBER_STRING'LENGTH - 1 =>
  3896.                      ' ');
  3897.         begin
  3898.             TEMP_STRING (1 .. I_STRING'LENGTH - 1) :=
  3899.               I_STRING (I_STRING'FIRST + 1 .. I_STRING'LAST);
  3900.             return TEMP_STRING;
  3901.         exception
  3902.             when CONSTRAINT_ERROR => 
  3903.             return TEMP_STRING;
  3904.         end;
  3905.         end;
  3906.     end ITEM_NUMBER;
  3907.     begin
  3908.     declare
  3909.         MENU          : MENU_TYPE (1 .. MENU_SIZE);
  3910.         NUMBER_SPACES : INTEGER := SPACING_LENGTH;
  3911.     begin
  3912.         declare
  3913.         SCREEN_SPACING : STRING (1 .. NUMBER_SPACES) :=
  3914.                  (1 .. NUMBER_SPACES => ' ');
  3915.         begin
  3916. -- construct the mennu line-by-line
  3917.         for INDEX in 1 .. MENU_SIZE loop
  3918.             MENU (INDEX) :=
  3919.               new STRING'
  3920.                 (SCREEN_SPACING & ITEM_NUMBER (INDEX) &
  3921.                  SCREEN_SPACING &
  3922.                  MENU_ITEMS_TYPE'IMAGE
  3923.                    (MENU_ITEMS_TYPE'VAL (INDEX - 1)));
  3924.         end loop;
  3925.  
  3926.         return MENU;
  3927.         end;
  3928.     end;
  3929.     end ENUMERATION_MENU;
  3930.  
  3931.     function STRING_MENU (ITEMS : ITEM_ARRAY_TYPE) return MENU_TYPE is
  3932. -- Summary: This procedure creates a menu from an array of strings
  3933.  
  3934.     MENU_SIZE : constant POSITIVE := ITEMS'LENGTH;
  3935.     -- front_spacing + max_item_number_width + bewteen_spacing +
  3936.     --   max_item_length + between_spacing = display_width
  3937.     function SPACING_LENGTH return INTEGER is
  3938. -- Summary: Since the spacings above are assumed to be equal, this
  3939. --          function calculates the amount of that spacing.
  3940.  
  3941.         MAX_ITEM_LENGTH : NATURAL := 0;
  3942.         LENGTH          : POSITIVE;
  3943.         ITEM_LENGTH     : INTEGER;
  3944.     begin
  3945.         for ITEM in 1 .. MENU_SIZE loop
  3946.         ITEM_LENGTH := ITEMS (ITEM)'LENGTH;
  3947.  
  3948.         if MAX_ITEM_LENGTH < ITEM_LENGTH then
  3949.             MAX_ITEM_LENGTH := ITEM_LENGTH;
  3950.         end if;
  3951.         end loop;
  3952.  
  3953.         LENGTH := (DISPLAY_WIDTH - INTEGER'IMAGE (ITEMS'LAST + 1)'LENGTH +
  3954.                1 - MAX_ITEM_LENGTH) / 3;
  3955.         return LENGTH;
  3956.     end SPACING_LENGTH;
  3957.  
  3958.  
  3959.     function ITEM_NUMBER (I : INTEGER) return STRING is
  3960. -- Summary: This function will convert an integer to a string
  3961.  
  3962.         MAX_ITEM_NUMBER : constant INTEGER := MENU_SIZE;
  3963.         I_STRING        : constant STRING := INTEGER'IMAGE (I);
  3964.     begin
  3965.         declare
  3966.         MAX_ITEM_NUMBER_STRING : constant STRING :=
  3967.                      INTEGER'IMAGE (MAX_ITEM_NUMBER);
  3968.         begin
  3969.         declare
  3970.             TEMP_STRING : STRING
  3971.                     (1 .. MAX_ITEM_NUMBER_STRING'LENGTH - 1) :=
  3972.                   (1 .. MAX_ITEM_NUMBER_STRING'LENGTH - 1 =>
  3973.                      ' ');
  3974.         begin
  3975.             TEMP_STRING (1 .. I_STRING'LENGTH - 1) :=
  3976.               I_STRING (I_STRING'FIRST + 1 .. I_STRING'LAST);
  3977.             return TEMP_STRING;
  3978.         exception
  3979.             when CONSTRAINT_ERROR => 
  3980.             return TEMP_STRING;
  3981.         end;
  3982.         end;
  3983.     end ITEM_NUMBER;
  3984.     begin
  3985.     declare
  3986.         MENU          : MENU_TYPE (1 .. MENU_SIZE);
  3987.         NUMBER_SPACES : INTEGER := SPACING_LENGTH;
  3988.     begin
  3989.         declare
  3990.         SCREEN_SPACING : STRING (1 .. NUMBER_SPACES) :=
  3991.                  (1 .. NUMBER_SPACES => ' ');
  3992.         begin
  3993. -- The menu construction begins...
  3994.         for INDEX in 1 .. MENU_SIZE loop
  3995.             MENU (INDEX) :=
  3996.               new STRING'
  3997.                 (SCREEN_SPACING & ITEM_NUMBER (INDEX) &
  3998.                  SCREEN_SPACING & ITEMS (INDEX).all);
  3999.         end loop;
  4000.  
  4001.         return MENU;
  4002.         end;
  4003.     end;
  4004.     end STRING_MENU;
  4005. end MENU;
  4006.  
  4007.  
  4008.  
  4009.  
  4010. package MULTIPLE_CHOICE is
  4011. -- Author   : M. K. McNair
  4012. -- Source:     Division Software Technology and Support
  4013. --             Western Development Laboratories
  4014. --             Ford Aerospace & Communications Corporation
  4015. --             ATTN:  Ada Tools Group
  4016. -- Date     : 8 March 1985
  4017. -- Summary  :
  4018. --   This package implements a MULTIPLE_CHOICE scheme for getting input.
  4019. --   A multiple choice question is generalized to consist of:
  4020. -- 
  4021. --   Preceding text
  4022. --     ...
  4023. --   Choices
  4024. --     ...
  4025. --   Following text
  4026. --     ...
  4027. --   Prompt.
  4028.  
  4029.  
  4030.     type STRING_ACCESS_TYPE is access STRING;
  4031.  
  4032.     type TEXT_TYPE is array (POSITIVE range <>) of STRING_ACCESS_TYPE;
  4033.  
  4034.     generic
  4035.     type ANSWER_TYPE is (<>);
  4036.     procedure GET (ANSWER         : out ANSWER_TYPE;
  4037.            PRECEDING_TEXT : TEXT_TYPE;
  4038.            FOLLOWING_TEXT : TEXT_TYPE);
  4039.  
  4040. end MULTIPLE_CHOICE;
  4041.  
  4042.  
  4043.  
  4044.  
  4045. with TEXT_IO,
  4046.      FATAL;
  4047.  
  4048. package body MULTIPLE_CHOICE is
  4049. -- Author   : M. K. McNair
  4050. -- Source:     Division Software Technology and Support
  4051. --             Western Development Laboratories
  4052. --             Ford Aerospace & Communications Corporation
  4053. --             ATTN:  Ada Tools Group
  4054. -- Date     : 8 March 1985
  4055. -- Summary  :
  4056. --   This is the body to the MULTIPLE_CHOICE package.
  4057.  
  4058.     procedure GET (ANSWER         : out ANSWER_TYPE;
  4059.            PRECEDING_TEXT : TEXT_TYPE;
  4060.            FOLLOWING_TEXT : TEXT_TYPE) is
  4061.  
  4062.     package ANSWER_IO is new TEXT_IO.ENUMERATION_IO (ANSWER_TYPE);
  4063.  
  4064.     RESPONSE        : ANSWER_TYPE;
  4065.     BUFFER          : STRING (1 .. 128);
  4066.     TEMP_LAST, LAST : NATURAL;
  4067.  
  4068.     CHOICE_COLUMN   : constant TEXT_IO.COUNT := 5;
  4069.     begin
  4070.     for INDEX in PRECEDING_TEXT'RANGE loop
  4071.         TEXT_IO.PUT_LINE (PRECEDING_TEXT (INDEX).all);
  4072.     end loop;
  4073.  
  4074.     TEXT_IO.NEW_LINE;
  4075.  
  4076.     for INDEX in ANSWER_TYPE loop
  4077.         TEXT_IO.SET_COL (CHOICE_COLUMN);
  4078.         TEXT_IO.PUT ('(' & INTEGER'IMAGE (ANSWER_TYPE'POS (INDEX) + 1) &
  4079.              ")    ");
  4080.         TEXT_IO.PUT_LINE (ANSWER_TYPE'IMAGE (INDEX));
  4081.     end loop;
  4082.  
  4083.     TEXT_IO.NEW_LINE;
  4084.  
  4085.     for INDEX in FOLLOWING_TEXT'RANGE loop
  4086.         TEXT_IO.PUT_LINE (FOLLOWING_TEXT (INDEX).all);
  4087.     end loop;
  4088.  
  4089.     TEXT_IO.NEW_LINE;  TEXT_IO.PUT ("? ");
  4090.     TEXT_IO.GET_LINE (BUFFER, LAST);
  4091.     ANSWER_IO.GET (BUFFER (1 .. LAST), RESPONSE, TEMP_LAST);
  4092.     ANSWER := RESPONSE;
  4093.     exception
  4094.     when TEXT_IO.DATA_ERROR | CONSTRAINT_ERROR => 
  4095.         declare
  4096.         NUMBER : INTEGER;
  4097.  
  4098.         package INT_IO is new TEXT_IO.INTEGER_IO (INTEGER);
  4099.         begin
  4100.         -- did the user type in the number instead??
  4101.         INT_IO.GET (BUFFER (1 .. LAST), NUMBER, TEMP_LAST);
  4102.         ANSWER := ANSWER_TYPE'VAL (NUMBER - 1);
  4103.         exception
  4104.         when TEXT_IO.DATA_ERROR | CONSTRAINT_ERROR => 
  4105.             TEXT_IO.NEW_LINE;
  4106.             TEXT_IO.PUT_LINE ("Invalid response.");
  4107.             TEXT_IO.NEW_LINE;
  4108.             GET (ANSWER, PRECEDING_TEXT, FOLLOWING_TEXT);
  4109.         end;
  4110.  
  4111.     when TEXT_IO.END_ERROR => 
  4112.         TEXT_IO.NEW_LINE;
  4113.         GET (ANSWER, PRECEDING_TEXT, FOLLOWING_TEXT);
  4114.  
  4115.     when others => 
  4116.         FATAL (UNIT => "multiple_choice.get");
  4117.     end GET;
  4118.  
  4119. end MULTIPLE_CHOICE;
  4120.  
  4121.  
  4122.  
  4123.  
  4124. with TEXT_IO;
  4125. generic
  4126.     DISPLAY_WIDTH  : POSITIVE := 80;
  4127.     DISPLAY_HEIGHT : POSITIVE := 24;
  4128. package CHARTS is
  4129. -- Author : M. K. McNair
  4130. -- Source:     Division Software Technology and Support
  4131. --             Western Development Laboratories
  4132. --             Ford Aerospace & Communications Corporation
  4133. --             ATTN:  Ada Tools Group
  4134. -- Date   : 8 March 1985
  4135. -- Summary: This package provides a data structure and a "hands-off"
  4136. --          means of outputing charts. A chart is composed of a two-
  4137. --          dimensional matrix where each element of the matrix can
  4138. --          be either a string, integer or float. There are three
  4139. --          restrictions to the construction of a chart: it must fit
  4140. --          the above DISPLAY_WIDTH and DISPLAY_HEIGHT parameters,
  4141. --          there must be enough storage to store the chart in
  4142. --          memory, and the output file must be open for output.
  4143. --          As a possible solution to storage problems, consider
  4144. --          declaring an access type to CHART_TYPE and then allocating
  4145. --          the chart when needed. When it is no longer required,
  4146. --          then use UNCHECKED_DEALLOCATION to deallocate the chart.
  4147.  
  4148.  
  4149.     type STRING_ACCESS_TYPE is access STRING;
  4150.     type TITLE_ARRAY        is array (POSITIVE range <>) of STRING_ACCESS_TYPE;
  4151.     type ELEMENT_TYPE is (STRNG, INT, REAL);
  4152.     type CHART_ELEMENT_TYPE (KIND_OF_ELEMENT : ELEMENT_TYPE := STRNG) is
  4153.     record
  4154.         WIDTH : NATURAL := 0;
  4155.         -- width being 0 implies the smallest width required to fit the
  4156.         -- value
  4157.         case KIND_OF_ELEMENT is
  4158.         when STRNG => 
  4159.             STRING_VALUE : STRING_ACCESS_TYPE;
  4160.             -- value of null implies a blank line
  4161.         when INT => 
  4162.             INTEGER_VALUE : INTEGER;
  4163.  
  4164.         when REAL => 
  4165.             FLOAT_VALUE : FLOAT;
  4166.             AFT         : INTEGER := 2;
  4167.         end case;
  4168.     end record;
  4169.     type CHART_TYPE is array (POSITIVE range <>, POSITIVE range <>)
  4170.                   of CHART_ELEMENT_TYPE;
  4171. -- the first index is the row number, the second index is the column number
  4172.  
  4173.     procedure OUTPUT (THE_CHART  : CHART_TYPE;
  4174.               WITH_TITLE : TITLE_ARRAY;
  4175.               TO_FILE    : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT);
  4176.  
  4177.     procedure CLEANUP (THE_TITLE : in out TITLE_ARRAY);
  4178.     procedure CLEANUP (THE_CHART : in out CHART_TYPE);
  4179.  
  4180.     OUTPUT_ALREADY_OPEN, OUTPUT_NOT_OPEN, CHART_TO_WIDE, CHART_TO_TALL : exception;
  4181. -- note: STORAGE_ERROR is not listed here since, if it is to be raised,
  4182. --       it will be raised at the point where the chart is declared.
  4183. end CHARTS;
  4184.  
  4185. with FATAL,
  4186.      UNCHECKED_DEALLOCATION;
  4187. -- This is an error reporting subprogram
  4188.  
  4189.  
  4190.  
  4191.  
  4192.  
  4193. package body CHARTS is
  4194. -- Author : M. K. McNair
  4195. -- Source:     Division Software Technology and Support
  4196. --             Western Development Laboratories
  4197. --             Ford Aerospace & Communications Corporation
  4198. --             ATTN:  Ada Tools Group
  4199. -- Date   : 8 March 1985
  4200. -- Summary: This is the body to the CHARTS package. There are no global
  4201. --          variables, so it is o.k. to use this package in a multi-
  4202. --          tasking environment.
  4203.  
  4204.  
  4205.     procedure FREE is new UNCHECKED_DEALLOCATION (STRING, STRING_ACCESS_TYPE);
  4206.  
  4207.     package FLT_IO is new TEXT_IO.FLOAT_IO (FLOAT);
  4208.  
  4209.     procedure OUTPUT (THE_CHART  : CHART_TYPE;
  4210.               WITH_TITLE : TITLE_ARRAY;
  4211.               TO_FILE    : TEXT_IO.FILE_TYPE :=
  4212.                    TEXT_IO.CURRENT_OUTPUT) is
  4213.     FILE_LINE_LENGTH : TEXT_IO.COUNT := TEXT_IO.LINE_LENGTH (TO_FILE);
  4214.     TITLE            : TITLE_ARRAY renames WITH_TITLE;
  4215.     ROW_OFFSET       : NATURAL;
  4216.  
  4217.     procedure OUTPUT_STRING (WITH_VALUE : STRING;
  4218.                  AND_WIDTH  : NATURAL;
  4219.                  TO_FILE    : TEXT_IO.FILE_TYPE) is
  4220.  
  4221. -- Summary: This procedure will output a string with the specified
  4222. --          width to the specified file. The file must already be
  4223. --          open for output.
  4224.  
  4225.         VALUE : STRING renames WITH_VALUE;
  4226.         WIDTH : NATURAL renames AND_WIDTH;
  4227.         FILE  : TEXT_IO.FILE_TYPE renames TO_FILE;
  4228.     begin
  4229.         if (WIDTH = 0) or (WIDTH = VALUE'LENGTH) then
  4230.         -- if actual width indicated ....
  4231.         TEXT_IO.PUT (FILE, VALUE);
  4232.  
  4233.         elsif WIDTH > VALUE'LENGTH then
  4234.         -- leading blanks need to be attached
  4235.         TEXT_IO.SET_COL
  4236.            (FILE,
  4237.             TEXT_IO.COUNT
  4238.                (INTEGER (TEXT_IO.COL (FILE)) + WIDTH - VALUE'LENGTH));
  4239.         TEXT_IO.PUT (FILE, VALUE);
  4240.         else
  4241.         -- the string needs to be truncated
  4242.         TEXT_IO.PUT (FILE,
  4243.                  VALUE (VALUE'FIRST .. VALUE'FIRST + WIDTH - 1));
  4244.         end if;
  4245.     exception
  4246.         when others => 
  4247.         raise;
  4248.     end OUTPUT_STRING;
  4249.  
  4250.     begin
  4251.     -- set the output file's line length to display_width
  4252.     TEXT_IO.SET_LINE_LENGTH (TO_FILE, TEXT_IO.COUNT (DISPLAY_WIDTH));
  4253.  
  4254.     -- Find longest line and then provide a line offset - that way,
  4255.     -- all the lines will be centered within the DISPLAY_WIDTH.
  4256.     declare
  4257.         LENGTH, MAX_LENGTH : NATURAL := 0;
  4258.     begin
  4259.         for ROW in THE_CHART'RANGE (1) loop
  4260.         LENGTH := 0;
  4261.  
  4262.         for COLUMN in THE_CHART'RANGE (2) loop
  4263.             declare
  4264.             ELEMENT : constant CHART_ELEMENT_TYPE :=
  4265.                   THE_CHART (ROW, COLUMN);
  4266.             begin
  4267.             if ELEMENT.WIDTH > 0 then
  4268.                 LENGTH := LENGTH + ELEMENT.WIDTH;
  4269.             else
  4270.                 case ELEMENT.KIND_OF_ELEMENT is
  4271.                 when STRNG => 
  4272.                     begin
  4273.                     LENGTH :=
  4274.                       LENGTH +
  4275.                       ELEMENT.STRING_VALUE.all'LENGTH;
  4276.                     exception
  4277.                     when CONSTRAINT_ERROR => 
  4278.                         null;
  4279.                     end;
  4280.  
  4281.                 when INT => 
  4282.                     LENGTH :=
  4283.                       LENGTH +
  4284.                       INTEGER'IMAGE (ELEMENT.INTEGER_VALUE)
  4285.                        'LENGTH;
  4286.  
  4287.                 when REAL => 
  4288.                     declare
  4289.                     TEMP_STRING : STRING (1 .. 60);
  4290.                     FIRST       : NATURAL;
  4291.                     begin
  4292.                     FLT_IO.PUT
  4293.                        (TEMP_STRING, ELEMENT.FLOAT_VALUE,
  4294.                         EXP => 0, AFT => ELEMENT.AFT);
  4295.  
  4296.                     for INDEX in 1 .. 60 loop
  4297.                         FIRST := INDEX;
  4298.                         exit when TEMP_STRING (INDEX) /=
  4299.                               ' ';
  4300.                     end loop;
  4301.  
  4302.                     LENGTH := LENGTH + 60 - FIRST + 1;
  4303.                     end;
  4304.                 end case;
  4305.             end if;
  4306.             end;
  4307.         end loop;
  4308.  
  4309.         if LENGTH > MAX_LENGTH then
  4310.             MAX_LENGTH := LENGTH;
  4311.         end if;
  4312.         end loop;
  4313.  
  4314.         ROW_OFFSET := (DISPLAY_WIDTH - MAX_LENGTH) / 2;
  4315.     exception
  4316.         when CONSTRAINT_ERROR => 
  4317.         raise CHART_TO_WIDE;
  4318.     end;
  4319.  
  4320.     -- put out centered title ...
  4321.     declare
  4322.         SPACING : NATURAL;
  4323.     begin
  4324.         TEXT_IO.NEW_PAGE (TO_FILE);
  4325.         SPACING := (DISPLAY_HEIGHT - TITLE'LENGTH -
  4326.             THE_CHART'LENGTH (1)) / 2;
  4327.  
  4328.         for INDEX in TITLE'RANGE loop
  4329.         declare
  4330.             CENTER : NATURAL;
  4331.         begin
  4332.             CENTER := (DISPLAY_WIDTH - TITLE (INDEX).all'LENGTH) / 2;
  4333.             TEXT_IO.SET_COL (TO_FILE, TEXT_IO.COUNT (CENTER));
  4334.             TEXT_IO.PUT_LINE (TO_FILE, TITLE (INDEX).all);
  4335.         exception
  4336.             when CONSTRAINT_ERROR => 
  4337.             if TITLE (INDEX) /= null then
  4338.                 -- i.e. title line to long
  4339.                 raise;
  4340.             else
  4341.                 TEXT_IO.NEW_LINE (TO_FILE);
  4342.             end if;
  4343.         end;
  4344.         end loop;
  4345.  
  4346.         if SPACING > 0 then
  4347.         TEXT_IO.NEW_LINE (TO_FILE, TEXT_IO.COUNT (SPACING));
  4348.         end if;
  4349.     exception
  4350.         when CONSTRAINT_ERROR => 
  4351.         raise CHART_TO_TALL;
  4352.     end;
  4353.  
  4354.     -- put out chart
  4355.     for ROW in THE_CHART'FIRST (1) .. THE_CHART'LAST (1) loop
  4356.         TEXT_IO.PUT (TO_FILE, (1 .. ROW_OFFSET => ' '));
  4357.  
  4358.         for COLUMN in THE_CHART'FIRST (2) .. THE_CHART'LAST (2) loop
  4359.         declare
  4360.             ELEMENT : constant CHART_ELEMENT_TYPE :=
  4361.                   THE_CHART (ROW, COLUMN);
  4362.             FILE    : TEXT_IO.FILE_TYPE renames TO_FILE;
  4363.         begin
  4364.             case ELEMENT.KIND_OF_ELEMENT is
  4365.             when STRNG => 
  4366.                 begin
  4367.                 OUTPUT_STRING
  4368.                    (WITH_VALUE => ELEMENT.STRING_VALUE.all,
  4369.                     AND_WIDTH  => ELEMENT.WIDTH,
  4370.                     TO_FILE    => FILE);
  4371.                 exception
  4372.                 when CONSTRAINT_ERROR =>  -- blank field desired
  4373.                     begin
  4374.                     TEXT_IO.SET_COL
  4375.                        (FILE,
  4376.                         TEXT_IO.COUNT
  4377.                            (INTEGER (TEXT_IO.COL (FILE)) +
  4378.                         ELEMENT.WIDTH));
  4379.                     exception
  4380.                     when TEXT_IO.LAYOUT_ERROR => 
  4381.                         null;
  4382.                     end;
  4383.                 end;
  4384.  
  4385.             when INT => 
  4386.                 OUTPUT_STRING
  4387.                    (WITH_VALUE => INTEGER'IMAGE
  4388.                         (ELEMENT.INTEGER_VALUE),
  4389.                 AND_WIDTH  => ELEMENT.WIDTH,
  4390.                 TO_FILE    => FILE);
  4391.  
  4392.             when REAL => 
  4393.                 declare
  4394.                 TEMP_STRING : STRING (1 .. 60);
  4395.                 FIRST       : NATURAL;
  4396.                 begin
  4397.                 FLT_IO.PUT
  4398.                    (TEMP_STRING, ELEMENT.FLOAT_VALUE,
  4399.                     EXP => 0, AFT => ELEMENT.AFT);
  4400.  
  4401.                 for INDEX in 1 .. 60 loop
  4402.                     FIRST := INDEX;
  4403.                     exit when TEMP_STRING (INDEX) /= ' ';
  4404.                 end loop;
  4405.  
  4406.                 OUTPUT_STRING
  4407.                    (WITH_VALUE => TEMP_STRING (FIRST .. 60),
  4408.                     AND_WIDTH  => ELEMENT.WIDTH,
  4409.                     TO_FILE    => FILE);
  4410.                 end;
  4411.             end case;
  4412.         exception
  4413.             when others => 
  4414.             raise;
  4415.         end;
  4416.         end loop;
  4417.  
  4418.         TEXT_IO.NEW_LINE (TO_FILE);
  4419.     end loop;
  4420.  
  4421.     -- restore line length
  4422.     TEXT_IO.SET_LINE_LENGTH (TO_FILE, FILE_LINE_LENGTH);
  4423.     exception
  4424.     when TEXT_IO.STATUS_ERROR => 
  4425.         TEXT_IO.SET_LINE_LENGTH (TO_FILE, FILE_LINE_LENGTH);
  4426.         raise OUTPUT_NOT_OPEN;
  4427.  
  4428.     when TEXT_IO.MODE_ERROR => 
  4429.         TEXT_IO.SET_LINE_LENGTH (TO_FILE, FILE_LINE_LENGTH);
  4430.         raise OUTPUT_ALREADY_OPEN;
  4431.  
  4432.     when TEXT_IO.LAYOUT_ERROR => 
  4433.         TEXT_IO.SET_LINE_LENGTH (TO_FILE, FILE_LINE_LENGTH);
  4434.         raise CHART_TO_WIDE;
  4435.  
  4436.     when CHART_TO_WIDE => 
  4437.         TEXT_IO.SET_LINE_LENGTH (TO_FILE, FILE_LINE_LENGTH);
  4438.         raise;
  4439.  
  4440.     when CHART_TO_TALL => 
  4441.         TEXT_IO.SET_LINE_LENGTH (TO_FILE, FILE_LINE_LENGTH);
  4442.         raise;
  4443.  
  4444.     when others => 
  4445.         FATAL (UNIT => "charts.output");
  4446.         raise;
  4447.     end OUTPUT;
  4448.  
  4449.     procedure CLEANUP (THE_TITLE : in out TITLE_ARRAY) is
  4450.     begin
  4451.     for INDEX in THE_TITLE'RANGE loop
  4452.         FREE (THE_TITLE (INDEX));
  4453.     end loop;
  4454.     end CLEANUP;
  4455.  
  4456.     procedure CLEANUP (THE_CHART : in out CHART_TYPE) is
  4457.     begin
  4458.     for FIRST_INDEX in THE_CHART'RANGE (1) loop
  4459.         for SECOND_INDEX in THE_CHART'RANGE (2) loop
  4460.         if THE_CHART (FIRST_INDEX, SECOND_INDEX).KIND_OF_ELEMENT =
  4461.            STRNG then
  4462.             FREE (THE_CHART (FIRST_INDEX, SECOND_INDEX).STRING_VALUE);
  4463.         end if;
  4464.         end loop;
  4465.     end loop;
  4466.     end CLEANUP;
  4467.  
  4468. end CHARTS;
  4469.  
  4470.  
  4471.  
  4472.  
  4473.  
  4474. generic
  4475.     type ARC_DATA_TYPE  is private;
  4476.     type NODE_DATA_TYPE is private;
  4477. package GRAPHS is
  4478.     type NODE_TYPE  is private;
  4479.     type ARC_TYPE   is private;
  4480.     type GRAPH_TYPE is limited private;
  4481.  
  4482.     procedure CREATE_ARC                      (WITH_VALUE   : ARC_DATA_TYPE;
  4483.                            BETWEEN_NODE : NODE_TYPE;
  4484.                            AND_NODE     : NODE_TYPE);
  4485.     function  NEW_NODE                       
  4486.          (WITH_VALUE                      : NODE_DATA_TYPE;
  4487.           MAXIMUM_NUMBER_OF_INCOMING_ARCS : NATURAL;
  4488.           MAXIMUM_NUMBER_OF_OUTGOING_ARCS : NATURAL;
  4489.           IN_GRAPH                        : GRAPH_TYPE)
  4490.                             return NODE_TYPE;
  4491.     procedure CREATE                         
  4492.          (A_GRAPH                 : in out GRAPH_TYPE;
  4493.           WITH_START_NODE         : NODE_TYPE;
  4494.           WITH_END_NODE           : NODE_TYPE;
  4495.           MAXIMUM_NUMBER_OF_NODES : NATURAL);
  4496.     procedure SET_END_NODE                    (TO_VALUE : NODE_TYPE;
  4497.                            IN_GRAPH : GRAPH_TYPE);
  4498.     procedure SET_START_NODE                  (TO_VALUE : NODE_TYPE;
  4499.                            IN_GRAPH : GRAPH_TYPE);
  4500.     procedure DELETE                          (THE_NODE : in out NODE_TYPE);
  4501.     procedure DELETE                          (THE_ARC : in out ARC_TYPE);
  4502.     function  CURRENT_NUMBER_OF_INCOMING_ARCS (ON_NODE : NODE_TYPE)
  4503.                             return NATURAL;
  4504.     function  CURRENT_NUMBER_OF_OUTGOING_ARCS (ON_NODE : NODE_TYPE)
  4505.                             return NATURAL;
  4506.     function  MAXIMUM_NUMBER_OF_INCOMING_ARCS (ON_NODE : NODE_TYPE)
  4507.                             return NATURAL;
  4508.     function  MAXIMUM_NUMBER_OF_OUTGOING_ARCS (ON_NODE : NODE_TYPE)
  4509.                             return NATURAL;
  4510.     function  HEAD_NODE                       (OF_ARC : ARC_TYPE)
  4511.                             return NODE_TYPE;
  4512.     function  TAIL_NODE                       (OF_ARC : ARC_TYPE)
  4513.                             return NODE_TYPE;
  4514.     function  START_NODE                      (OF_GRAPH : GRAPH_TYPE)
  4515.                             return NODE_TYPE;
  4516.     function  END_NODE                        (OF_GRAPH : GRAPH_TYPE)
  4517.                             return NODE_TYPE;
  4518.     function  VALUE                           (OF_ARC : ARC_TYPE)
  4519.                             return ARC_DATA_TYPE;
  4520.     function  VALUE                           (OF_NODE : NODE_TYPE)
  4521.                             return NODE_DATA_TYPE;
  4522.     procedure ASSIGN_VALUE                    (OF_NODE  : NODE_TYPE;
  4523.                            TO_NODE  : in out NODE_TYPE;
  4524.                            IN_GRAPH : GRAPH_TYPE);
  4525.  
  4526.     type ARC_LIST_TYPE is array (INTEGER range <>) of ARC_TYPE;
  4527.     function ARC (WITH_TAIL : NODE_TYPE;
  4528.           WITH_HEAD : NODE_TYPE) return ARC_LIST_TYPE;
  4529.  
  4530.     procedure ASSIGN (VALUE : NODE_DATA_TYPE; TO_NODE : NODE_TYPE);
  4531.  
  4532.     procedure ASSIGN (VALUE : ARC_DATA_TYPE; TO_ARC : ARC_TYPE);
  4533.  
  4534.     type NODE_LIST_TYPE is array (INTEGER range <>) of NODE_TYPE;
  4535.  
  4536.     function  INCOMING_ARCS (ON_NODE : NODE_TYPE) return ARC_LIST_TYPE;
  4537.     function  OUTGOING_ARCS (ON_NODE : NODE_TYPE) return ARC_LIST_TYPE;
  4538.     function  NODES         (ON_GRAPH : GRAPH_TYPE) return NODE_LIST_TYPE;
  4539.     procedure TOPSORT       (NODE_LIST : in out NODE_LIST_TYPE);
  4540.  
  4541.  
  4542. -- misc functions
  4543.     function LIST_OF_SINKS   (IN_GRAPH : GRAPH_TYPE) return NODE_LIST_TYPE;
  4544.     function LIST_OF_SOURCES (IN_GRAPH : GRAPH_TYPE) return NODE_LIST_TYPE;
  4545.     function ANY_CYCLES      (IN_GRAPH : GRAPH_TYPE) return BOOLEAN;
  4546.  
  4547.  
  4548. -- exceptions
  4549.     HEAD_NODE_DOES_NOT_EXIST,
  4550. -- raised in: create_arc
  4551.  
  4552.  
  4553.  
  4554.  
  4555.  
  4556.     TAIL_NODE_DOES_NOT_EXIST,
  4557. -- raised in: create_arc
  4558.  
  4559.  
  4560.  
  4561.  
  4562.  
  4563.     MAXIMUM_NUMBER_OF_NODES_SPECIFIED_IN_GRAPH,
  4564. -- raised in: new_node
  4565.  
  4566.  
  4567.  
  4568.     NOT_ENOUGH_STORAGE_REMAINING,
  4569. -- raised in: create_arc,
  4570. --            new_node,
  4571. --            create
  4572.  
  4573.  
  4574.  
  4575.  
  4576.     END_NODE_ALREADY_EXISTS,
  4577. -- raised in: set_end_node
  4578.  
  4579.  
  4580.  
  4581.  
  4582.     START_NODE_ALREADY_EXISTS,
  4583. -- raised in: set_start_node
  4584.  
  4585.  
  4586.  
  4587.  
  4588.     ARC_DOES_NOT_EXIST,
  4589. -- raised in: head_node,
  4590. --            tail_node,
  4591. --            value (of_arc)
  4592.  
  4593.  
  4594.  
  4595.  
  4596.  
  4597.     ITERATION_IN_PROGRESS,
  4598. -- raised in: start_incoming_arc_iteration,
  4599. --            start_outgoing_arc_iteration,
  4600. --            start_node_iteration,
  4601. --            start_arc_iteration
  4602.  
  4603.  
  4604.  
  4605.  
  4606.     NODE_DOES_NOT_EXIST,
  4607. -- raised in: current_number_of_incoming_arcs,
  4608. --            current_number_of_outgoing_arcs,
  4609. --            value (of_node),
  4610. --            start_incoming_arc_iteration,
  4611. --            more_incoming_arcs
  4612. --            current_incoming_arc,
  4613. --            start_outgoing_arc_iteration,
  4614. --            more_outgoing_arcs,
  4615. --            current_outgoing_arc
  4616.  
  4617.  
  4618.  
  4619.  
  4620.  
  4621.     GRAPH_DOES_NOT_EXIST,
  4622. -- raised in: start_node,
  4623. --            end_node,
  4624. --            set_start_node,
  4625. --            set_end_node
  4626.  
  4627.  
  4628.  
  4629.  
  4630.  
  4631.  
  4632.     ASSIGN_FROM_NODE_DOES_NOT_EXIST,
  4633. -- raised in: assign_value
  4634.  
  4635.  
  4636.  
  4637.  
  4638.  
  4639.     NOT_ENOUGH_INCOMING_ARC_SLOTS_SPECIFIED,
  4640. -- raised in: assign_value
  4641.  
  4642.  
  4643.  
  4644.  
  4645.  
  4646.     NOT_ENOUGH_OUTGOING_ARC_SLOTS_SPECIFIED,
  4647. -- raised in: assign_value
  4648.  
  4649.  
  4650.  
  4651.  
  4652.  
  4653.     ARC_DOES_NOT_CONNECT_THESE_NODES,
  4654. -- raised in: arc
  4655.  
  4656.  
  4657.  
  4658.  
  4659.  
  4660.     MAXIMUM_NUMBER_OF_ARCS_SPECIFIED_BETWEEN_THESE_NODES,
  4661. -- raised in: create_arc
  4662.  
  4663.  
  4664.  
  4665.  
  4666.  
  4667.     PATH_NOT_FOUND,
  4668. -- raised in: search_tree
  4669.  
  4670.  
  4671.  
  4672.  
  4673.  
  4674.     NODE_FOUND_TWICE,
  4675. -- raised in: search_tree
  4676.  
  4677.  
  4678.  
  4679.  
  4680.  
  4681.     CYCLE_EXISTS,
  4682. --raised in:  TOPSORT
  4683.  
  4684.  
  4685.  
  4686.  
  4687.  
  4688.     NODE_NOT_FOUND : exception;
  4689. -- raised in: search_tree
  4690.  
  4691. private
  4692.     type ARC_VALUE_TYPE is
  4693.     record
  4694.         VALUE     : ARC_DATA_TYPE;
  4695.         HEAD_NODE : NODE_TYPE;
  4696.         TAIL_NODE : NODE_TYPE;
  4697.     end record;
  4698.     pragma PACK (ARC_VALUE_TYPE);
  4699.  
  4700.     type ARC_TYPE is access ARC_VALUE_TYPE;
  4701.  
  4702.     subtype ARRAY_OF_ARCS is ARC_LIST_TYPE;
  4703.  
  4704.     type NODE_VALUE_TYPE (MAXIMUM_INCOMING_ARCS : NATURAL;
  4705.               MAXIMUM_OUTGOING_ARCS : NATURAL) is
  4706.     record
  4707.         VALUE         : NODE_DATA_TYPE;
  4708.         INCOMING_ARCS : ARRAY_OF_ARCS (1 .. MAXIMUM_INCOMING_ARCS);
  4709.         OUTGOING_ARCS : ARRAY_OF_ARCS (1 .. MAXIMUM_OUTGOING_ARCS);
  4710.         TOPSORT_COUNT : NATURAL;
  4711.     end record;
  4712.     pragma PACK (NODE_VALUE_TYPE);
  4713.     type NODE_TYPE is access NODE_VALUE_TYPE;
  4714.     type GRAPH_VALUE_TYPE (MAX_NUMBER_OF_NODES : POSITIVE) is
  4715.     record
  4716.         START_NODE : NODE_TYPE;
  4717.         END_NODE   : NODE_TYPE;
  4718.         NODE_LIST  : NODE_LIST_TYPE (1 .. MAX_NUMBER_OF_NODES);
  4719.     end record;
  4720.     pragma PACK (GRAPH_VALUE_TYPE);
  4721.  
  4722.     type GRAPH_TYPE is access GRAPH_VALUE_TYPE;
  4723. end GRAPHS;
  4724.  
  4725.  
  4726.  
  4727.  
  4728.  
  4729. with UNCHECKED_DEALLOCATION;
  4730.  
  4731. package body GRAPHS is
  4732.  
  4733.     procedure CREATE_ARC (WITH_VALUE   : ARC_DATA_TYPE;
  4734.               BETWEEN_NODE : NODE_TYPE;
  4735.               AND_NODE     : NODE_TYPE) is
  4736.     pragma OPTIMIZE (TIME);
  4737.  
  4738.     HEAD_NODE : NODE_TYPE renames AND_NODE;
  4739.     TAIL_NODE : NODE_TYPE renames BETWEEN_NODE;
  4740.     ARC_VALUE : ARC_DATA_TYPE renames WITH_VALUE;
  4741.     TEMP_ARC  : ARC_TYPE := new ARC_VALUE_TYPE;
  4742.  
  4743.  
  4744.     function NEXT_FREE_SLOT (IN_ARRAY : ARRAY_OF_ARCS) return NATURAL is
  4745.         pragma OPTIMIZE (TIME);
  4746.  
  4747.         COUNT : NATURAL := 0;
  4748.     begin
  4749.         loop
  4750.         COUNT := COUNT + 1;
  4751.         exit when IN_ARRAY (COUNT) = null;
  4752.         end loop;
  4753.  
  4754.         return COUNT;
  4755.     exception
  4756.         when CONSTRAINT_ERROR => 
  4757.         raise MAXIMUM_NUMBER_OF_ARCS_SPECIFIED_BETWEEN_THESE_NODES;
  4758.     end NEXT_FREE_SLOT;
  4759.     begin
  4760.     TEMP_ARC.all := (ARC_VALUE, HEAD_NODE, TAIL_NODE);
  4761.     HEAD_NODE.INCOMING_ARCS (NEXT_FREE_SLOT (HEAD_NODE.INCOMING_ARCS)) :=
  4762.       TEMP_ARC;
  4763.     TAIL_NODE.OUTGOING_ARCS (NEXT_FREE_SLOT (TAIL_NODE.OUTGOING_ARCS)) :=
  4764.       TEMP_ARC;
  4765.     exception
  4766.     when STORAGE_ERROR => 
  4767.         raise NOT_ENOUGH_STORAGE_REMAINING;
  4768.  
  4769.     when CONSTRAINT_ERROR => 
  4770.         if (HEAD_NODE = null) then
  4771.         raise HEAD_NODE_DOES_NOT_EXIST;
  4772.  
  4773.         elsif (TAIL_NODE = null) then
  4774.         raise TAIL_NODE_DOES_NOT_EXIST;
  4775.         end if;
  4776.     end CREATE_ARC;
  4777.  
  4778.  
  4779.     function NEW_NODE (WITH_VALUE                      : NODE_DATA_TYPE;
  4780.                MAXIMUM_NUMBER_OF_INCOMING_ARCS : NATURAL;
  4781.                MAXIMUM_NUMBER_OF_OUTGOING_ARCS : NATURAL;
  4782.                IN_GRAPH                        : GRAPH_TYPE)
  4783.                 return NODE_TYPE is
  4784.     pragma OPTIMIZE (SPACE);
  4785.  
  4786.     NODE_VALUE : NODE_DATA_TYPE renames WITH_VALUE;
  4787.     GRAPH      : GRAPH_TYPE renames IN_GRAPH;
  4788.     TEMP_NODE  : NODE_TYPE;
  4789.  
  4790.  
  4791.     function NEXT_FREE_SLOT (IN_ARRAY : NODE_LIST_TYPE) return NATURAL is
  4792.         COUNT : NATURAL := 0;
  4793.     begin
  4794.         loop
  4795.         COUNT := COUNT + 1;
  4796.         exit when IN_ARRAY (COUNT) = null;
  4797.         end loop;
  4798.  
  4799.         return COUNT;
  4800.     exception
  4801.         when CONSTRAINT_ERROR => 
  4802.         raise MAXIMUM_NUMBER_OF_NODES_SPECIFIED_IN_GRAPH;
  4803.     end NEXT_FREE_SLOT;
  4804.     begin
  4805.     TEMP_NODE := new NODE_VALUE_TYPE
  4806.                (MAXIMUM_NUMBER_OF_INCOMING_ARCS,
  4807.                 MAXIMUM_NUMBER_OF_OUTGOING_ARCS);
  4808.     TEMP_NODE.VALUE := NODE_VALUE;
  4809.     GRAPH.NODE_LIST (NEXT_FREE_SLOT (GRAPH.NODE_LIST)) := TEMP_NODE;
  4810.     return TEMP_NODE;
  4811.     exception
  4812.     when STORAGE_ERROR => 
  4813.         raise NOT_ENOUGH_STORAGE_REMAINING;
  4814.     end NEW_NODE;
  4815.  
  4816.  
  4817.     procedure CREATE (A_GRAPH                 : in out GRAPH_TYPE;
  4818.               WITH_START_NODE         : NODE_TYPE;
  4819.               WITH_END_NODE           : NODE_TYPE;
  4820.               MAXIMUM_NUMBER_OF_NODES : NATURAL) is
  4821.     pragma OPTIMIZE (SPACE);
  4822.  
  4823.     START_NODE : NODE_TYPE renames WITH_START_NODE;
  4824.     END_NODE   : NODE_TYPE renames WITH_END_NODE;
  4825.     TEMP_GRAPH : GRAPH_TYPE;
  4826.     begin
  4827.     TEMP_GRAPH := new GRAPH_VALUE_TYPE (MAXIMUM_NUMBER_OF_NODES);
  4828.     TEMP_GRAPH.START_NODE := START_NODE;
  4829.     TEMP_GRAPH.END_NODE := END_NODE;
  4830.     A_GRAPH := TEMP_GRAPH;
  4831.     exception
  4832.     when STORAGE_ERROR => 
  4833.         raise NOT_ENOUGH_STORAGE_REMAINING;
  4834.     end CREATE;
  4835.  
  4836.     procedure SET_END_NODE (TO_VALUE : NODE_TYPE; IN_GRAPH : GRAPH_TYPE) is
  4837.     begin
  4838.     IN_GRAPH.END_NODE := TO_VALUE;
  4839.     exception
  4840.     when CONSTRAINT_ERROR => 
  4841.         raise GRAPH_DOES_NOT_EXIST;
  4842.     end SET_END_NODE;
  4843.  
  4844.     procedure SET_START_NODE (TO_VALUE : NODE_TYPE; IN_GRAPH : GRAPH_TYPE) is
  4845.     begin
  4846.     IN_GRAPH.START_NODE := TO_VALUE;
  4847.     exception
  4848.     when CONSTRAINT_ERROR => 
  4849.         raise GRAPH_DOES_NOT_EXIST;
  4850.     end SET_START_NODE;
  4851.  
  4852.     procedure DELETE (THE_NODE : in out NODE_TYPE) is
  4853.     pragma OPTIMIZE (SPACE);
  4854.  
  4855.     procedure DEALLOCATE is new UNCHECKED_DEALLOCATION
  4856.            (NODE_VALUE_TYPE, NODE_TYPE);
  4857.     begin
  4858.     DEALLOCATE (THE_NODE);
  4859.     end DELETE;
  4860.  
  4861.  
  4862.     procedure DELETE (THE_ARC : in out ARC_TYPE) is
  4863.     pragma OPTIMIZE (SPACE);
  4864.  
  4865.     procedure DEALLOCATE is new UNCHECKED_DEALLOCATION
  4866.            (ARC_VALUE_TYPE, ARC_TYPE);
  4867.     begin
  4868.     DEALLOCATE (THE_ARC);
  4869.     end DELETE;
  4870.  
  4871.  
  4872.     function NUMBER_NON_NULL_ELEMENTS (IN_ARRAY : ARRAY_OF_ARCS)
  4873.                         return NATURAL is
  4874.     pragma OPTIMIZE (TIME);
  4875.  
  4876.     THE_ARRAY : ARRAY_OF_ARCS renames IN_ARRAY;
  4877.     COUNT     : NATURAL := 0;
  4878.     begin
  4879.     for INDEX in THE_ARRAY'RANGE loop
  4880.         if THE_ARRAY (INDEX) /= null then
  4881.         COUNT := COUNT + 1;
  4882.         end if;
  4883.     end loop;
  4884.  
  4885.     return COUNT;
  4886.     end NUMBER_NON_NULL_ELEMENTS;
  4887.  
  4888.  
  4889.     function CURRENT_NUMBER_OF_INCOMING_ARCS (ON_NODE : NODE_TYPE)
  4890.                            return NATURAL is
  4891.     pragma OPTIMIZE (TIME);
  4892.  
  4893.     NODE : NODE_TYPE renames ON_NODE;
  4894.     begin
  4895.     return NUMBER_NON_NULL_ELEMENTS (IN_ARRAY => NODE.INCOMING_ARCS);
  4896.     exception
  4897.     when CONSTRAINT_ERROR => 
  4898.         raise NODE_DOES_NOT_EXIST;
  4899.     end CURRENT_NUMBER_OF_INCOMING_ARCS;
  4900.  
  4901.  
  4902.     function CURRENT_NUMBER_OF_OUTGOING_ARCS (ON_NODE : NODE_TYPE)
  4903.                            return NATURAL is
  4904.     pragma OPTIMIZE (TIME);
  4905.  
  4906.     NODE : NODE_TYPE renames ON_NODE;
  4907.     begin
  4908.     return NUMBER_NON_NULL_ELEMENTS (IN_ARRAY => NODE.OUTGOING_ARCS);
  4909.     exception
  4910.     when CONSTRAINT_ERROR => 
  4911.         raise NODE_DOES_NOT_EXIST;
  4912.     end CURRENT_NUMBER_OF_OUTGOING_ARCS;
  4913.  
  4914.  
  4915.     function MAXIMUM_NUMBER_OF_INCOMING_ARCS (ON_NODE : NODE_TYPE)
  4916.                            return NATURAL is
  4917.     pragma OPTIMIZE (TIME);
  4918.  
  4919.     NODE : NODE_TYPE renames ON_NODE;
  4920.     begin
  4921.     return NODE.MAXIMUM_INCOMING_ARCS;
  4922.     exception
  4923.     when CONSTRAINT_ERROR => 
  4924.         raise NODE_DOES_NOT_EXIST;
  4925.     end MAXIMUM_NUMBER_OF_INCOMING_ARCS;
  4926.  
  4927.     function MAXIMUM_NUMBER_OF_OUTGOING_ARCS (ON_NODE : NODE_TYPE)
  4928.                            return NATURAL is
  4929.     pragma OPTIMIZE (TIME);
  4930.  
  4931.     NODE : NODE_TYPE renames ON_NODE;
  4932.     begin
  4933.     return NODE.MAXIMUM_OUTGOING_ARCS;
  4934.     exception
  4935.     when CONSTRAINT_ERROR => 
  4936.         raise NODE_DOES_NOT_EXIST;
  4937.     end MAXIMUM_NUMBER_OF_OUTGOING_ARCS;
  4938.  
  4939.  
  4940.     function HEAD_NODE (OF_ARC : ARC_TYPE) return NODE_TYPE is
  4941.     pragma OPTIMIZE (TIME);
  4942.  
  4943.     ARC : ARC_TYPE renames OF_ARC;
  4944.     begin
  4945.     return ARC.HEAD_NODE;
  4946.     exception
  4947.     when CONSTRAINT_ERROR => 
  4948.         raise ARC_DOES_NOT_EXIST;
  4949.     end HEAD_NODE;
  4950.  
  4951.  
  4952.     function TAIL_NODE (OF_ARC : ARC_TYPE) return NODE_TYPE is
  4953.     pragma OPTIMIZE (TIME);
  4954.  
  4955.     ARC : ARC_TYPE renames OF_ARC;
  4956.     begin
  4957.     return ARC.TAIL_NODE;
  4958.     exception
  4959.     when CONSTRAINT_ERROR => 
  4960.         raise ARC_DOES_NOT_EXIST;
  4961.     end TAIL_NODE;
  4962.  
  4963.  
  4964.     function START_NODE (OF_GRAPH : GRAPH_TYPE) return NODE_TYPE is
  4965.     pragma OPTIMIZE (TIME);
  4966.  
  4967.     GRAPH : GRAPH_TYPE renames OF_GRAPH;
  4968.     begin
  4969.     return GRAPH.START_NODE;
  4970.     exception
  4971.     when CONSTRAINT_ERROR => 
  4972.         raise GRAPH_DOES_NOT_EXIST;
  4973.     end START_NODE;
  4974.  
  4975.  
  4976.     function END_NODE (OF_GRAPH : GRAPH_TYPE) return NODE_TYPE is
  4977.     pragma OPTIMIZE (TIME);
  4978.  
  4979.     GRAPH : GRAPH_TYPE renames OF_GRAPH;
  4980.     begin
  4981.     return GRAPH.END_NODE;
  4982.     exception
  4983.     when CONSTRAINT_ERROR => 
  4984.         raise GRAPH_DOES_NOT_EXIST;
  4985.     end END_NODE;
  4986.  
  4987.  
  4988.     function VALUE (OF_ARC : ARC_TYPE) return ARC_DATA_TYPE is
  4989.     pragma OPTIMIZE (TIME);
  4990.  
  4991.     ARC : ARC_TYPE renames OF_ARC;
  4992.     begin
  4993.     return ARC.VALUE;
  4994.     exception
  4995.     when CONSTRAINT_ERROR => 
  4996.         raise ARC_DOES_NOT_EXIST;
  4997.     end VALUE;
  4998.  
  4999.  
  5000.     function VALUE (OF_NODE : NODE_TYPE) return NODE_DATA_TYPE is
  5001.     pragma OPTIMIZE (TIME);
  5002.  
  5003.     NODE : NODE_TYPE renames OF_NODE;
  5004.     begin
  5005.     return NODE.VALUE;
  5006.     exception
  5007.     when CONSTRAINT_ERROR => 
  5008.         raise NODE_DOES_NOT_EXIST;
  5009.     end VALUE;
  5010.  
  5011.  
  5012.     procedure ASSIGN_VALUE (OF_NODE  : NODE_TYPE;
  5013.                 TO_NODE  : in out NODE_TYPE;
  5014.                 IN_GRAPH : GRAPH_TYPE) is
  5015.     pragma OPTIMIZE (TIME);
  5016.  
  5017.     ASSIGN_FROM_NODE : NODE_TYPE renames OF_NODE;
  5018.     ASSIGN_TO_NODE   : NODE_TYPE renames TO_NODE;
  5019.     GRAPH            : GRAPH_TYPE renames IN_GRAPH;
  5020.     begin
  5021.     if ASSIGN_TO_NODE = null then
  5022.         ASSIGN_TO_NODE := NEW_NODE (ASSIGN_FROM_NODE.VALUE,
  5023.                     ASSIGN_FROM_NODE.MAXIMUM_INCOMING_ARCS,
  5024.                     ASSIGN_FROM_NODE.MAXIMUM_OUTGOING_ARCS,
  5025.                     GRAPH);
  5026.     else
  5027.         ASSIGN_TO_NODE.VALUE := ASSIGN_FROM_NODE.VALUE;
  5028.  
  5029.         for INDEX in 1 .. ASSIGN_TO_NODE.MAXIMUM_INCOMING_ARCS loop
  5030.         DELETE (ASSIGN_TO_NODE.INCOMING_ARCS (INDEX));
  5031.         end loop;
  5032.  
  5033.         for INDEX in 1 .. ASSIGN_TO_NODE.MAXIMUM_OUTGOING_ARCS loop
  5034.         DELETE (ASSIGN_TO_NODE.OUTGOING_ARCS (INDEX));
  5035.         end loop;
  5036.     end if;
  5037.  
  5038.     declare
  5039.         TO_INDEX : NATURAL := 0;
  5040.     begin
  5041.         for FROM_INDEX in ASSIGN_FROM_NODE.INCOMING_ARCS'RANGE loop
  5042.         if ASSIGN_FROM_NODE.INCOMING_ARCS (FROM_INDEX) /= null then
  5043.             TO_INDEX := TO_INDEX + 1;
  5044.             ASSIGN_TO_NODE.INCOMING_ARCS (TO_INDEX) :=
  5045.               ASSIGN_FROM_NODE.INCOMING_ARCS (FROM_INDEX);
  5046.             ASSIGN_TO_NODE.INCOMING_ARCS (TO_INDEX).all :=
  5047.               ASSIGN_FROM_NODE.INCOMING_ARCS (FROM_INDEX).all;
  5048.         end if;
  5049.         end loop;
  5050.  
  5051.         for FROM_INDEX in ASSIGN_FROM_NODE.OUTGOING_ARCS'RANGE loop
  5052.         if ASSIGN_FROM_NODE.OUTGOING_ARCS (FROM_INDEX) /= null then
  5053.             TO_INDEX := TO_INDEX + 1;
  5054.             ASSIGN_TO_NODE.OUTGOING_ARCS (TO_INDEX) :=
  5055.               ASSIGN_FROM_NODE.OUTGOING_ARCS (FROM_INDEX);
  5056.             ASSIGN_TO_NODE.OUTGOING_ARCS (TO_INDEX).all :=
  5057.               ASSIGN_FROM_NODE.OUTGOING_ARCS (FROM_INDEX).all;
  5058.         end if;
  5059.         end loop;
  5060.     end;
  5061.     exception
  5062.     when CONSTRAINT_ERROR => 
  5063.         if ASSIGN_FROM_NODE = null then
  5064.         raise ASSIGN_FROM_NODE_DOES_NOT_EXIST;
  5065.  
  5066.         elsif ASSIGN_TO_NODE.MAXIMUM_INCOMING_ARCS <
  5067.           ASSIGN_FROM_NODE.MAXIMUM_INCOMING_ARCS then
  5068.         raise NOT_ENOUGH_INCOMING_ARC_SLOTS_SPECIFIED;
  5069.  
  5070.         elsif ASSIGN_TO_NODE.MAXIMUM_OUTGOING_ARCS <
  5071.           ASSIGN_FROM_NODE.MAXIMUM_OUTGOING_ARCS then
  5072.         raise NOT_ENOUGH_OUTGOING_ARC_SLOTS_SPECIFIED;
  5073.         end if;
  5074.     end ASSIGN_VALUE;
  5075.  
  5076.  
  5077.     function ARC (WITH_TAIL : NODE_TYPE;
  5078.           WITH_HEAD : NODE_TYPE) return ARC_LIST_TYPE is
  5079.     TIP_NODE   : NODE_TYPE renames WITH_HEAD;
  5080.     TAIL_NODE  : NODE_TYPE renames WITH_TAIL;
  5081.     ARC_LIST   : constant ARC_LIST_TYPE :=
  5082.              OUTGOING_ARCS (ON_NODE => TAIL_NODE);
  5083.     TEMP_LIST  : ARC_LIST_TYPE (ARC_LIST'RANGE);
  5084.     TEMP_INDEX : INTEGER range ARC_LIST'FIRST .. ARC_LIST'LAST :=
  5085.              ARC_LIST'FIRST;
  5086.     begin
  5087.  
  5088.     for INDEX in ARC_LIST'RANGE loop
  5089.  
  5090.         if TIP_NODE = HEAD_NODE (OF_ARC => ARC_LIST (INDEX)) then
  5091.         TEMP_LIST (TEMP_INDEX) := ARC_LIST (INDEX);
  5092.         end if;
  5093.     end loop;
  5094.  
  5095.     if TEMP_LIST (TEMP_LIST'FIRST) /= null then
  5096.         return TEMP_LIST (TEMP_LIST'FIRST .. TEMP_LIST'LAST);
  5097.     else
  5098.         raise ARC_DOES_NOT_CONNECT_THESE_NODES;
  5099.     end if;
  5100.     end ARC;
  5101.  
  5102.     procedure ASSIGN (VALUE : NODE_DATA_TYPE; TO_NODE : NODE_TYPE) is
  5103.     begin
  5104.     TO_NODE.VALUE := VALUE;
  5105.     exception
  5106.     when CONSTRAINT_ERROR => 
  5107.         raise NODE_DOES_NOT_EXIST;
  5108.     end ASSIGN;
  5109.  
  5110.     procedure ASSIGN (VALUE : ARC_DATA_TYPE; TO_ARC : ARC_TYPE) is
  5111.     begin
  5112.     TO_ARC.VALUE := VALUE;
  5113.     exception
  5114.     when CONSTRAINT_ERROR => 
  5115.         raise ARC_DOES_NOT_EXIST;
  5116.     end ASSIGN;
  5117.  
  5118.     function INCOMING_ARCS (ON_NODE : NODE_TYPE) return ARC_LIST_TYPE is
  5119.     NODE  : NODE_TYPE renames ON_NODE;
  5120.     TEMP  : ARC_LIST_TYPE (1 .. NODE.MAXIMUM_INCOMING_ARCS);
  5121.     INDEX : NATURAL := 0;
  5122.     begin
  5123.     for I in NODE.INCOMING_ARCS'RANGE loop
  5124.         if NODE.INCOMING_ARCS (I) /= null then
  5125.         INDEX := INDEX + 1;
  5126.         TEMP (INDEX) := NODE.INCOMING_ARCS (I);
  5127.         end if;
  5128.     end loop;
  5129.  
  5130.     return TEMP (1 .. INDEX);
  5131.     exception
  5132.     when CONSTRAINT_ERROR => 
  5133.         raise NODE_DOES_NOT_EXIST;
  5134.     end INCOMING_ARCS;
  5135.  
  5136.     function OUTGOING_ARCS (ON_NODE : NODE_TYPE) return ARC_LIST_TYPE is
  5137.     NODE  : NODE_TYPE renames ON_NODE;
  5138.     TEMP  : ARC_LIST_TYPE (1 .. NODE.MAXIMUM_OUTGOING_ARCS);
  5139.     INDEX : NATURAL := 0;
  5140.     begin
  5141.     for I in NODE.OUTGOING_ARCS'RANGE loop
  5142.         if NODE.OUTGOING_ARCS (I) /= null then
  5143.         INDEX := INDEX + 1;
  5144.         TEMP (INDEX) := NODE.OUTGOING_ARCS (I);
  5145.         end if;
  5146.     end loop;
  5147.  
  5148.     return TEMP (1 .. INDEX);
  5149.     exception
  5150.     when CONSTRAINT_ERROR => 
  5151.         raise GRAPH_DOES_NOT_EXIST;
  5152.     end OUTGOING_ARCS;
  5153.  
  5154.     function NODES (ON_GRAPH : GRAPH_TYPE) return NODE_LIST_TYPE is
  5155.     GRAPH : GRAPH_TYPE renames ON_GRAPH;
  5156.     TEMP  : NODE_LIST_TYPE (1 .. GRAPH.MAX_NUMBER_OF_NODES);
  5157.     INDEX : NATURAL := 0;
  5158.     begin
  5159.     for I in GRAPH.NODE_LIST'RANGE loop
  5160.         if GRAPH.NODE_LIST (I) /= null then
  5161.         INDEX := INDEX + 1;
  5162.         TEMP (INDEX) := GRAPH.NODE_LIST (I);
  5163.         end if;
  5164.     end loop;
  5165.  
  5166.     return TEMP (1 .. INDEX);
  5167.     end NODES;
  5168.  
  5169.  
  5170.     function LIST_OF_SINKS (IN_GRAPH : GRAPH_TYPE) return NODE_LIST_TYPE is
  5171.     GRAPH     : GRAPH_TYPE renames IN_GRAPH;
  5172.     TEMP_LIST : NODE_LIST_TYPE (1 .. GRAPH.MAX_NUMBER_OF_NODES);
  5173.     INDEX     : NATURAL := 0;
  5174.     NODE_LIST : constant NODE_LIST_TYPE := NODES (ON_GRAPH => GRAPH);
  5175.     begin
  5176.  
  5177.     for NODE_INDEX in NODE_LIST'RANGE loop
  5178.  
  5179.         declare
  5180.         NODE : NODE_TYPE renames NODE_LIST (NODE_INDEX);
  5181.         begin
  5182.         if ((MAXIMUM_NUMBER_OF_OUTGOING_ARCS (NODE) = 0) or else
  5183.             (CURRENT_NUMBER_OF_OUTGOING_ARCS (NODE) = 0)) then
  5184.             INDEX := INDEX + 1;
  5185.             TEMP_LIST (INDEX) := NODE;
  5186.         end if;
  5187.         end;
  5188.     end loop;
  5189.  
  5190.     return TEMP_LIST (1 .. INDEX);
  5191.     end LIST_OF_SINKS;
  5192.  
  5193.     function LIST_OF_SOURCES (IN_GRAPH : GRAPH_TYPE) return NODE_LIST_TYPE is
  5194.     GRAPH     : GRAPH_TYPE renames IN_GRAPH;
  5195.     TEMP_LIST : NODE_LIST_TYPE (1 .. GRAPH.MAX_NUMBER_OF_NODES);
  5196.     INDEX     : NATURAL := 0;
  5197.     NODE_LIST : constant NODE_LIST_TYPE := NODES (ON_GRAPH => GRAPH);
  5198.     begin
  5199.  
  5200.     for NODE_INDEX in NODE_LIST'RANGE loop
  5201.         declare
  5202.         NODE : NODE_TYPE renames NODE_LIST (NODE_INDEX);
  5203.         begin
  5204.         if ((MAXIMUM_NUMBER_OF_INCOMING_ARCS (NODE) = 0) or else
  5205.             (CURRENT_NUMBER_OF_INCOMING_ARCS (NODE) = 0)) then
  5206.             INDEX := INDEX + 1;
  5207.             TEMP_LIST (INDEX) := NODE;
  5208.         end if;
  5209.         end;
  5210.     end loop;
  5211.  
  5212.     return TEMP_LIST (1 .. INDEX);
  5213.     end LIST_OF_SOURCES;
  5214.  
  5215.     function ANY_CYCLES (IN_GRAPH : GRAPH_TYPE) return BOOLEAN is
  5216.     GRAPH     : GRAPH_TYPE renames IN_GRAPH;
  5217.     VISITED   : NODE_LIST_TYPE (1 .. GRAPH.MAX_NUMBER_OF_NODES);
  5218.     INDEX     : NATURAL := 0;
  5219.     NODE_LIST : constant NODE_LIST_TYPE := NODES (ON_GRAPH => GRAPH);
  5220.     begin
  5221.  
  5222.     for NODE_INDEX in NODE_LIST'RANGE loop
  5223.  
  5224.         declare
  5225.         NODE : NODE_TYPE renames NODE_LIST (NODE_INDEX);
  5226.         begin
  5227. -- search for node in visited list
  5228.         for I in 1 .. INDEX loop
  5229.             if NODE = VISITED (I) then
  5230.             return TRUE;
  5231.             end if;
  5232.         end loop;
  5233.         -- node not visited yet...
  5234.         INDEX := INDEX + 1;
  5235.         VISITED (INDEX) := NODE;
  5236.         end;
  5237.     end loop;
  5238.  
  5239.     return FALSE;
  5240.     end ANY_CYCLES;
  5241.  
  5242.     procedure TOPSORT (NODE_LIST : in out NODE_LIST_TYPE) is
  5243. --Arrange nodelist into topological sort order.  
  5244.     ZERO_COUNT : NODE_LIST_TYPE (NODE_LIST'RANGE);
  5245.     --set of nodes all of whose predecessors are in zero_count or
  5246.     -- sorted_nodes.
  5247.  
  5248.     SORTED_NODES          : NODE_LIST_TYPE (NODE_LIST'RANGE); --builds up
  5249.                                   -- the
  5250.                                   -- topological
  5251.                                   -- sort
  5252.  
  5253.     Z_INSERT, Z_DELETE, S : INTEGER := 0; --indices to zero_count and
  5254.                           -- sorted_nodes.
  5255.     NUMBER_NON_NULL_NODES : INTEGER := 0;
  5256.  
  5257.     begin
  5258.     for I in NODE_LIST'RANGE loop
  5259.         if NODE_LIST (I) /= null then
  5260.         NUMBER_NON_NULL_NODES := NUMBER_NON_NULL_NODES + 1;
  5261.         NODE_LIST (I).TOPSORT_COUNT :=
  5262.           CURRENT_NUMBER_OF_INCOMING_ARCS (NODE_LIST (I));
  5263.  
  5264.         if NODE_LIST (I).TOPSORT_COUNT = 0 then
  5265.             Z_INSERT := Z_INSERT + 1;
  5266.             ZERO_COUNT (Z_INSERT) := NODE_LIST (I);
  5267.         end if;
  5268.         end if;
  5269.     end loop;
  5270.  
  5271.     while Z_DELETE < Z_INSERT loop
  5272.         --main loop;  select a node from zero_count, move it to
  5273.         -- sorted_nodes, and
  5274.         --decrement the topsort_count fields of all nodes it points to.
  5275.         S := S + 1;
  5276.         Z_DELETE := Z_DELETE + 1;
  5277.         SORTED_NODES (S) := ZERO_COUNT (Z_DELETE);
  5278.  
  5279.         for J in SORTED_NODES (S).OUTGOING_ARCS'RANGE loop
  5280.         if SORTED_NODES (S).OUTGOING_ARCS (J) /= null then
  5281.             SORTED_NODES (S).OUTGOING_ARCS (J).HEAD_NODE
  5282.              .TOPSORT_COUNT :=
  5283.               SORTED_NODES (S).OUTGOING_ARCS (J).HEAD_NODE
  5284.                .TOPSORT_COUNT - 1;
  5285.  
  5286.             if SORTED_NODES (S).OUTGOING_ARCS (J).HEAD_NODE
  5287.             .TOPSORT_COUNT = 0 then
  5288.             Z_INSERT := Z_INSERT + 1;
  5289.             ZERO_COUNT (Z_INSERT) :=
  5290.               SORTED_NODES (S).OUTGOING_ARCS (J).HEAD_NODE;
  5291.             end if;
  5292.         end if;
  5293.         end loop;
  5294.     end loop;
  5295.     --main while loop
  5296.  
  5297.     if S < NUMBER_NON_NULL_NODES then
  5298.         raise CYCLE_EXISTS;
  5299.     else
  5300.         NODE_LIST := SORTED_NODES;
  5301.     end if;
  5302.  
  5303.     end TOPSORT;
  5304.  
  5305. end GRAPHS;
  5306.  
  5307.  
  5308.  
  5309.  
  5310.  
  5311. with TEXT_IO;
  5312.  
  5313. package PERT_IO is
  5314.  
  5315. -- This package is used to read and write the text Activity File. The package
  5316. -- spec contains types for the records describing the activities, the records
  5317. -- describing the file header, and functions for reading and writting to the 
  5318. -- Activity File.
  5319.  
  5320.     subtype NAME_TYPE is STRING (10 .. 41);
  5321.     subtype CODE_TYPE is STRING (1 .. 8);
  5322.  
  5323.     type INPUT_LINE_RECORD_TYPE is
  5324.     record
  5325.         WBS_CODE      : CODE_TYPE;
  5326.         ACTIVITY_NAME : NAME_TYPE;
  5327.         TAIL_NODE     : INTEGER;
  5328.         HEAD_NODE     : INTEGER;
  5329.         OPTIMISTICS   : FLOAT;
  5330.         MOST_LIKELY   : FLOAT;
  5331.         PESSIMISTICS  : FLOAT;
  5332.         STAFFING      : FLOAT;
  5333.         RATE          : FLOAT;
  5334.     end record;
  5335.  
  5336.  
  5337.     subtype LENGTH_RANGE is INTEGER range 1 .. 132;
  5338.  
  5339.     type HEADER_LINE_TYPE (LENGTH : LENGTH_RANGE := 1) is
  5340.     record
  5341.         VALUE : STRING (1 .. LENGTH);
  5342.     end record;
  5343.  
  5344.     NUMBER_OF_HEADER_RECORDS : constant := 5;
  5345.  
  5346.     type HEADER_BUFFER_ARRAY is array (1 .. NUMBER_OF_HEADER_RECORDS)
  5347.                        of HEADER_LINE_TYPE;
  5348.  
  5349.  
  5350.     procedure READ_HEADER (FROM_FILE  : TEXT_IO.FILE_TYPE;
  5351.                HEADER_SET : out HEADER_BUFFER_ARRAY);
  5352.  
  5353.  
  5354.     procedure WRITE_HEADER
  5355.          (TO_FILE    : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  5356.           HEADER_SET : HEADER_BUFFER_ARRAY);
  5357.  
  5358.  
  5359.     procedure READ_ONE_ACTIVITY_LINE (FROM_FILE : TEXT_IO.FILE_TYPE;
  5360.                       A_RECORD  : out INPUT_LINE_RECORD_TYPE);
  5361.  
  5362.  
  5363.     procedure WRITE_ONE_LINE
  5364.          (TO_FILE  : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  5365.           A_RECORD : INPUT_LINE_RECORD_TYPE);
  5366.  
  5367.  
  5368.  
  5369.     ACTIVITY_FILE_IS_NOT_OPEN    : exception;
  5370.     END_OF_ACTIVITY_FILE_REACHED : exception;
  5371.     ACTIVITY_FILE_IS_READ_ONLY   : exception;
  5372.     BAD_DATA                     : exception;
  5373.     VALUE_OUTSIDE_LEGAL_RANGE    : exception;
  5374.  
  5375.  
  5376.  
  5377. end PERT_IO;
  5378.  
  5379.  
  5380.  
  5381.  
  5382.  
  5383. -- This is the package body for the PERT_IO package. It contains the
  5384. -- the procedures bodies of the procedures given in the spec. No internal
  5385. -- procedures are needed.
  5386.  
  5387. package body PERT_IO is
  5388.  
  5389.  
  5390.     procedure READ_HEADER (FROM_FILE  : TEXT_IO.FILE_TYPE;
  5391.                HEADER_SET : out HEADER_BUFFER_ARRAY) is
  5392.  
  5393.     ACTIVITY_FILE  : TEXT_IO.FILE_TYPE renames FROM_FILE;
  5394.     INPUT_LINE     : STRING (LENGTH_RANGE);
  5395.     INPUT_LINE_END : POSITIVE;
  5396.  
  5397.     begin
  5398.     for I in 1 .. NUMBER_OF_HEADER_RECORDS loop
  5399.         TEXT_IO.GET_LINE (ACTIVITY_FILE, INPUT_LINE, INPUT_LINE_END);
  5400.         HEADER_SET (I) := (INPUT_LINE_END,
  5401.                    INPUT_LINE (1 .. INPUT_LINE_END));
  5402.     end loop;
  5403.  
  5404.     exception
  5405.     when TEXT_IO.STATUS_ERROR => 
  5406.         raise ACTIVITY_FILE_IS_NOT_OPEN;
  5407.  
  5408.     when TEXT_IO.END_ERROR => 
  5409.         raise END_OF_ACTIVITY_FILE_REACHED;
  5410.  
  5411.     end READ_HEADER;
  5412.  
  5413.  
  5414.  
  5415.     procedure WRITE_HEADER
  5416.          (TO_FILE    : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  5417.           HEADER_SET : HEADER_BUFFER_ARRAY) is
  5418.  
  5419.     ACTIVITY_FILE : TEXT_IO.FILE_TYPE renames TO_FILE;
  5420.  
  5421.     begin
  5422.     for I in 1 .. NUMBER_OF_HEADER_RECORDS loop
  5423.         TEXT_IO.PUT_LINE (ACTIVITY_FILE, HEADER_SET (I).VALUE);
  5424.     end loop;
  5425.  
  5426.     exception
  5427.     when TEXT_IO.STATUS_ERROR => 
  5428.         raise ACTIVITY_FILE_IS_NOT_OPEN;
  5429.  
  5430.     when TEXT_IO.MODE_ERROR => 
  5431.         raise ACTIVITY_FILE_IS_READ_ONLY;
  5432.  
  5433.     end WRITE_HEADER;
  5434.  
  5435.  
  5436.  
  5437.     procedure READ_ONE_ACTIVITY_LINE (FROM_FILE : TEXT_IO.FILE_TYPE;
  5438.                       A_RECORD  : out INPUT_LINE_RECORD_TYPE) is
  5439.  
  5440.     ACTIVITY_FILE : TEXT_IO.FILE_TYPE renames FROM_FILE;
  5441.  
  5442.     package INT_IO is new TEXT_IO.INTEGER_IO (INTEGER);
  5443.     package FLT_IO is new TEXT_IO.FLOAT_IO (FLOAT);
  5444.  
  5445.     begin
  5446.     TEXT_IO.GET (ACTIVITY_FILE, A_RECORD.WBS_CODE);
  5447.     TEXT_IO.SET_COL (ACTIVITY_FILE, 10);
  5448.     TEXT_IO.GET (ACTIVITY_FILE, A_RECORD.ACTIVITY_NAME);
  5449.     INT_IO.GET (ACTIVITY_FILE, A_RECORD.TAIL_NODE);
  5450.     INT_IO.GET (ACTIVITY_FILE, A_RECORD.HEAD_NODE);
  5451.     FLT_IO.GET (ACTIVITY_FILE, A_RECORD.OPTIMISTICS);
  5452.     FLT_IO.GET (ACTIVITY_FILE, A_RECORD.MOST_LIKELY);
  5453.     FLT_IO.GET (ACTIVITY_FILE, A_RECORD.PESSIMISTICS);
  5454.     FLT_IO.GET (ACTIVITY_FILE, A_RECORD.STAFFING);
  5455.     FLT_IO.GET (ACTIVITY_FILE, A_RECORD.RATE);
  5456.  
  5457.     exception
  5458.     when TEXT_IO.STATUS_ERROR => 
  5459.         raise ACTIVITY_FILE_IS_NOT_OPEN;
  5460.  
  5461.     when TEXT_IO.END_ERROR => 
  5462.         raise END_OF_ACTIVITY_FILE_REACHED;
  5463.  
  5464.     when TEXT_IO.DATA_ERROR => 
  5465.         raise BAD_DATA;
  5466.  
  5467.     when CONSTRAINT_ERROR => 
  5468.         raise VALUE_OUTSIDE_LEGAL_RANGE;
  5469.  
  5470.     end READ_ONE_ACTIVITY_LINE;
  5471.  
  5472.  
  5473.  
  5474.     procedure WRITE_ONE_LINE
  5475.          (TO_FILE  : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  5476.           A_RECORD : INPUT_LINE_RECORD_TYPE) is
  5477.  
  5478.     ACTIVITY_FILE : TEXT_IO.FILE_TYPE renames TO_FILE;
  5479.  
  5480.     package INT_IO is new TEXT_IO.INTEGER_IO (INTEGER);
  5481.     package FLT_IO is new TEXT_IO.FLOAT_IO (FLOAT);
  5482.  
  5483.     begin
  5484.     TEXT_IO.PUT (ACTIVITY_FILE, A_RECORD.WBS_CODE);
  5485.     TEXT_IO.PUT (ACTIVITY_FILE, " ");
  5486.     TEXT_IO.PUT (ACTIVITY_FILE, A_RECORD.ACTIVITY_NAME);
  5487.     TEXT_IO.PUT (ACTIVITY_FILE, " ");
  5488.     INT_IO.PUT (ACTIVITY_FILE, A_RECORD.TAIL_NODE, WIDTH => 4);
  5489.     TEXT_IO.PUT (ACTIVITY_FILE, " ");
  5490.     INT_IO.PUT (ACTIVITY_FILE, A_RECORD.HEAD_NODE, WIDTH => 4);
  5491.     TEXT_IO.PUT (ACTIVITY_FILE, " ");
  5492.     FLT_IO.PUT
  5493.        (ACTIVITY_FILE, A_RECORD.OPTIMISTICS, EXP => 0, FORE => 3, AFT => 1);
  5494.     TEXT_IO.PUT (ACTIVITY_FILE, " ");
  5495.     FLT_IO.PUT
  5496.        (ACTIVITY_FILE, A_RECORD.MOST_LIKELY, EXP => 0, FORE => 3, AFT => 1);
  5497.     TEXT_IO.PUT (ACTIVITY_FILE, " ");
  5498.     FLT_IO.PUT
  5499.        (ACTIVITY_FILE, A_RECORD.PESSIMISTICS, EXP => 0, FORE => 3,
  5500.         AFT => 1);
  5501.     TEXT_IO.PUT (ACTIVITY_FILE, " ");
  5502.     FLT_IO.PUT
  5503.        (ACTIVITY_FILE, A_RECORD.STAFFING, EXP => 0, FORE => 2, AFT => 1);
  5504.     TEXT_IO.PUT (ACTIVITY_FILE, " ");
  5505.     FLT_IO.PUT
  5506.        (ACTIVITY_FILE, A_RECORD.RATE, EXP => 0, FORE => 7, AFT => 1);
  5507.  
  5508.     TEXT_IO.NEW_LINE;
  5509.  
  5510.     exception
  5511.     when TEXT_IO.STATUS_ERROR => 
  5512.         raise ACTIVITY_FILE_IS_NOT_OPEN;
  5513.  
  5514.     when TEXT_IO.MODE_ERROR => 
  5515.         raise ACTIVITY_FILE_IS_READ_ONLY;
  5516.  
  5517.     end WRITE_ONE_LINE;
  5518.  
  5519.  
  5520.  
  5521. end PERT_IO;
  5522.  
  5523.  
  5524.  
  5525.  
  5526. package FILE_HANDLER is
  5527.  
  5528.  
  5529. -----------------------------------------------------------
  5530. -- Author:     T. C. Bryan/Ken Lamarche
  5531. -- Source:     Division Software Technology and Support
  5532. --             Western Development Laboratories
  5533. --             Ford Aerospace & Communications Corporation
  5534. --             ATTN:  Ada Tools Group
  5535. -- Date  :     May 25 1985
  5536. -- Summary:    This function prompts users for a string
  5537. --   of a specified length required by the SIMPERT run.
  5538. --   Example -  a file name, a title for a report, etc.
  5539. -----------------------------------------------------------
  5540.  
  5541.     type OUTFILES is (TOUT, ACT, NODE, MAN, BARIN);
  5542.  
  5543.     subtype LENGTH_RANGE is INTEGER range 1 .. 132;
  5544.  
  5545.     type OUTFILE_NAME_TYPE (LENGTH : LENGTH_RANGE := 1) is
  5546.     record
  5547.         VALUE : STRING (1 .. LENGTH);
  5548.     end record;
  5549.     type OUTFILE_ARRAY_TYPE is array (OUTFILES) of OUTFILE_NAME_TYPE;
  5550.  
  5551.     OUTFILE_ARRAY : constant OUTFILE_ARRAY_TYPE :=
  5552.             (TOUT  => (8, "tout.tem"),
  5553.              ACT   => (7, "act.tem"),
  5554.              NODE  => (8, "node.tem"),
  5555.              MAN   => (12, "manpower.tem"),
  5556.              BARIN => (9, "barin.tem"));
  5557.  
  5558.  
  5559.     procedure VERIFY_OUTPUT;
  5560.  
  5561.  
  5562.     function VERIFY_LABEL
  5563.             (WITH_PROMPT     : STRING := "ENTER a string of characters";
  5564.          LENGTH_OF_LABEL : INTEGER := 80;
  5565.          STRING_TYPE     : STRING := "string") return STRING;
  5566.  
  5567.  
  5568.  
  5569.     function VERIFY_INPUT (FILE_PROMPT          : STRING;
  5570.                MAX_FILE_NAME_LENGTH : INTEGER) return STRING;
  5571.  
  5572.  
  5573.  
  5574.     STOP_ON_USER_REQUEST     : exception;
  5575.     END_FILE_HANDLER_REQUEST : exception;
  5576.  
  5577.  
  5578. end FILE_HANDLER;
  5579.  
  5580.  
  5581.  
  5582.  
  5583. with TEXT_IO,
  5584.      SCREEN_IO,
  5585.      FILE_OPS;
  5586.  
  5587.  
  5588. package body FILE_HANDLER is
  5589.  
  5590. -----------------------------------------------------------
  5591. -- Author:     T. C. Bryan/Ken Lamarche
  5592. -- Source:     Division Software Technology and Support
  5593. --             Western Development Laboratories
  5594. --             Ford Aerospace & Communications Corporation
  5595. --             ATTN:  Ada Tools Group
  5596. -- Date  :     May 25 1985
  5597. -- Summary:    This package contains subprograms handling
  5598. --             verification of input and output files used
  5599. --             by SIMPERT.
  5600. -----------------------------------------------------------
  5601.  
  5602.  
  5603.     type YESNO_TYPE is (Y, YE, YES, N, NO, NONE);
  5604.  
  5605.     function RETURN_YESNO is new SCREEN_IO.RETURNED_ENUMERATION (YESNO_TYPE);
  5606.  
  5607.     ERROR_INDENTATION : TEXT_IO.COUNT := 15;
  5608.  
  5609.  
  5610.  
  5611.  
  5612. -----------------------------------------------------------
  5613. -- Author:     T. C. Bryan/Ken Lamarche
  5614. -- Source:     Division Software Technology and Support
  5615. --             Western Development Laboratories
  5616. --             Ford Aerospace & Communications Corporation
  5617. --             ATTN:  Ada Tools Group
  5618. -- Date  :     May 25 1985
  5619. -- Summary:    This procedure verifies the output files
  5620. --             created in the SIMPERT run. It allows user
  5621. --             to save output files from previous SIMPERT run,
  5622. --             and assure that the output files can be created.
  5623. -----------------------------------------------------------
  5624.     procedure VERIFY_OUTPUT is
  5625.  
  5626.     GO_AHEAD : BOOLEAN := TRUE;
  5627.  
  5628.     STOP_FILES_EXIST : exception;
  5629.  
  5630.  
  5631.     -- Attempts to create the output files (with no content).
  5632.     procedure CREATE_OUTPUT_FILES is
  5633.     begin
  5634.         for I in OUTFILES loop
  5635.         declare
  5636.             THE_OUTPUT_FILE : TEXT_IO.FILE_TYPE;
  5637.         begin
  5638.             FILE_OPS.OPEN
  5639.                (THE_FILE         => THE_OUTPUT_FILE,
  5640.             WITH_NAME        => OUTFILE_ARRAY (I).VALUE,
  5641.             TO_MODE          => TEXT_IO.IN_FILE,
  5642.             CREATION_ENABLED => TRUE);
  5643.  
  5644.             TEXT_IO.DELETE (THE_OUTPUT_FILE);
  5645.  
  5646.  
  5647.         exception
  5648.  
  5649.             when FILE_OPS.SYSTEM_CANNOT_CREATE_FILE => 
  5650.             TEXT_IO.NEW_LINE;
  5651.             TEXT_IO.PUT_LINE ("INPUT ERROR:");
  5652.  
  5653.             TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5654.             TEXT_IO.PUT_LINE
  5655.                ("Program cannot create [" &
  5656.                 OUTFILE_ARRAY (I).VALUE & "]");
  5657.             TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5658.             TEXT_IO.PUT_LINE ("due to an access problem.");
  5659.             TEXT_IO.NEW_LINE;
  5660.             raise END_FILE_HANDLER_REQUEST;
  5661.  
  5662.             when FILE_OPS.FILE_ALREADY_OPEN => 
  5663.             TEXT_IO.NEW_LINE;
  5664.             TEXT_IO.PUT_LINE ("INPUT ERROR:");
  5665.  
  5666.             TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5667.             TEXT_IO.PUT_LINE
  5668.                ("[" & OUTFILE_ARRAY (I).VALUE &
  5669.                 "] is currently in use.");
  5670.  
  5671.             TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5672.             TEXT_IO.PUT_LINE ("Program cannot access it");
  5673.             TEXT_IO.NEW_LINE;
  5674.             raise END_FILE_HANDLER_REQUEST;
  5675.  
  5676.         end;
  5677.         end loop;
  5678.     end CREATE_OUTPUT_FILES;
  5679.  
  5680.     begin
  5681.  
  5682.     for I in OUTFILES loop
  5683.         if FILE_OPS.FILE_EXISTS (WITH_NAME => OUTFILE_ARRAY (I).VALUE) then
  5684.         TEXT_IO.NEW_LINE;
  5685.         TEXT_IO.PUT ("WARNING !!!  [" & OUTFILE_ARRAY (I).VALUE & "]");
  5686.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5687.         TEXT_IO.PUT_LINE (" will be overwritten.  ");
  5688.         GO_AHEAD := FALSE;
  5689.         end if;
  5690.     end loop;
  5691.  
  5692.     if GO_AHEAD then
  5693.         CREATE_OUTPUT_FILES;
  5694.     else
  5695.         if (RETURN_YESNO
  5696.            (PROMPT     => ASCII.LF & ASCII.CR &
  5697.                   "Do you wish to CONTINUE?  (y/n) -->  ",
  5698.             DEFAULT    => NONE,
  5699.             FROM_VALUE => Y,
  5700.             TO_VALUE   => NO,
  5701.             ERROR_TEXT => ASCII.LF & ASCII.CR & "INPUT ERROR:  " &
  5702.                   "Answer must be either Y or N." & ASCII.LF &
  5703.                   ASCII.CR) in Y .. YES) then
  5704.         CREATE_OUTPUT_FILES;
  5705.         else
  5706.         raise STOP_FILES_EXIST;
  5707.  
  5708.         end if;
  5709.     end if;
  5710.  
  5711.     exception
  5712.     when STOP_FILES_EXIST => 
  5713.         raise STOP_ON_USER_REQUEST;
  5714.  
  5715.     end VERIFY_OUTPUT;
  5716.  
  5717.  
  5718.  
  5719. -----------------------------------------------------------
  5720. -- Author:     T. C. Bryan/Ken Lamarche
  5721. -- Source:     Division Software Technology and Support
  5722. --             Western Development Laboratories
  5723. --             Ford Aerospace & Communications Corporation
  5724. --             ATTN:  Ada Tools Group
  5725. -- Date  :     May 25 1985
  5726. -- Summary:    This function prompts users for a string
  5727. --   of a specified length required by the SIMPERT run.
  5728. --   Example -  a file name, a title for a report, etc.
  5729. -----------------------------------------------------------
  5730.     function VERIFY_LABEL
  5731.             (WITH_PROMPT     : STRING := "ENTER a string of characters";
  5732.          LENGTH_OF_LABEL : INTEGER := 80;
  5733.          STRING_TYPE     : STRING := "string") return STRING is
  5734.  
  5735.     LABEL : constant STRING :=
  5736.         (SCREEN_IO.RETURNED_STRING
  5737.             (PROMPT  => ASCII.LF & ASCII.CR & WITH_PROMPT & ASCII.LF &
  5738.                 ASCII.CR & ASCII.LF & ASCII.CR & "-->   ",
  5739.              CONFIRM => FALSE));
  5740.     begin
  5741.     if LABEL'LENGTH = 0 or LABEL'LENGTH > LENGTH_OF_LABEL then
  5742.         TEXT_IO.NEW_LINE;
  5743.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  5744.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5745.         TEXT_IO.PUT_LINE ("The " & STRING_TYPE &
  5746.                   " required must be of length");
  5747.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5748.         TEXT_IO.PUT_LINE ("1 to " & INTEGER'IMAGE (LENGTH_OF_LABEL) &
  5749.                   " characters. Please try again.");
  5750.         TEXT_IO.NEW_LINE;
  5751.         return (VERIFY_LABEL (WITH_PROMPT, LENGTH_OF_LABEL, STRING_TYPE));
  5752.     else
  5753.         return (LABEL);
  5754.     end if;
  5755.     end VERIFY_LABEL;
  5756.  
  5757.  
  5758.  
  5759. ----------------------------------------------------------------------------
  5760. --  Summary
  5761. --     This function returns a file name that is free of text_io error
  5762. --     That is it assures the file with specified name exists and is accessible.
  5763. --     Although the function requires opening the file during checking its
  5764. --     status, it closes the file upon leaving, the user, therefore,
  5765. --     must re_open it prior to using.
  5766. --  Author:  T. C. Bryan
  5767. -- Source:     Division Software Technology and Support
  5768. --             Western Development Laboratories
  5769. --             Ford Aerospace & Communications Corporation
  5770. --             ATTN:  Ada Tools Group
  5771. --  Date  :  May 25, 1985
  5772. ----------------------------------------------------------------------------
  5773.  
  5774.     function VERIFY_INPUT (FILE_PROMPT          : STRING;
  5775.                MAX_FILE_NAME_LENGTH : INTEGER) return STRING is
  5776.  
  5777.     WORKING_FILE : TEXT_IO.FILE_TYPE;
  5778.  
  5779.     FILE_DOESNOT_EXIST : exception;
  5780.  
  5781.  
  5782.  
  5783.     -----------------------------------------------------------
  5784.     -- 
  5785.     -----------------------------------------------------------
  5786.     function GETNAME_AND_VERIFY_EXISTENCE return STRING is
  5787.  
  5788.         THE_FILE : constant STRING :=
  5789.                (VERIFY_LABEL
  5790.                (WITH_PROMPT     => FILE_PROMPT,
  5791.                 LENGTH_OF_LABEL => MAX_FILE_NAME_LENGTH,
  5792.                 STRING_TYPE     => "file name"));
  5793.  
  5794.     begin
  5795.  
  5796.         if FILE_OPS.FILE_EXISTS (WITH_NAME => THE_FILE) then
  5797.         return (THE_FILE);
  5798.         else
  5799.         TEXT_IO.NEW_LINE;
  5800.         TEXT_IO.PUT_LINE ("WARNING !!!");
  5801.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5802.         TEXT_IO.PUT_LINE ("File [" & THE_FILE & "] not found.");
  5803.         TEXT_IO.NEW_LINE (2);
  5804.  
  5805.         if (RETURN_YESNO
  5806.                (PROMPT     => ASCII.LF & ASCII.CR &
  5807.                       "Do you wish to try again " &
  5808.                       "on another file name (y/n) -->  ",
  5809.             DEFAULT    => NONE,
  5810.             FROM_VALUE => Y,
  5811.             TO_VALUE   => NO,
  5812.             ERROR_TEXT => ASCII.LF & ASCII.CR & "INPUT ERROR:  " &
  5813.                       "Answer must be either Y or N." &
  5814.                       ASCII.LF & ASCII.CR)) in Y .. YES then
  5815.             return (GETNAME_AND_VERIFY_EXISTENCE);
  5816.         else
  5817.             return (" ");
  5818.         end if;
  5819.         end if;
  5820.  
  5821.  
  5822.     end GETNAME_AND_VERIFY_EXISTENCE;
  5823.  
  5824.  
  5825.     begin
  5826.  
  5827.     declare
  5828.         THE_FILE_NAME : constant STRING := GETNAME_AND_VERIFY_EXISTENCE;
  5829.  
  5830.     begin
  5831.         if THE_FILE_NAME = " " then
  5832.         raise FILE_DOESNOT_EXIST;
  5833.         end if;
  5834.  
  5835.         FILE_OPS.OPEN
  5836.            (THE_FILE         => WORKING_FILE,
  5837.         WITH_NAME        => THE_FILE_NAME,
  5838.         TO_MODE          => TEXT_IO.IN_FILE,
  5839.         CREATION_ENABLED => TRUE);
  5840.  
  5841.         TEXT_IO.CLOSE (WORKING_FILE);
  5842.         return (THE_FILE_NAME);
  5843.  
  5844.     exception
  5845.         when FILE_DOESNOT_EXIST => 
  5846. --TEXT_IO.NEW_LINE (2);
  5847. --TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5848. --TEXT_IO.PUT_LINE ("Program terminates on user request");
  5849. --TEXT_IO.NEW_LINE (2);
  5850.         return (" ");
  5851.         -- raise STOP_ON_USER_REQUEST;
  5852.  
  5853.         when FILE_OPS.SYSTEM_CANNOT_OPEN_FILE => 
  5854.         TEXT_IO.NEW_LINE;
  5855.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  5856.  
  5857.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5858.         TEXT_IO.PUT_LINE
  5859.            ("[" & THE_FILE_NAME & "] cannot be accessed.");
  5860.         TEXT_IO.NEW_LINE (2);
  5861.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5862.         TEXT_IO.PUT_LINE
  5863.            ("A fatal error ocurred. Program cannot continue.");
  5864.         TEXT_IO.NEW_LINE (2);
  5865.         return (" ");
  5866.         -- raise END_FILE_HANDLER_REQUEST;
  5867.  
  5868.         when FILE_OPS.FILE_ALREADY_OPEN => 
  5869.         TEXT_IO.NEW_LINE;
  5870.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  5871.  
  5872.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5873.         TEXT_IO.PUT_LINE
  5874.            ("[" & THE_FILE_NAME & "] is currently in use.");
  5875.  
  5876.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5877.         TEXT_IO.PUT_LINE ("Program cannot access it");
  5878.         TEXT_IO.NEW_LINE (2);
  5879.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5880.         TEXT_IO.PUT_LINE
  5881.            ("A fatal error ocurred. Program cannot continue.");
  5882.         TEXT_IO.NEW_LINE (2);
  5883.         return (" ");
  5884.         -- raise END_FILE_HANDLER_REQUEST;
  5885.  
  5886.         when FILE_OPS.ILLEGAL_FILE_NAME => 
  5887.         TEXT_IO.NEW_LINE;
  5888.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  5889.  
  5890.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5891.         TEXT_IO.PUT_LINE ("[" & THE_FILE_NAME & "] is an illegal name");
  5892.         TEXT_IO.NEW_LINE (2);
  5893.  
  5894.         if (RETURN_YESNO
  5895.                (PROMPT     => "Do you wish to try again" &
  5896.                       " on another file name (y/n) -->  " &
  5897.                       ASCII.LF & ASCII.CR,
  5898.             DEFAULT    => NONE,
  5899.             FROM_VALUE => Y,
  5900.             TO_VALUE   => NO,
  5901.             ERROR_TEXT => ASCII.LF & ASCII.CR & "INPUT ERROR:  " &
  5902.                       "Answer must be either Y or N.")) in
  5903.            Y .. YES then
  5904.             return (VERIFY_INPUT (FILE_PROMPT, MAX_FILE_NAME_LENGTH));
  5905.  
  5906.         else
  5907.             --TEXT_IO.NEW_LINE (2);
  5908.             --TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  5909.             --TEXT_IO.PUT_LINE ("Program terminates on user request");
  5910.             --TEXT_IO.NEW_LINE (2);
  5911.             return (" ");
  5912.             -- raise STOP_ON_USER_REQUEST;
  5913.         end if;
  5914.     end;
  5915.     end VERIFY_INPUT;
  5916.  
  5917.  
  5918.  
  5919. end FILE_HANDLER;
  5920. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  5921. --schedule.ada
  5922. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  5923. with TEXT_IO,
  5924.      MENU,
  5925.      PRESS_RETURN_TO_CONTINUE,
  5926.      FATAL;
  5927.  
  5928. procedure SCHEDULE is
  5929. -------------------------------------------------------------------------------
  5930. -- Author : M. McNair, L. Yelowitz
  5931. -- Source:     Division Software Technology and Support
  5932. --             Western Development Laboratories
  5933. --             Ford Aerospace & Communications Corporation
  5934. --             ATTN:  Ada Tools Group
  5935. -- Date   : 28 May 1985
  5936. -- Summary:
  5937. --   This procedure is the main program to the NOSC Pert Model tools. It
  5938. --   calls the programs to create and modify files for Simpert, as well
  5939. --   as Simpert and Gantt. The constants
  5940. --   DISPLAY_HEIGHT and DISPLAY_WIDTH are used throughout both of
  5941. --   these programs. The modification of them here, will effect the
  5942. --   entire tool.
  5943. -- 
  5944. -------------------------------------------------------------------------------
  5945.     DISPLAY_HEIGHT : constant NATURAL := 24;
  5946.     DISPLAY_WIDTH  : constant NATURAL := 80;
  5947.  
  5948.     package MENU_OPS is new MENU (DISPLAY_WIDTH, DISPLAY_HEIGHT);
  5949.  
  5950.     TOP_LEVEL_MENU : constant MENU_OPS.ITEM_ARRAY_TYPE :=
  5951.              (1 => new STRING'("Create New Input File for Simpert"),
  5952.               2 => new STRING'("Modify Existing File for Simpert"),
  5953.               3 => new STRING'("Run Simpert"),
  5954.               4 => new STRING'("Run Gantt"),
  5955.               5 => new STRING'("Exit from Project Planning Tools."));
  5956.     -- top level menu
  5957.  
  5958.     TOP_LEVEL_TITLE : constant MENU_OPS.STRING_ACCESS_TYPE :=
  5959.               new STRING'("Project Planning Tools - Top Level Menu");
  5960.     -- top level menu title
  5961.  
  5962.     CHOICE : POSITIVE;
  5963.     -- menu choice of user
  5964.  
  5965.     procedure NEWFILE is separate;
  5966.  
  5967.     procedure MODIFY is separate;
  5968.  
  5969.     procedure PERT is separate;
  5970.  
  5971.     procedure OUT_GANTT is separate;  --change to OUT_GANTT for real
  5972.  
  5973.  
  5974.  
  5975. begin
  5976.     INITIAL_GREETING:
  5977.     begin
  5978.     -- This initial greeting has been localized here. To change what
  5979.     -- is seen, just modify the code in this block.
  5980.     TEXT_IO.NEW_PAGE;
  5981.     TEXT_IO.NEW_LINE (TEXT_IO.COUNT (DISPLAY_HEIGHT / 2 - 1));
  5982.     TEXT_IO.SET_COL (TEXT_IO.COUNT ((DISPLAY_WIDTH - 14) / 2));
  5983.     TEXT_IO.PUT_LINE ("Welcome to the");
  5984.     TEXT_IO.SET_COL (TEXT_IO.COUNT ((DISPLAY_WIDTH - 17) / 2));
  5985.     TEXT_IO.PUT_LINE ("Project Planning Tools.");
  5986.     delay 2.0;
  5987.     end INITIAL_GREETING;
  5988.  
  5989.     loop
  5990.     -- main program loop
  5991.  
  5992.     MENU_OPS.GET_MENU_VALUE
  5993.        (MENU_USED     => MENU_OPS.STRING_MENU (TOP_LEVEL_MENU),
  5994.         TITLE         => TOP_LEVEL_TITLE,
  5995.         CHOICE_CHOSEN => CHOICE);
  5996.  
  5997.     case CHOICE is
  5998. -- choice has been made - now branch accordingly
  5999.         when 1 => 
  6000.         NEWFILE;
  6001.  
  6002.         when 2 => 
  6003.         MODIFY;
  6004.  
  6005.         when 3 => 
  6006.         PERT;
  6007.  
  6008.         when 4 => 
  6009.         OUT_GANTT;
  6010.  
  6011.         when 5 => 
  6012.         exit;
  6013.  
  6014.         when others => 
  6015.         null;
  6016.     end case;
  6017.  
  6018.     delay 1.0;
  6019.  
  6020.     end loop;
  6021.  
  6022.     FINAL_GREETING:
  6023.     begin
  6024.     -- This block is similar to that which houses the intro. message.
  6025.     -- Make respective changes here.
  6026.     TEXT_IO.NEW_PAGE;
  6027.     TEXT_IO.NEW_LINE (TEXT_IO.COUNT (DISPLAY_HEIGHT / 2));
  6028.     TEXT_IO.SET_COL (TEXT_IO.COUNT ((DISPLAY_WIDTH - 42) / 2));
  6029.     TEXT_IO.PUT_LINE ("Thank you for using the Project Planning Tools.");
  6030.     end FINAL_GREETING;
  6031.  
  6032. exception
  6033.     when others => 
  6034. -- Throughout the tool, a FATAL procedure is available. This is
  6035. -- for debugging once the tool is in use. If an unexpected branch
  6036. -- in execution arises, this procedure will notify the user of
  6037. -- it.
  6038.     FATAL (UNIT => "SCHEDULE -- the main");
  6039. end SCHEDULE;
  6040. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6041. --newfile.ada
  6042. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6043. with TEXT_IO;
  6044. with SCREEN_IO,
  6045.      FILE_OPS;
  6046.  
  6047. separate (SCHEDULE)
  6048.  
  6049.  
  6050.  
  6051.  
  6052. ----------------------------------------------------------------
  6053. -- Author:     T. C. Bryan
  6054. -- Source:     Division Software Technology and Support
  6055. --             Western Development Laboratories
  6056. --             Ford Aerospace & Communications Corporation
  6057. --             ATTN:  Ada Tools Group
  6058. -- Date  :     April 1985
  6059. -- Summary:    This procedure creates a new input file for
  6060. --             SIMPERT run.
  6061. -----------------------------------------------------------------
  6062. procedure NEWFILE is
  6063.  
  6064.     subtype INT_NUM is INTEGER range 0 .. 1000000;
  6065.  
  6066.     package I_NUMBER is new TEXT_IO.INTEGER_IO (INT_NUM);
  6067.  
  6068.     subtype FLOAT_NUM is FLOAT range 0.0 .. 100_000.0;
  6069.  
  6070.     package F_NUMBER is new TEXT_IO.FLOAT_IO (FLOAT_NUM);
  6071.  
  6072.     MAXIMUM_NUMBER_OF_ACTIVITIES                : constant INTEGER := 4000;
  6073.     MAXIMUM_NUMBER_OF_NODES                     : constant INTEGER := 3400;
  6074.     MAXIMUM_NUMBER_OF_IN_OUT_NODES              : constant INTEGER := 25;
  6075.     MAXIMUM_NUMBER_OF_ACTIVITY_IN_CRITICAL_PATH : constant INTEGER := 2000;
  6076.     MAXIMUM_NUMBER_OF_NAME_NODES                : constant INTEGER := 9999;
  6077.  
  6078.     MAX_ERROR   : exception;
  6079.     END_NEWFILE : exception;
  6080.  
  6081.  
  6082.     UNITS            : STRING (1 .. 1) := " ";
  6083.     CONTINUE_OR_STOP : STRING (1 .. 1) := " ";
  6084.  
  6085.     type GO_OR_STOP is (S, STOP, CONTINUE, C);
  6086.     -------------------------------------------------------
  6087.     -- newly created INFILE = THE_NEWFILE_NAME(1..LAST_CHAR_OF_FILENAME)
  6088.     -------------------------------------------------------
  6089.     MAX_ACT_CODE          : constant INTEGER := 8;
  6090.     MAX_ACT_NAME          : constant INTEGER := 32;
  6091.     MAX_LINE              : constant INTEGER := 80;
  6092.     THE_NEWFILE_NAME      : STRING (1 .. MAX_LINE);
  6093.     MAX_FILE_NAME         : constant INTEGER := 32;
  6094.     LAST_CHAR_OF_FILENAME : NATURAL;
  6095.     THE_NEW_FILE          : TEXT_IO.FILE_TYPE;
  6096.  
  6097.     MAX_YEAR              : constant INTEGER := 99;
  6098.     KDAY, KMON, KYR       : INTEGER := 1;
  6099.  
  6100.     ACTIVITY_CODE         : STRING (1 .. MAX_LINE);
  6101.     CODE_LAST             : NATURAL;
  6102.     ACTIVITY_NAME         : STRING (1 .. MAX_LINE);
  6103.     NAME_LAST             : NATURAL;
  6104.     ERROR_INDENTATION     : TEXT_IO.COUNT := 15;
  6105.  
  6106.  
  6107.  
  6108.  
  6109.     -------------------------------------------------------
  6110.     -- function receives an integer within the range 
  6111.     -- start_integer .. end_integer
  6112.     -------------------------------------------------------
  6113.     function RETURN_INTEGER (INPUT_PROMPT  : STRING;
  6114.                  START_INTEGER : INTEGER := 0;
  6115.                  END_INTEGER   : INTEGER := 0) return INTEGER is
  6116.  
  6117.  
  6118.     begin
  6119.     return SCREEN_IO.RETURNED_INTEGER
  6120.           (PROMPT     => ASCII.LF & ASCII.CR & INPUT_PROMPT &
  6121.                  ASCII.LF & ASCII.CR,
  6122.            FROM_VALUE => START_INTEGER,
  6123.            TO_VALUE   => END_INTEGER,
  6124.            CONFIRM    => FALSE,
  6125.            ERROR_TEXT =>
  6126.              ASCII.LF & ASCII.CR &
  6127.              "INPUT ERROR:   Program expects an integer number " &
  6128.              "within " & INTEGER'IMAGE (START_INTEGER) & " through " &
  6129.              INTEGER'IMAGE (END_INTEGER) & "." & ASCII.LF & ASCII.CR &
  6130.              "               Please try again." & ASCII.LF & ASCII.CR);
  6131.     end RETURN_INTEGER;
  6132.  
  6133.  
  6134.  
  6135.     -----------------------------------
  6136.     -- put out a welcome message
  6137.     -----------------------------------
  6138.     procedure WELCOME_MESSAGE is
  6139.     INDENTATION    : TEXT_IO.COUNT := 7;
  6140.     INDENT_FOR_MAX : TEXT_IO.COUNT := 50;
  6141.  
  6142.     begin
  6143.     TEXT_IO.NEW_PAGE;
  6144.     TEXT_IO.NEW_LINE (5);
  6145.     TEXT_IO.SET_COL (TO => INDENTATION);
  6146.     TEXT_IO.PUT ("      Welcome to NEWFILE Version 1.0");
  6147.  
  6148.     TEXT_IO.NEW_LINE (3);
  6149.     TEXT_IO.SET_COL (TO => INDENTATION);
  6150.     TEXT_IO.PUT ("Network constraints for this version are:");
  6151.  
  6152.     TEXT_IO.NEW_LINE (2);
  6153.     TEXT_IO.SET_COL (TO => INDENTATION);
  6154.     TEXT_IO.PUT ("    Max number of activities (arcs)       =");
  6155.     TEXT_IO.SET_COL (TO => INDENT_FOR_MAX);
  6156.     I_NUMBER.PUT (MAXIMUM_NUMBER_OF_ACTIVITIES);
  6157.  
  6158.     TEXT_IO.NEW_LINE;
  6159.     TEXT_IO.SET_COL (TO => INDENTATION);
  6160.     TEXT_IO.PUT ("    Max number of nodes                   =");
  6161.     TEXT_IO.SET_COL (TO => INDENT_FOR_MAX);
  6162.     I_NUMBER.PUT (MAXIMUM_NUMBER_OF_NODES);
  6163.  
  6164.     TEXT_IO.NEW_LINE;
  6165.     TEXT_IO.SET_COL (TO => INDENTATION);
  6166.     TEXT_IO.PUT ("    Max number of in/out arcs at any node =");
  6167.     TEXT_IO.SET_COL (TO => INDENT_FOR_MAX);
  6168.     I_NUMBER.PUT (MAXIMUM_NUMBER_OF_IN_OUT_NODES);
  6169.  
  6170.     TEXT_IO.NEW_LINE;
  6171.     TEXT_IO.SET_COL (TO => INDENTATION);
  6172.     TEXT_IO.PUT ("    Max number of arcs in critical path   =");
  6173.     TEXT_IO.SET_COL (TO => INDENT_FOR_MAX);
  6174.     I_NUMBER.PUT (MAXIMUM_NUMBER_OF_ACTIVITY_IN_CRITICAL_PATH);
  6175.  
  6176.     TEXT_IO.NEW_LINE (5);
  6177.     TEXT_IO.SET_COL (TO => INDENTATION);
  6178.         PRESS_RETURN_TO_CONTINUE;
  6179.     TEXT_IO.NEW_PAGE;
  6180.     end WELCOME_MESSAGE;
  6181.  
  6182.     ----------------------------------------
  6183.     -- prompt the user for the time units
  6184.     -- Units is either in days or in weeks
  6185.     ----------------------------------------
  6186.     procedure SELECTION_DAYS_OR_WEEKS is
  6187.  
  6188.     type D_OR_W is (D, DAY, DAYS, W, WEEK, WEEKS, NONE);
  6189.  
  6190.     function RETURNED_DW is new SCREEN_IO.RETURNED_ENUMERATION (D_OR_W);
  6191.  
  6192.     THE_ANSWER : D_OR_W := NONE;
  6193.  
  6194.  
  6195.     begin
  6196.  
  6197.     while THE_ANSWER not in D .. WEEKS loop
  6198.         THE_ANSWER := RETURNED_DW
  6199.                  (PROMPT     =>
  6200.                 ASCII.LF & ASCII.CR &
  6201.                 "           <-- ENTER time units " &
  6202.                 "(days = D, weeks = W)" & ASCII.CR,
  6203.                   DEFAULT    => NONE,
  6204.                   FROM_VALUE => D,
  6205.                   TO_VALUE   => WEEKS,
  6206.                   CONFIRM    => FALSE,
  6207.                   ERROR_TEXT =>
  6208.                 ASCII.LF & ASCII.CR &
  6209.                 "INPUT ERROR:  Answer must be either " &
  6210.                 "D for days or W for weeks");
  6211.     end loop;
  6212.  
  6213.     TEXT_IO.NEW_LINE;
  6214.  
  6215.     declare
  6216.         TEMP_UNITS : constant STRING := D_OR_W'IMAGE (THE_ANSWER);
  6217.     begin
  6218.         UNITS (1) := TEMP_UNITS (TEMP_UNITS'FIRST);
  6219.     end;
  6220.     end SELECTION_DAYS_OR_WEEKS;
  6221.  
  6222.  
  6223.     -------------------------------------------
  6224.     -- continue or not continue !!!
  6225.     -------------------------------------------
  6226.     procedure SELECTION_CONTINUE_OR_STOP is
  6227.  
  6228.     function RETURNED_GS is new SCREEN_IO.RETURNED_ENUMERATION (GO_OR_STOP);
  6229.  
  6230.     THE_ANSWER : GO_OR_STOP;
  6231.  
  6232.  
  6233.     begin
  6234.     THE_ANSWER := RETURNED_GS
  6235.              (PROMPT     => ASCII.LF & ASCII.CR &
  6236.                     "ENTER 'C' to continue program " &
  6237.                     "or 'S' to stop it -->   ",
  6238.               ERROR_TEXT =>
  6239.                 ASCII.LF & ASCII.CR &
  6240.                 "INPUT ERROR:  Answer must be either C for " &
  6241.                 "continue or S for stop  ");
  6242.  
  6243.     declare
  6244.         TEMP_UNITS : constant STRING := GO_OR_STOP'IMAGE (THE_ANSWER);
  6245.  
  6246.     begin
  6247.         CONTINUE_OR_STOP (1) := TEMP_UNITS (TEMP_UNITS'FIRST);
  6248.     end;
  6249.  
  6250.     end SELECTION_CONTINUE_OR_STOP;
  6251.  
  6252.  
  6253.  
  6254.     --------------------------------
  6255.     -- obtain a string from user
  6256.     --------------------------------
  6257.     procedure OBTAIN_NAME (WITH_PROMPT     : STRING := " ";
  6258.                THE_NAME        : out STRING;
  6259.                END_OF_THE_NAME : in out NATURAL;
  6260.                MAX_OF_THE_NAME : INTEGER := 8) is
  6261.  
  6262.     begin
  6263.     loop
  6264.         declare
  6265.         TEMP_NAME: constant STRING :=
  6266.               SCREEN_IO.RETURNED_STRING
  6267.                   (PROMPT  => ASCII.LF & ASCII.CR &
  6268.                             WITH_PROMPT &
  6269.                    ASCII.LF & ASCII.CR, 
  6270.                    CONFIRM => FALSE);
  6271.         begin
  6272.         END_OF_THE_NAME := TEMP_NAME'LENGTH;
  6273.         THE_NAME(1..END_OF_THE_NAME) := TEMP_NAME;
  6274.         exit when END_OF_THE_NAME in 1 .. MAX_OF_THE_NAME;
  6275.             TEXT_IO.NEW_LINE;
  6276.             TEXT_IO.PUT_LINE ("INPUT ERROR:");
  6277.  
  6278.             TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6279.             TEXT_IO.PUT_LINE ("Name must be within 1 through " &
  6280.                   INTEGER'IMAGE (MAX_OF_THE_NAME) & " characters.");
  6281.  
  6282.             TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6283.             TEXT_IO.PUT_LINE ("Please try again.");
  6284.             TEXT_IO.NEW_LINE;
  6285.         end;
  6286.     end loop;
  6287.  
  6288.     end OBTAIN_NAME;
  6289.  
  6290.  
  6291.     -------------------------------------------
  6292.     -- create a user requested new simpert file
  6293.     -------------------------------------------
  6294.     procedure CREATEF is
  6295.     CONTINUE_CASE : GO_OR_STOP := C;
  6296.  
  6297.     begin
  6298.     -----------------------------------------------
  6299.     -- gets file name from the user and creates it...
  6300.     -----------------------------------------------
  6301.  
  6302.     TEXT_IO.NEW_LINE;
  6303.     OBTAIN_NAME
  6304.        (WITH_PROMPT     => "              <-- ENTER name of newfile" &
  6305.                    ASCII.CR,
  6306.         THE_NAME        => THE_NEWFILE_NAME,
  6307.         END_OF_THE_NAME => LAST_CHAR_OF_FILENAME,
  6308.         MAX_OF_THE_NAME => MAX_FILE_NAME);
  6309.     TEXT_IO.NEW_LINE;
  6310.  
  6311.     if FILE_OPS.FILE_EXISTS
  6312.           (WITH_NAME => THE_NEWFILE_NAME (1 .. LAST_CHAR_OF_FILENAME)) then
  6313.  
  6314.         TEXT_IO.NEW_LINE;
  6315.         TEXT_IO.PUT_LINE ("WARNING!!!");
  6316.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6317.         TEXT_IO.PUT_LINE ("File " &
  6318.                   THE_NEWFILE_NAME (1 .. LAST_CHAR_OF_FILENAME) &
  6319.                   " already exists");
  6320.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6321.         TEXT_IO.PUT_LINE
  6322.            ("and will be overwritten.  Is it ok to continue?");
  6323.         SELECTION_CONTINUE_OR_STOP;
  6324.  
  6325.         if GO_OR_STOP'VALUE (CONTINUE_OR_STOP) = CONTINUE_CASE then
  6326.         TEXT_IO.CREATE
  6327.            (THE_NEW_FILE, TEXT_IO.OUT_FILE,
  6328.             THE_NEWFILE_NAME (1 .. LAST_CHAR_OF_FILENAME));
  6329.         TEXT_IO.CLOSE (THE_NEW_FILE);
  6330.         else
  6331.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6332.         TEXT_IO.PUT_LINE ("Program terminates per user request");
  6333.         TEXT_IO.NEW_LINE;
  6334.         raise END_NEWFILE;
  6335.         end if;
  6336.     end if;
  6337.  
  6338.     FILE_OPS.OPEN
  6339.        (THE_FILE         => THE_NEW_FILE,
  6340.         WITH_NAME        => THE_NEWFILE_NAME (1 .. LAST_CHAR_OF_FILENAME),
  6341.         TO_MODE          => TEXT_IO.OUT_FILE,
  6342.         CREATION_ENABLED => TRUE);
  6343.     ----------------------------------
  6344.     -- file exception handlers...
  6345.     ----------------------------------
  6346.     exception
  6347.     when FILE_OPS.SYSTEM_CANNOT_CREATE_FILE | FILE_OPS.ILLEGAL_FILE_NAME => 
  6348.         TEXT_IO.NEW_LINE;
  6349.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  6350.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6351.         TEXT_IO.PUT_LINE ("Program cannot create " &
  6352.                   THE_NEWFILE_NAME (1 .. LAST_CHAR_OF_FILENAME));
  6353.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6354.         TEXT_IO.PUT_LINE
  6355.            ("due to an access problem or an illegal file name");
  6356.         raise END_NEWFILE;
  6357.  
  6358.     when FILE_OPS.FILE_ALREADY_OPEN => 
  6359.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  6360.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6361.         TEXT_IO.PUT_LINE (THE_NEWFILE_NAME (1 .. LAST_CHAR_OF_FILENAME) &
  6362.                   " exists and is currently in use.");
  6363.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6364.         TEXT_IO.PUT_LINE ("Program cannot create it");
  6365.         raise END_NEWFILE;
  6366.  
  6367.  
  6368.  
  6369.  
  6370.     end CREATEF;
  6371.  
  6372.     -----------------------------------------------
  6373.     -- promt user for a project start date .....
  6374.     -----------------------------------------------
  6375.     procedure STARTDATE is
  6376.  
  6377.  
  6378.     begin
  6379.        ----------------------------------------------------
  6380.        -- a loop used to assure that user only enters 8
  6381.        -- characters for start date which is in the form
  6382.        -- of dd/mm/yy where dd =< 31 days, mm =<12 months,
  6383.        -- and yy between rang 80..max_year; where max_year
  6384.        -- has been globally defined.  An example is 28/11/80
  6385.        ----------------------------------------------------
  6386.  
  6387.     loop
  6388.         declare
  6389.            START_DATE : constant STRING :=
  6390.               SCREEN_IO.RETURNED_STRING
  6391.                   (PROMPT  => ASCII.LF & ASCII.CR &
  6392.                            "dd/mm/yy    <-- ENTER Estimated Project " &
  6393.                    "start date" & ASCII.LF & ASCII.CR, 
  6394.                    CONFIRM => FALSE);
  6395.         begin
  6396.         ----------------------------------------------------
  6397.         -- the inputted start date is parsed into
  6398.         -- dd, mm, yy string and inserted into three global
  6399.         -- variables named kday, kmon, and kyr respectively.
  6400.         ----------------------------------------------------
  6401.  
  6402.         KDAY := INTEGER'VALUE (START_DATE(1..2));
  6403.         KMON := INTEGER'VALUE (START_DATE(4..5));
  6404.         KYR  := INTEGER'VALUE (START_DATE(7..8));
  6405.  
  6406.             TEXT_IO.NEW_LINE;
  6407.             exit when START_DATE'LENGTH  = 8 and
  6408.               KDAY in 1 .. 31 and
  6409.               KMON in 1 .. 12 and KYR in 80 .. MAX_YEAR;
  6410.  
  6411.             TEXT_IO.PUT_LINE ("INPUT ERROR:");
  6412.  
  6413.             if START_DATE /= " " then
  6414.             TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6415.             TEXT_IO.PUT_LINE
  6416.                (START_DATE & "  is an incorrect response.");
  6417.             end if;
  6418.  
  6419.             TEXT_IO.NEW_LINE;
  6420.             TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6421.             TEXT_IO.PUT_LINE
  6422.                ("Start date needed must be in the form of dd/mm/yy.");
  6423.  
  6424.             TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6425.             TEXT_IO.PUT_LINE
  6426.                ("where [dd] is between 01..31 days, [mm] 01..12 months,");
  6427.  
  6428.             TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6429.             TEXT_IO.PUT ("and [yy] 80..");
  6430.             I_NUMBER.PUT (MAX_YEAR, WIDTH => 2);
  6431.             TEXT_IO.PUT_LINE (".  Please try again." & ASCII.LF & ASCII.CR);
  6432.  
  6433.         exception
  6434.             when others => null;
  6435.         end;
  6436.     end loop;
  6437.     end STARTDATE;
  6438.  
  6439.  
  6440.  
  6441.     ----------------------------------------------------------
  6442.     -- write input obtained to the newly created simpert file
  6443.     ----------------------------------------------------------
  6444.     procedure WRITEF is
  6445.  
  6446.  
  6447.     OPTIMISTICS                   : FLOAT;
  6448.     MOST_LIKELY                   : FLOAT;
  6449.     PESSIMISTICS                  : FLOAT;
  6450.     AVERAGE_NU                    : FLOAT;
  6451.     AVERAGE_COST                  : FLOAT;
  6452.  
  6453.     HEAD_NODE, TAIL_NODE          : INTEGER := 0;
  6454.     NUMBER_OF_ACTIVITIES_INPUTTED : INTEGER := 1;
  6455.  
  6456.     INPUT_COMPLETE                : BOOLEAN := FALSE;
  6457.  
  6458.     type DUMMIES is (DUMMY);
  6459.  
  6460.  
  6461.  
  6462.     -------------------------------------------------------
  6463.     -- writes global variables to the newly created file
  6464.     -------------------------------------------------------
  6465.     procedure WRITE_GLOBAL is
  6466.         PROG : constant STRING := "S";
  6467.  
  6468.     begin
  6469.  
  6470.         TEXT_IO.PUT_LINE (THE_NEW_FILE, PROG);
  6471.         TEXT_IO.PUT_LINE (THE_NEW_FILE, UNITS);
  6472.         I_NUMBER.PUT (THE_NEW_FILE, KDAY, WIDTH => 2);
  6473.         TEXT_IO.PUT (THE_NEW_FILE, " ");
  6474.         I_NUMBER.PUT (THE_NEW_FILE, KMON, WIDTH => 2);
  6475.         TEXT_IO.PUT (THE_NEW_FILE, " ");
  6476.         I_NUMBER.PUT (THE_NEW_FILE, KYR, WIDTH => 2);
  6477.         TEXT_IO.NEW_LINE (THE_NEW_FILE);
  6478.         TEXT_IO.PUT (THE_NEW_FILE,
  6479.              "  CODE        " &
  6480.              "ACTIVITY TITLE              TAIL HEAD ");
  6481.         TEXT_IO.PUT_LINE (THE_NEW_FILE,
  6482.                   "  OPTM  M.L.  PESS STAF $RATE/ODC");
  6483.         TEXT_IO.PUT (THE_NEW_FILE,
  6484.              "XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXX XXXX");
  6485.         TEXT_IO.PUT_LINE (THE_NEW_FILE,
  6486.                   "  XXX.X XXX.X XXX.X XX.X XXXXXXX.X");
  6487.  
  6488.     end WRITE_GLOBAL;
  6489.  
  6490.     -------------------------------------------------------
  6491.     -- function verifies string called "dummy" ...
  6492.     -------------------------------------------------------
  6493.     function IN_DUMMIES return BOOLEAN is
  6494.         D_TEMP : DUMMIES;
  6495.  
  6496.  
  6497.     begin
  6498.         D_TEMP := DUMMIES'VALUE (ACTIVITY_NAME (1 .. 5));
  6499.         return TRUE;
  6500.     exception
  6501.         when CONSTRAINT_ERROR =>  return FALSE;
  6502.     end IN_DUMMIES;
  6503.  
  6504.  
  6505.  
  6506.  
  6507.     -------------------------------------------------------
  6508.     -- prompt user for all estimates for one activity
  6509.     -- input data must be in float number ...
  6510.     -------------------------------------------------------
  6511.     procedure NEW_SIMPERT_LINE is
  6512.  
  6513.  
  6514.         function RETURN_ESTIMATE (INPUT_PROMPT : STRING;
  6515.                       BEGIN_AT     : FLOAT := 0.0;
  6516.                       LIMIT_FLOAT  : FLOAT := 999.90000)
  6517.                        return FLOAT is
  6518.  
  6519.  
  6520.         begin
  6521.         return SCREEN_IO.RETURNED_FLOAT
  6522.               (PROMPT     => ASCII.LF & ASCII.CR & INPUT_PROMPT &
  6523.                      ASCII.LF & ASCII.CR,
  6524.                FROM_VALUE => BEGIN_AT,
  6525.                CONFIRM    => FALSE,
  6526.                TO_VALUE   => LIMIT_FLOAT);
  6527.  
  6528.         end RETURN_ESTIMATE;
  6529.  
  6530.  
  6531.     begin
  6532.  
  6533.         OPTIMISTICS := RETURN_ESTIMATE
  6534.                   (INPUT_PROMPT =>
  6535.                  "XXX.X  <--ENTER optimistic (1%) " &
  6536.                  "time estimate");
  6537.  
  6538.         MOST_LIKELY := RETURN_ESTIMATE
  6539.                   (INPUT_PROMPT =>
  6540.                  "XXX.X  <--ENTER most likely (1%) " &
  6541.                  "time estimate");
  6542.         PESSIMISTICS := RETURN_ESTIMATE
  6543.                    (INPUT_PROMPT =>
  6544.                   "XXX.X  <--ENTER pessimistic (1%) " &
  6545.                   "time estimate");
  6546.  
  6547.         if OPTIMISTICS = 0.0 and
  6548.            MOST_LIKELY = 0.0 and PESSIMISTICS = 0.0 then
  6549.         AVERAGE_NU := 0.0;
  6550.         AVERAGE_COST := 0.0;
  6551.         else
  6552.         AVERAGE_NU := RETURN_ESTIMATE
  6553.                  (INPUT_PROMPT =>
  6554.                     "XX.X  <--ENTER average number of " &
  6555.                     "equivalent of full-time personnel",
  6556.                   LIMIT_FLOAT  => 99.90000);
  6557.         AVERAGE_COST :=
  6558.           RETURN_ESTIMATE
  6559.              (INPUT_PROMPT =>
  6560.             "XXXXXXX.X  <--ENTER average cost per " &
  6561.             "man-time unit",
  6562.               BEGIN_AT     => 1.0,
  6563.               LIMIT_FLOAT  => 999999.90000);
  6564.         end if;
  6565.  
  6566.     end NEW_SIMPERT_LINE;
  6567.  
  6568.  
  6569.  
  6570.     -------------------------------------------------------
  6571.     -- prompt user for activity name & node information
  6572.     -------------------------------------------------------
  6573.     procedure NAME_NODE_ENTRY is
  6574.  
  6575.  
  6576.  
  6577. -----------------------------------
  6578. -- accept input for one activity
  6579. -----------------------------------
  6580.         procedure TAKE_INPUT is
  6581.  
  6582.         begin
  6583.  
  6584.         ------------------------------------------
  6585.         -- NAME is a 32 character string
  6586.         -- ACTIVITY CODE is an 8 character string
  6587.         ------------------------------------------
  6588.         TEXT_IO.NEW_PAGE;
  6589.         TEXT_IO.NEW_LINE (2);
  6590.  
  6591.         TEXT_IO.SET_COL (TO => 15);
  6592.         TEXT_IO.PUT ("Activity [arc] number ");
  6593.         I_NUMBER.PUT (NUMBER_OF_ACTIVITIES_INPUTTED);
  6594.         TEXT_IO.NEW_LINE (2);
  6595.  
  6596.         OBTAIN_NAME
  6597.            (WITH_PROMPT     => "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  " &
  6598.                        "<-- ENTER name of activity",
  6599.             THE_NAME        => ACTIVITY_NAME,
  6600.             END_OF_THE_NAME => NAME_LAST,
  6601.             MAX_OF_THE_NAME => MAX_ACT_NAME);
  6602.         TEXT_IO.NEW_LINE;
  6603.  
  6604.         if IN_DUMMIES then
  6605.             CODE_LAST := 8;
  6606.             ACTIVITY_CODE (1 .. CODE_LAST) := (1 .. CODE_LAST => ' ');
  6607.         else
  6608.             TEXT_IO.NEW_LINE;
  6609.             OBTAIN_NAME
  6610.                (WITH_PROMPT     => "XXXXXXXX  <-- ENTER arc code [WBS]",
  6611.             THE_NAME        => ACTIVITY_CODE,
  6612.             END_OF_THE_NAME => CODE_LAST,
  6613.             MAX_OF_THE_NAME => MAX_ACT_CODE);
  6614.             TEXT_IO.NEW_LINE;
  6615.         end if;
  6616.         -------------------------------------------------------
  6617.         -- TAIL and HEAD nodes must be greater than zero .......
  6618.         -------------------------------------------------------
  6619.         TAIL_NODE := RETURN_INTEGER
  6620.                 (INPUT_PROMPT  => "XXXX  <--ENTER tail node",
  6621.                  START_INTEGER => 1,
  6622.                  END_INTEGER   => MAXIMUM_NUMBER_OF_NAME_NODES);
  6623.         TEXT_IO.NEW_LINE;
  6624.  
  6625.         HEAD_NODE := RETURN_INTEGER
  6626.                 (INPUT_PROMPT  => "XXXX  <--ENTER head node",
  6627.                  START_INTEGER => 1,
  6628.                  END_INTEGER   => MAXIMUM_NUMBER_OF_NAME_NODES);
  6629.  
  6630.         TEXT_IO.NEW_PAGE;
  6631.         -- 
  6632.         --   CHECK FOR STRING "DUMMY" IN FIRST 5 CHARACTERS of ACT .....
  6633.         -- 
  6634.         if IN_DUMMIES then
  6635.             OPTIMISTICS := 0.0;
  6636.             MOST_LIKELY := 0.0;
  6637.             PESSIMISTICS := 0.0;
  6638.             AVERAGE_NU := 0.0;
  6639.             AVERAGE_COST := 0.0;
  6640.             TEXT_IO.NEW_LINE (5);
  6641.         else
  6642.             TEXT_IO.NEW_LINE (3);
  6643.             TEXT_IO.SET_COL (TO => 10);
  6644.             TEXT_IO.PUT_LINE
  6645.                ("ENTER following parameters for activity:");
  6646.  
  6647.             TEXT_IO.SET_COL (TO => 14);
  6648.             TEXT_IO.PUT_LINE (ACTIVITY_NAME (1 .. NAME_LAST));
  6649.             TEXT_IO.NEW_LINE (3);
  6650.             -- 
  6651.             --          NEW FILE SIMPERT .....
  6652.             -- 
  6653.             -------------------------------------------------------
  6654.             -- MOST_LIKELY must be within the range of OPTI..PESSI
  6655.             -------------------------------------------------------
  6656.             NEW_SIMPERT_LINE;
  6657.  
  6658.             loop
  6659.             if OPTIMISTICS > MOST_LIKELY or
  6660.                MOST_LIKELY > PESSIMISTICS then
  6661.                 TEXT_IO.NEW_LINE;
  6662.                 TEXT_IO.PUT_LINE ("INPUT ERROR:");
  6663.  
  6664.                 TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6665.                 TEXT_IO.PUT_LINE
  6666.                    ("Relative size of input is inconsistent.");
  6667.                 TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6668.                 TEXT_IO.PUT_LINE
  6669.                     ("Optimistics must be <= most likely " &
  6670.                     " <= pessimistic");
  6671.  
  6672.                 TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6673.                 TEXT_IO.PUT_LINE ("Please try again.");
  6674.                 TEXT_IO.NEW_LINE (2);
  6675.                 NEW_SIMPERT_LINE;
  6676.             else
  6677.                 exit;
  6678.             end if;
  6679.             end loop;
  6680.         end if;
  6681.  
  6682.         end TAKE_INPUT;
  6683.  
  6684.  
  6685.     begin
  6686.         TAKE_INPUT;
  6687.  
  6688.         loop
  6689.         declare
  6690.             LOOP_ANSWER : constant STRING :=
  6691.                   SCREEN_IO.RETURNED_STRING
  6692.                      (PROMPT =>
  6693.                     ASCII.LF & ASCII.CR &
  6694.                     "ENTER [r] to RE_ENTER parameters " &
  6695.                     "for this activity," & ASCII.LF &
  6696.                     ASCII.CR &
  6697.                     "or [s] for STOP inputting, or press " &
  6698.                     "RETURN to continue ....." &
  6699.                     ASCII.LF & ASCII.CR);
  6700.  
  6701.         begin
  6702.  
  6703.             if LOOP_ANSWER = "r" or LOOP_ANSWER = "R" then
  6704.             TAKE_INPUT;
  6705.  
  6706.             elsif LOOP_ANSWER = "s" or LOOP_ANSWER = "S" then
  6707.             INPUT_COMPLETE := TRUE;
  6708.             exit;
  6709.  
  6710.             elsif LOOP_ANSWER = "" then
  6711.             exit;
  6712.             else
  6713.             TEXT_IO.NEW_LINE;
  6714.             TEXT_IO.PUT_LINE ("INPUT ERROR:  Please try again.");
  6715.             TEXT_IO.NEW_LINE;
  6716.             end if;
  6717.         end;
  6718.         end loop;
  6719.  
  6720.         TEXT_IO.NEW_LINE (1);
  6721.     end NAME_NODE_ENTRY;
  6722.  
  6723.  
  6724.  
  6725.  
  6726.     begin
  6727.     --   MAIN
  6728.     WRITE_GLOBAL;
  6729.  
  6730.     for I in 1 .. MAXIMUM_NUMBER_OF_ACTIVITIES loop
  6731.         -- 
  6732.         --          READ ACTIVITY NAME & NODE NUMBERS FROM SCREEN .....
  6733.         -- 
  6734.  
  6735.         NAME_NODE_ENTRY;
  6736.  
  6737.         -----------------### text_io limitation ### ----------------
  6738.  
  6739.         -- when text_io.float_io.put encounters the float value 0.0
  6740.         -- it puts out the sequence 0.^A .  In order to make up
  6741.         -- for this limitation, the program is coded so that the string
  6742.         -- "0.0" will be printed in lieu when such condition is met.
  6743.  
  6744.         --------------- ### end text_io limitation ### --------------
  6745.  
  6746.  
  6747.         TEXT_IO.PUT (THE_NEW_FILE, ACTIVITY_CODE (1 .. CODE_LAST));
  6748.  
  6749.         TEXT_IO.SET_COL (THE_NEW_FILE, TO => 10);
  6750.         TEXT_IO.PUT (THE_NEW_FILE, ACTIVITY_NAME (1 .. NAME_LAST));
  6751.  
  6752.         TEXT_IO.SET_COL (THE_NEW_FILE, TO => 43);
  6753.         I_NUMBER.PUT (THE_NEW_FILE, TAIL_NODE, WIDTH => 4);
  6754.  
  6755.         TEXT_IO.SET_COL (THE_NEW_FILE, TO => 48);
  6756.         I_NUMBER.PUT (THE_NEW_FILE, HEAD_NODE, WIDTH => 4);
  6757.  
  6758.         TEXT_IO.SET_COL (THE_NEW_FILE, TO => 54);
  6759.  
  6760.         if OPTIMISTICS = 0.0 then
  6761.         TEXT_IO.PUT (THE_NEW_FILE, "  0.0");
  6762.         else
  6763.         F_NUMBER.PUT
  6764.            (THE_NEW_FILE, OPTIMISTICS, EXP => 0, FORE => 3, AFT => 1);
  6765.         end if;
  6766.  
  6767.         TEXT_IO.SET_COL (THE_NEW_FILE, TO => 60);
  6768.  
  6769.         if MOST_LIKELY = 0.0 then
  6770.         TEXT_IO.PUT (THE_NEW_FILE, "  0.0");
  6771.         else
  6772.         F_NUMBER.PUT
  6773.            (THE_NEW_FILE, MOST_LIKELY, EXP => 0, FORE => 3, AFT => 1);
  6774.         end if;
  6775.  
  6776.         TEXT_IO.SET_COL (THE_NEW_FILE, TO => 66);
  6777.  
  6778.         if PESSIMISTICS = 0.0 then
  6779.         TEXT_IO.PUT (THE_NEW_FILE, "  0.0");
  6780.         else
  6781.         F_NUMBER.PUT
  6782.            (THE_NEW_FILE, PESSIMISTICS, EXP => 0, FORE => 3, AFT => 1);
  6783.         end if;
  6784.  
  6785.         TEXT_IO.SET_COL (THE_NEW_FILE, TO => 72);
  6786.  
  6787.         if AVERAGE_NU = 0.0 then
  6788.         TEXT_IO.PUT (THE_NEW_FILE, " 0.0");
  6789.         else
  6790.         F_NUMBER.PUT
  6791.            (THE_NEW_FILE, AVERAGE_NU, EXP => 0, FORE => 2, AFT => 1);
  6792.         end if;
  6793.  
  6794.         TEXT_IO.SET_COL (THE_NEW_FILE, TO => 77);
  6795.  
  6796.         if AVERAGE_COST = 0.0 then
  6797.         TEXT_IO.PUT (THE_NEW_FILE, "      0.0");
  6798.         else
  6799.         F_NUMBER.PUT
  6800.            (THE_NEW_FILE, AVERAGE_COST, EXP => 0, FORE => 7, AFT => 1);
  6801.         end if;
  6802.  
  6803.         TEXT_IO.NEW_LINE (THE_NEW_FILE);
  6804.  
  6805.         exit when INPUT_COMPLETE;
  6806.         NUMBER_OF_ACTIVITIES_INPUTTED := NUMBER_OF_ACTIVITIES_INPUTTED + 1;
  6807.  
  6808.     end loop;
  6809.  
  6810.     if NUMBER_OF_ACTIVITIES_INPUTTED > MAXIMUM_NUMBER_OF_ACTIVITIES then
  6811.         TEXT_IO.NEW_LINE;
  6812.         TEXT_IO.PUT_LINE ("NETWORK CONSTRAINT ERROR:");
  6813.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6814.         TEXT_IO.PUT ("Number of activities exceeds the maximum limit of ");
  6815.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  6816.         I_NUMBER.PUT (MAXIMUM_NUMBER_OF_ACTIVITIES);
  6817.         TEXT_IO.PUT (".   Program aborts.");
  6818.         TEXT_IO.NEW_LINE;
  6819.         TEXT_IO.CLOSE (THE_NEW_FILE);
  6820.         raise MAX_ERROR;
  6821.     end if;
  6822.  
  6823.     -------------------------
  6824.     -- error handlers
  6825.     -------------------------
  6826.     exception
  6827.     when MAX_ERROR => 
  6828.         raise END_NEWFILE;
  6829.     end WRITEF;
  6830.  
  6831.  
  6832.     -------------------------
  6833.     -- THE MAIN BODY OF NEWFILE
  6834.     -------------------------
  6835. begin
  6836.     -- 
  6837.     -- To screen: welcome statement and network constraints ...
  6838.     -- 
  6839.     WELCOME_MESSAGE;
  6840.  
  6841.     -- 
  6842.     -- Enter time units (D = days or W = weeks) ....
  6843.     -- 
  6844.     TEXT_IO.NEW_LINE (4);
  6845.  
  6846.     SELECTION_DAYS_OR_WEEKS;
  6847.  
  6848.     -- 
  6849.     -- Open new file to be generated .....
  6850.     -- 
  6851.     CREATEF;
  6852.  
  6853.     -- 
  6854.     -- Read estimated project start date from screen .....
  6855.     -- 
  6856.     STARTDATE;
  6857.     -- 
  6858.     -- New file simpert .....
  6859.     -- 
  6860.     WRITEF;
  6861.     -- 
  6862.     -- Close new file .....
  6863.     -- 
  6864.     TEXT_IO.CLOSE (THE_NEW_FILE);
  6865.  
  6866. exception
  6867.     when END_NEWFILE =>
  6868.         PRESS_RETURN_TO_CONTINUE;
  6869.  
  6870.     when others => 
  6871.     FATAL (UNIT => "Schedule Tool - Unit named " &
  6872.                "[NEWFILE]");
  6873.  
  6874. end NEWFILE;
  6875. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6876. --modify.ada
  6877. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6878. with TEXT_IO;
  6879. with SCREEN_IO,
  6880.      FILE_OPS;
  6881.  
  6882.  
  6883.  
  6884. separate (SCHEDULE)
  6885.  
  6886. ------------------------------------------------------------------------
  6887. -- Author:     T.C. Bryan
  6888. -- Source:     Division Software Technology and Support
  6889. --             Western Development Laboratories
  6890. --             Ford Aerospace & Communications Corporation
  6891. --             ATTN:  Ada Tools Group
  6892. -- Date  :     April 1985
  6893. -- Summary:    This procedure edits input files for
  6894. --             SIMPERT run.  Two major functions are add input data
  6895. --             to and/or delete from an existing input file.
  6896. --             This file is originally created by routine "newfile".
  6897. ------------------------------------------------------------------------
  6898. procedure MODIFY is
  6899.  
  6900.     subtype INT_NUM is INTEGER range 0 .. 1000000;
  6901.  
  6902.     package I_NUMBER is new TEXT_IO.INTEGER_IO (INT_NUM);
  6903.  
  6904.     subtype FLOAT_NUM is FLOAT range 0.0 .. 100_000.0;
  6905.  
  6906.     package F_NUMBER is new TEXT_IO.FLOAT_IO (FLOAT_NUM);
  6907.  
  6908.     type YESNO_TYPE is (Y, YE, YES, N, NO, NONE);
  6909.  
  6910.     function RETURN_YESNO is new SCREEN_IO.RETURNED_ENUMERATION (YESNO_TYPE);
  6911.  
  6912.     YES_NO_ANSWER                               : YESNO_TYPE;
  6913.  
  6914.     MAXIMUM_NUMBER_OF_ACTIVITIES                : constant INTEGER := 4000; 
  6915.     MAXIMUM_NUMBER_OF_NODES                     : constant INTEGER := 3400; 
  6916.     MAXIMUM_NUMBER_OF_IN_OUT_NODES              : constant INTEGER := 25; 
  6917.     MAXIMUM_NUMBER_OF_ACTIVITY_IN_CRITICAL_PATH : constant INTEGER := 2000; 
  6918.     MAXIMUM_NUMBER_OF_NAME_NODES                : constant INTEGER := 9999;
  6919.  
  6920.     MAX_ACT_ERROR      : exception;
  6921.     BAD_DATA           : exception;
  6922.     END_PER_USER_ERROR : exception;
  6923.     END_MODIFY         : exception;
  6924.  
  6925.  
  6926.     type A_OR_D is (A, ADD, D, DELETE, NONE);
  6927.  
  6928.     REQUEST_FOR_DELETION : A_OR_D := D;
  6929.     REQUEST_FOR_ADDITION : A_OR_D := A;
  6930.     ADD_DELETE_ANSWER    : STRING (1 .. 1) := " ";                    
  6931.  
  6932.     MAX_LINE             : constant INTEGER := 80;
  6933.     MAX_ACT_CODE         : constant INTEGER := 8;
  6934.     MAX_ACT_NAME         : constant INTEGER := 32;
  6935.  
  6936.     type GO_OR_STOP is (S, STOP, CONTINUE, C);
  6937.  
  6938.     CONTINUE_OR_STOP  : STRING (1 .. 1) := " ";
  6939.     CONTINUE_CASE     : GO_OR_STOP := C;
  6940.  
  6941.     INPUT_FILE        : STRING (1 .. MAX_LINE);
  6942.     MAX_FILE_NAME     : constant INTEGER := 32;
  6943.     END_FILE_NAME     : NATURAL;
  6944.     USER_INPUT_FILE   : TEXT_IO.FILE_TYPE;
  6945.  
  6946.     ERROR_INDENTATION : TEXT_IO.COUNT := 15;
  6947.  
  6948.     VALID_DATA        : INTEGER;
  6949.  
  6950.     subtype LENGTH_RANGE is INTEGER range 1 .. 132;
  6951.  
  6952.     type HEADER_LINE_TYPE (LENGTH : LENGTH_RANGE := 1) is
  6953.     record
  6954.         VALUE : STRING (1 .. LENGTH);
  6955.     end record;
  6956.     type HEADER_BUFFER_ARRAY is array (1 .. 5) of HEADER_LINE_TYPE;
  6957.  
  6958.     FILE_HEADER : HEADER_BUFFER_ARRAY;
  6959.  
  6960.     type INPUT_LINE_RECORD_TYPE is
  6961.  
  6962.     record
  6963.         WBS_CODE      : STRING (1 .. 8);
  6964.         ACTIVITY_NAME : STRING (1 .. 32);
  6965.         TAIL_NODE     : INTEGER;
  6966.         HEAD_NODE     : INTEGER;
  6967.         OPTIMISTICS   : FLOAT;
  6968.         MOST_LIKELY   : FLOAT;
  6969.         PESSIMISTICS  : FLOAT;
  6970.         STAFFING      : FLOAT;
  6971.         RATE          : FLOAT;
  6972.     end record;
  6973.  
  6974.     CURRENT_INPUT_LINE : INPUT_LINE_RECORD_TYPE;
  6975.     type BODY_BUFFER_ARRAY_TYPE        is array (INTEGER range <>)
  6976.                          of INPUT_LINE_RECORD_TYPE;
  6977.     type BODY_BUFFER_ARRAY_ACCESS_TYPE is access BODY_BUFFER_ARRAY_TYPE;
  6978.  
  6979.     BODY_BUFFER_ARRAY         : BODY_BUFFER_ARRAY_ACCESS_TYPE :=
  6980.                 new BODY_BUFFER_ARRAY_TYPE
  6981.                       (1 .. MAXIMUM_NUMBER_OF_ACTIVITIES);
  6982.     BODY_BUFFER_ARRAY_COUNTER : INTEGER;
  6983.  
  6984.  
  6985.  
  6986.  
  6987.  
  6988.  
  6989.     -----------------------------------------------------------
  6990.     -- read in 9 fields from a given input line and insert
  6991.     -- each field into appropriate place in the working buffer
  6992.     -----------------------------------------------------------
  6993.     procedure READ_ONE_ACTIVITY_LINE (FROM_FILE : TEXT_IO.FILE_TYPE;
  6994.                       A_RECORD  : out INPUT_LINE_RECORD_TYPE) is
  6995.  
  6996.  
  6997.     begin
  6998.  
  6999.     TEXT_IO.GET (FROM_FILE, A_RECORD.WBS_CODE);
  7000.     TEXT_IO.SET_COL (FROM_FILE, TO => 10);
  7001.     TEXT_IO.GET (FROM_FILE, A_RECORD.ACTIVITY_NAME);
  7002.     I_NUMBER.GET (FROM_FILE, A_RECORD.TAIL_NODE);
  7003.     I_NUMBER.GET (FROM_FILE, A_RECORD.HEAD_NODE);
  7004.     F_NUMBER.GET (FROM_FILE, A_RECORD.OPTIMISTICS);
  7005.     F_NUMBER.GET (FROM_FILE, A_RECORD.MOST_LIKELY);
  7006.     F_NUMBER.GET (FROM_FILE, A_RECORD.PESSIMISTICS);
  7007.     F_NUMBER.GET (FROM_FILE, A_RECORD.STAFFING);
  7008.     F_NUMBER.GET (FROM_FILE, A_RECORD.RATE);
  7009.  
  7010.  
  7011.     exception
  7012.     when TEXT_IO.DATA_ERROR => 
  7013.         raise BAD_DATA;
  7014.  
  7015.     end READ_ONE_ACTIVITY_LINE;
  7016.  
  7017.  
  7018.  
  7019.     --------------------------------------------------------
  7020.     -- write the value of elements in each record 
  7021.     --------------------------------------------------------
  7022.     procedure WRITE_ONE_LINE
  7023.          (TO_FILE  : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  7024.           A_RECORD : INPUT_LINE_RECORD_TYPE) is
  7025.  
  7026.     begin
  7027.     -----------------### text_io limitation ### ----------------
  7028.  
  7029.     -- when text_io.float_io.put encounters the float value 0.0
  7030.     -- it puts out the sequence 0.^A .  In order to make up
  7031.     -- for this limitation, the program is coded so that the string
  7032.     -- "0.0" will be printed in lieu when such condition is met.
  7033.  
  7034.     --------------- ### end text_io limitation ### --------------
  7035.  
  7036.  
  7037.     TEXT_IO.PUT (TO_FILE, A_RECORD.WBS_CODE);
  7038.  
  7039.     TEXT_IO.SET_COL (TO_FILE, TO => 10);
  7040.  
  7041.     TEXT_IO.PUT (TO_FILE, A_RECORD.ACTIVITY_NAME);
  7042.  
  7043.     TEXT_IO.SET_COL (TO_FILE, TO => 43);
  7044.     I_NUMBER.PUT (TO_FILE, A_RECORD.TAIL_NODE, WIDTH => 4);
  7045.  
  7046.     TEXT_IO.SET_COL (TO_FILE, TO => 48);
  7047.     I_NUMBER.PUT (TO_FILE, A_RECORD.HEAD_NODE, WIDTH => 4);
  7048.  
  7049.     TEXT_IO.SET_COL (TO_FILE, TO => 54);
  7050.  
  7051.     if A_RECORD.OPTIMISTICS = 0.0 then
  7052.         TEXT_IO.PUT (TO_FILE, "  0.0");
  7053.     else
  7054.         F_NUMBER.PUT
  7055.            (TO_FILE, A_RECORD.OPTIMISTICS, EXP => 0, FORE => 3, AFT => 1);
  7056.     end if;
  7057.  
  7058.     TEXT_IO.SET_COL (TO_FILE, TO => 60);
  7059.  
  7060.     if A_RECORD.MOST_LIKELY = 0.0 then
  7061.         TEXT_IO.PUT (TO_FILE, "  0.0");
  7062.     else
  7063.         F_NUMBER.PUT
  7064.            (TO_FILE, A_RECORD.MOST_LIKELY, EXP => 0, FORE => 3, AFT => 1);
  7065.     end if;
  7066.  
  7067.     TEXT_IO.SET_COL (TO_FILE, TO => 66);
  7068.  
  7069.     if A_RECORD.PESSIMISTICS = 0.0 then
  7070.         TEXT_IO.PUT (TO_FILE, "  0.0");
  7071.     else
  7072.         F_NUMBER.PUT
  7073.            (TO_FILE, A_RECORD.PESSIMISTICS, EXP => 0, FORE => 3, AFT => 1);
  7074.     end if;
  7075.  
  7076.     TEXT_IO.SET_COL (TO_FILE, TO => 72);
  7077.  
  7078.     if A_RECORD.STAFFING = 0.0 then
  7079.         TEXT_IO.PUT (TO_FILE, " 0.0");
  7080.     else
  7081.         F_NUMBER.PUT
  7082.            (TO_FILE, A_RECORD.STAFFING, EXP => 0, FORE => 2, AFT => 1);
  7083.     end if;
  7084.  
  7085.     TEXT_IO.SET_COL (TO_FILE, TO => 77);
  7086.  
  7087.     if A_RECORD.RATE = 0.0 then
  7088.         TEXT_IO.PUT (TO_FILE, "      0.0");
  7089.     else
  7090.         F_NUMBER.PUT
  7091.            (TO_FILE, A_RECORD.RATE, EXP => 0, FORE => 7, AFT => 1);
  7092.     end if;
  7093.  
  7094.     TEXT_IO.NEW_LINE (TO_FILE);
  7095.  
  7096.     end WRITE_ONE_LINE;
  7097.  
  7098.  
  7099.  
  7100.     ----------------------------------------
  7101.     -- putout a welcome message
  7102.     ----------------------------------------
  7103.     procedure WELCOME_MESSAGE is
  7104.  
  7105.     INDENTATION    : TEXT_IO.COUNT := 7;
  7106.     INDENT_FOR_MAX : TEXT_IO.COUNT := 53;
  7107.  
  7108.     begin
  7109.     TEXT_IO.NEW_PAGE;
  7110.     TEXT_IO.NEW_LINE (5);
  7111.     TEXT_IO.SET_COL (TO => INDENTATION);
  7112.     TEXT_IO.PUT ("      Welcome to MODIFY Version 1.0");
  7113.  
  7114.     TEXT_IO.NEW_LINE (3);
  7115.     TEXT_IO.SET_COL (TO => INDENTATION);
  7116.     TEXT_IO.PUT ("Network constraints for this version are:");
  7117.  
  7118.     TEXT_IO.NEW_LINE (2);
  7119.     TEXT_IO.SET_COL (TO => INDENTATION);
  7120.     TEXT_IO.PUT ("    Max number of activities (arcs)        =");
  7121.     TEXT_IO.SET_COL (TO => INDENT_FOR_MAX);
  7122.     I_NUMBER.PUT (MAXIMUM_NUMBER_OF_ACTIVITIES);
  7123.  
  7124.     TEXT_IO.NEW_LINE;
  7125.     TEXT_IO.SET_COL (TO => INDENTATION);
  7126.     TEXT_IO.PUT ("    Max number of nodes                    =");
  7127.     TEXT_IO.SET_COL (TO => INDENT_FOR_MAX);
  7128.     I_NUMBER.PUT (MAXIMUM_NUMBER_OF_NODES);
  7129.  
  7130.     TEXT_IO.NEW_LINE;
  7131.     TEXT_IO.SET_COL (TO => INDENTATION);
  7132.     TEXT_IO.PUT ("    Max number of inbound arcs at any node =");
  7133.     TEXT_IO.SET_COL (TO => INDENT_FOR_MAX);
  7134.     I_NUMBER.PUT (MAXIMUM_NUMBER_OF_IN_OUT_NODES);
  7135.  
  7136.     TEXT_IO.NEW_LINE;
  7137.     TEXT_IO.SET_COL (TO => INDENTATION);
  7138.     TEXT_IO.PUT ("    Max number of arcs in critical path    =");
  7139.     TEXT_IO.SET_COL (TO => INDENT_FOR_MAX);
  7140.     I_NUMBER.PUT (MAXIMUM_NUMBER_OF_ACTIVITY_IN_CRITICAL_PATH);
  7141.  
  7142.     TEXT_IO.NEW_LINE (5);
  7143.     TEXT_IO.SET_COL (TO => INDENTATION);
  7144.         PRESS_RETURN_TO_CONTINUE;
  7145.  
  7146.     TEXT_IO.NEW_PAGE;
  7147.     end WELCOME_MESSAGE;
  7148.  
  7149.  
  7150.  
  7151.     -------------------------------------------------------------------
  7152.     -- receive an integer within the range start_integer .. end_integer
  7153.     -------------------------------------------------------------------
  7154.     function RETURN_INTEGER (INPUT_PROMPT  : STRING;
  7155.                  START_INTEGER : INTEGER := 0;
  7156.                  END_INTEGER   : INTEGER := 0) return INTEGER is
  7157.     begin
  7158.     return SCREEN_IO.RETURNED_INTEGER
  7159.           (PROMPT     => ASCII.LF & ASCII.CR & INPUT_PROMPT &
  7160.                  ASCII.LF & ASCII.CR,
  7161.            FROM_VALUE => START_INTEGER,
  7162.            TO_VALUE   => END_INTEGER,
  7163.            CONFIRM    => FALSE,
  7164.            ERROR_TEXT =>
  7165.              ASCII.LF & ASCII.CR &
  7166.              "INPUT ERROR:   Program expects an integer number " &
  7167.              "within " & INTEGER'IMAGE (START_INTEGER) & " through " &
  7168.              INTEGER'IMAGE (END_INTEGER) & "." & ASCII.LF & ASCII.CR &
  7169.              "               Please try again." & ASCII.LF & ASCII.CR);
  7170.     end RETURN_INTEGER;
  7171.  
  7172.  
  7173.  
  7174.     --------------------------------------------------
  7175.     -- prompt the user for a choice of either to ADD
  7176.     -- or DELETE records from a given input file
  7177.     --------------------------------------------------
  7178.     procedure OBTAIN_ADD_OR_DELETE is
  7179.  
  7180.     function RETURNED_A_D is new SCREEN_IO.RETURNED_ENUMERATION (A_OR_D);
  7181.  
  7182.     THE_ANSWER : A_OR_D := NONE;
  7183.  
  7184.     begin
  7185.     while THE_ANSWER not in A .. DELETE loop
  7186.         THE_ANSWER := RETURNED_A_D
  7187.                  (PROMPT     =>
  7188.                 "Do you want to add or delete?  " &
  7189.                 "ENTER:  a or d -->    ",
  7190.                   DEFAULT    => NONE,
  7191.                   FROM_VALUE => A,
  7192.                       CONFIRM    => FALSE,
  7193.                   TO_VALUE   => DELETE,
  7194.                   ERROR_TEXT =>
  7195.                 ASCII.LF & ASCII.CR &
  7196.                 "INPUT ERROR:  Answer must be either " &
  7197.                 "[a] for add or [d]  for delete" & ASCII.LF &
  7198.                 ASCII.CR);
  7199.     end loop;
  7200.  
  7201.     declare
  7202.         TEMP_UNITS : constant STRING := A_OR_D'IMAGE (THE_ANSWER);
  7203.     begin
  7204.         ADD_DELETE_ANSWER (1) := TEMP_UNITS (TEMP_UNITS'FIRST);
  7205.     end;
  7206.  
  7207.     end OBTAIN_ADD_OR_DELETE;
  7208.  
  7209.  
  7210.  
  7211.     ---------------------------------------------------------------
  7212.     -- prompt the user for continue or stop program decision
  7213.     ---------------------------------------------------------------
  7214.     procedure SELECTION_CONTINUE_OR_STOP is
  7215.  
  7216.     function RETURNED_GS is new SCREEN_IO.RETURNED_ENUMERATION (GO_OR_STOP);
  7217.  
  7218.     THE_ANSWER : GO_OR_STOP;
  7219.  
  7220.     begin
  7221.     THE_ANSWER := RETURNED_GS
  7222.              (PROMPT     =>
  7223.                 ASCII.LF & ASCII.CR &
  7224.                 "       <-- ENTER C to continue program " &
  7225.                 "or S to stop it" & ASCII.LF & ASCII.CR,
  7226.               ERROR_TEXT =>
  7227.                 ASCII.LF & ASCII.CR & "INPUT ERROR:  " &
  7228.                 "Answer must be either C for continue " &
  7229.                 "or S for stop  ");
  7230.  
  7231.     declare
  7232.         TEMP_UNITS : constant STRING := GO_OR_STOP'IMAGE (THE_ANSWER);
  7233.     begin
  7234.         CONTINUE_OR_STOP (1) := TEMP_UNITS (TEMP_UNITS'FIRST);
  7235.     end;
  7236.  
  7237.     end SELECTION_CONTINUE_OR_STOP;
  7238.  
  7239.  
  7240.  
  7241.     --------------------------------
  7242.     -- obtain a string from user
  7243.     --------------------------------
  7244.     procedure OBTAIN_NAME (WITH_PROMPT     : STRING := " ";
  7245.                THE_NAME        : out STRING;
  7246.                END_OF_THE_NAME : in out NATURAL;
  7247.                MAX_OF_THE_NAME : INTEGER := 8) is
  7248.  
  7249.     begin
  7250.     loop
  7251.         declare
  7252.         TEMP_NAME: constant STRING :=
  7253.               SCREEN_IO.RETURNED_STRING
  7254.                   (PROMPT  => ASCII.LF & ASCII.CR &
  7255.                             WITH_PROMPT &
  7256.                    ASCII.LF & ASCII.CR, 
  7257.                    CONFIRM => FALSE);
  7258.         begin
  7259.             END_OF_THE_NAME := TEMP_NAME'LENGTH;
  7260.             THE_NAME(1..END_OF_THE_NAME) := TEMP_NAME;
  7261.             exit when END_OF_THE_NAME in 1 .. MAX_OF_THE_NAME;
  7262.             TEXT_IO.NEW_LINE;
  7263.             TEXT_IO.PUT_LINE ("INPUT ERROR:");
  7264.  
  7265.             TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7266.             TEXT_IO.PUT_LINE ("File name must be within 1 through " &
  7267.                   INTEGER'IMAGE (MAX_OF_THE_NAME) & " characters.");
  7268.  
  7269.             TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7270.             TEXT_IO.PUT_LINE ("Please try again.");
  7271.             TEXT_IO.NEW_LINE;
  7272.         end;
  7273.     end loop;
  7274.  
  7275.     end OBTAIN_NAME;
  7276.  
  7277.  
  7278.  
  7279.     -----------------------------------
  7280.     -- obtain input file from user 
  7281.     -----------------------------------
  7282.     procedure OBTAIN_INPUT_FILE_NAME is
  7283.  
  7284.     END_GET_FILE_NAME : exception;
  7285.  
  7286.     --------------------------------------------
  7287.     -- query user for a valid input file name
  7288.     --------------------------------------------
  7289.     procedure GET_FILE_NAME is
  7290.  
  7291.     begin
  7292.         TEXT_IO.NEW_LINE;
  7293.         OBTAIN_NAME
  7294.            (WITH_PROMPT     => "              <-- ENTER name of input file",
  7295.         THE_NAME        => INPUT_FILE,
  7296.         END_OF_THE_NAME => END_FILE_NAME,
  7297.         MAX_OF_THE_NAME => MAX_FILE_NAME);
  7298.         TEXT_IO.NEW_LINE;
  7299.  
  7300.         if FILE_OPS.FILE_EXISTS
  7301.           (WITH_NAME => INPUT_FILE (1 .. END_FILE_NAME)) then
  7302.         TEXT_IO.NEW_LINE (2);
  7303.  
  7304.         if (RETURN_YESNO
  7305.                (PROMPT     =>
  7306.               "WARNING !!!  [" & INPUT_FILE (1 .. END_FILE_NAME) &
  7307.               "]    will be modified.  " & ASCII.LF & ASCII.CR &
  7308.               "Do you wish to RE-ENTER the name?  (y/n) -->  ",
  7309.             DEFAULT    => NONE,
  7310.             FROM_VALUE => Y,
  7311.             TO_VALUE   => NO,
  7312.             ERROR_TEXT => ASCII.LF & ASCII.CR & "INPUT ERROR:  " &
  7313.                       "Answer must be either Y or N." &
  7314.                       ASCII.LF & ASCII.CR) in Y .. YES) then
  7315.             GET_FILE_NAME;
  7316.         end if;
  7317.         else
  7318.         TEXT_IO.NEW_LINE;
  7319.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  7320.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7321.         TEXT_IO.PUT_LINE
  7322.            ("File " & INPUT_FILE (1 .. END_FILE_NAME) & " not found.");
  7323.         TEXT_IO.NEW_LINE (2);
  7324.         YES_NO_ANSWER :=
  7325.           RETURN_YESNO
  7326.              (PROMPT     => ASCII.LF & ASCII.CR &
  7327.                     "Do you wish to try again " &
  7328.                     "on another file name (y/n) -->  ",
  7329.               DEFAULT    => NONE,
  7330.               FROM_VALUE => Y,
  7331.               TO_VALUE   => NO,
  7332.               ERROR_TEXT => ASCII.LF & ASCII.CR & "INPUT ERROR:  " &
  7333.                     "Answer must be either Y or N." &
  7334.                     ASCII.LF & ASCII.CR);
  7335.  
  7336.         if YES_NO_ANSWER in Y .. YES then
  7337.             GET_FILE_NAME;
  7338.         else
  7339.             TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7340.             TEXT_IO.PUT_LINE ("Program terminate per user request");
  7341.             TEXT_IO.NEW_LINE;
  7342.             raise END_GET_FILE_NAME;
  7343.         end if;
  7344.         end if;
  7345.  
  7346.     end GET_FILE_NAME;
  7347.  
  7348.  
  7349.     begin
  7350.  
  7351.     GET_FILE_NAME;
  7352.  
  7353.     FILE_OPS.OPEN
  7354.        (THE_FILE         => USER_INPUT_FILE,
  7355.         WITH_NAME        => INPUT_FILE (1 .. END_FILE_NAME),
  7356.         TO_MODE          => TEXT_IO.IN_FILE,
  7357.         CREATION_ENABLED => TRUE);
  7358.  
  7359.  
  7360.     ----------------------------------
  7361.     -- file error handlers...
  7362.     ----------------------------------
  7363.     exception
  7364.     when END_GET_FILE_NAME => 
  7365.         raise END_PER_USER_ERROR;
  7366.  
  7367.     when FILE_OPS.SYSTEM_CANNOT_OPEN_FILE => 
  7368.         TEXT_IO.NEW_LINE;
  7369.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  7370.  
  7371.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7372.         TEXT_IO.PUT_LINE (INPUT_FILE (1 .. END_FILE_NAME) &
  7373.                   " cannot be accessed.");
  7374.         TEXT_IO.NEW_LINE;
  7375.         raise END_PER_USER_ERROR;
  7376.  
  7377.     when FILE_OPS.FILE_ALREADY_OPEN => 
  7378.         TEXT_IO.NEW_LINE;
  7379.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  7380.  
  7381.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7382.         TEXT_IO.PUT_LINE (INPUT_FILE (1 .. END_FILE_NAME) &
  7383.                   " is currently in use.");
  7384.  
  7385.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7386.         TEXT_IO.PUT_LINE ("Program cannot access it");
  7387.         TEXT_IO.NEW_LINE;
  7388.         raise END_PER_USER_ERROR;
  7389.  
  7390.     when FILE_OPS.ILLEGAL_FILE_NAME => 
  7391.         TEXT_IO.NEW_LINE;
  7392.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  7393.  
  7394.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7395.         TEXT_IO.PUT_LINE ("[" & INPUT_FILE (1 .. END_FILE_NAME) &
  7396.                   "] is an illegal name");
  7397.         TEXT_IO.NEW_LINE (2);
  7398.         YES_NO_ANSWER := RETURN_YESNO
  7399.                 (PROMPT     =>
  7400.                    "Do you wish to try again" &
  7401.                    " on another file name (y/n) -->  " &
  7402.                    ASCII.LF & ASCII.CR,
  7403.                  DEFAULT    => NONE,
  7404.                  FROM_VALUE => Y,
  7405.                  TO_VALUE   => NO,
  7406.                  ERROR_TEXT =>
  7407.                    ASCII.LF & ASCII.CR & "INPUT ERROR:  " &
  7408.                    "Answer must be either Y or N.");
  7409.  
  7410.         if YES_NO_ANSWER in Y .. YES then
  7411.         OBTAIN_INPUT_FILE_NAME;
  7412.         else
  7413.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7414.         TEXT_IO.PUT_LINE ("Program terminate per user request");
  7415.         TEXT_IO.NEW_LINE;
  7416.         raise END_PER_USER_ERROR;
  7417.         end if;
  7418.  
  7419.     end OBTAIN_INPUT_FILE_NAME;
  7420.  
  7421.  
  7422.  
  7423.  
  7424.     ----------------------------------------------------------
  7425.     -- create buffers to store data read from user input file,
  7426.     -- the data are used during modification process
  7427.     ----------------------------------------------------------
  7428.     procedure CREATE_INPUT_BUFFER_ARRAY is
  7429.  
  7430.     HEADER_LINES    : STRING (LENGTH_RANGE'FIRST .. LENGTH_RANGE'LAST);
  7431.     HEADER_LINE_END : NATURAL;
  7432.  
  7433.  
  7434.  
  7435.     begin
  7436.     ------------------------------------------------------------
  7437.     -- user input file contains two type of lines -
  7438.     -- The first 5 lines of input file have header information
  7439.     -- which are read and stored in buffer named "header_buffer_array".
  7440.     -- The subsequent lines of input file have activities information
  7441.     -- which are read and stored in buffer named "body_buffer_array".
  7442.     ------------------------------------------------------------
  7443.  
  7444.     -------------------------------------
  7445.     -- read in header lines
  7446.     -------------------------------------
  7447.     for I in 1 .. 5 loop
  7448.         TEXT_IO.GET_LINE (USER_INPUT_FILE, HEADER_LINES, HEADER_LINE_END);
  7449.         FILE_HEADER (I) :=
  7450.           (HEADER_LINE_END, HEADER_LINES (1 .. HEADER_LINE_END));
  7451.     end loop;
  7452.  
  7453.  
  7454.     -------------------------------------
  7455.     -- read in the rest of the lines
  7456.     -------------------------------------
  7457.     BODY_BUFFER_ARRAY_COUNTER := 0;
  7458.  
  7459.     loop
  7460.         BODY_BUFFER_ARRAY_COUNTER := BODY_BUFFER_ARRAY_COUNTER + 1;
  7461.  
  7462.         if BODY_BUFFER_ARRAY_COUNTER > MAXIMUM_NUMBER_OF_ACTIVITIES then
  7463.         raise MAX_ACT_ERROR;
  7464.         end if;
  7465.  
  7466.         READ_ONE_ACTIVITY_LINE
  7467.            (FROM_FILE => USER_INPUT_FILE, A_RECORD => CURRENT_INPUT_LINE);
  7468.  
  7469.         BODY_BUFFER_ARRAY.all (BODY_BUFFER_ARRAY_COUNTER) :=
  7470.           CURRENT_INPUT_LINE;
  7471.     end loop;
  7472.  
  7473.  
  7474.     ------------------------
  7475.     -- errors handlers
  7476.     ------------------------
  7477.     exception
  7478.     when MAX_ACT_ERROR => 
  7479.         TEXT_IO.PUT_LINE ("NETWORK CONSTRAINT ERROR:");
  7480.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7481.         TEXT_IO.PUT ("The number of activities contained in " &
  7482.              INPUT_FILE (1 .. END_FILE_NAME));
  7483.         TEXT_IO.PUT_LINE (" exceeds the maximum limit of ");
  7484.         I_NUMBER.PUT (MAXIMUM_NUMBER_OF_ACTIVITIES);
  7485.         TEXT_IO.PUT_LINE (".");
  7486.         raise END_MODIFY;
  7487.  
  7488.     when BAD_DATA => 
  7489.         TEXT_IO.NEW_LINE;
  7490.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  7491.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7492.         TEXT_IO.PUT_LINE ("Inconsistent data encountered at the line ");
  7493.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7494.         TEXT_IO.PUT ("containing activity named:");
  7495.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7496.         TEXT_IO.PUT_LINE ("   [" & CURRENT_INPUT_LINE.ACTIVITY_NAME & "].");
  7497.         raise END_MODIFY;
  7498.  
  7499.     when TEXT_IO.END_ERROR => 
  7500.         BODY_BUFFER_ARRAY_COUNTER := BODY_BUFFER_ARRAY_COUNTER - 1;
  7501.         TEXT_IO.CLOSE (USER_INPUT_FILE);
  7502.  
  7503.     end CREATE_INPUT_BUFFER_ARRAY;
  7504.  
  7505.  
  7506.  
  7507.  
  7508.     -------------------------------------------
  7509.     -- remove unwanted records from the record
  7510.     -- array as per user request.
  7511.     -------------------------------------------
  7512.     procedure PROCESS_DELETION is
  7513.  
  7514.     CURRENT_BEGIN_RANGE      : INTEGER := 1;
  7515.     CURRENT_END_RANGE        : INTEGER := 0;
  7516.  
  7517.     SEGMENT_OF_DELETED_LINES : constant INTEGER := 12;
  7518.  
  7519.     DELETED_LINE             : INTEGER;
  7520.  
  7521.  
  7522.     DELETE_RECORD : INPUT_LINE_RECORD_TYPE :=
  7523.             (WBS_CODE      => "delete--",
  7524.              ACTIVITY_NAME => "this record will be deleted     ",
  7525.              TAIL_NODE     => -1,
  7526.              HEAD_NODE     => -1,
  7527.              OPTIMISTICS   => -1.0,
  7528.              MOST_LIKELY   => -1.0,
  7529.              PESSIMISTICS  => -1.0,
  7530.              STAFFING      => 0.0,
  7531.              RATE          => 0.0);
  7532.  
  7533.  
  7534.  
  7535.     ------------------------------------------------
  7536.     -- prompt user for delete or not delete decision
  7537.     -- if delete, how many?
  7538.     ------------------------------------------------
  7539.     function HOW_MANY_TO_BE_DELETED return INTEGER is
  7540.  
  7541.     begin
  7542.         if (RETURN_YESNO
  7543.            (PROMPT     => ASCII.LF & ASCII.CR &
  7544.                   "Do you wish to delete any " &
  7545.                   "of above activities (y/n) -->  ",
  7546.             DEFAULT    => NONE,
  7547.             FROM_VALUE => Y,
  7548.             TO_VALUE   => NO,
  7549.             ERROR_TEXT => ASCII.LF & ASCII.CR & "INPUT ERROR:  " &
  7550.                   "Answer must be either Y or N.") in
  7551.         Y .. YES) then
  7552.  
  7553.         return (RETURN_INTEGER
  7554.                (INPUT_PROMPT =>
  7555.                   ASCII.LF & ASCII.CR &
  7556.                   "      <-- How many activities will be deleted?",
  7557.                 END_INTEGER  => SEGMENT_OF_DELETED_LINES));
  7558.         else
  7559.         return (0);
  7560.         end if;
  7561.  
  7562.     end HOW_MANY_TO_BE_DELETED;
  7563.  
  7564.  
  7565.     ----------------------------------------------
  7566.     -- main of PROCESS_DELETION
  7567.     ----------------------------------------------
  7568.     begin
  7569.  
  7570.     loop
  7571.         -----------------------------------
  7572.         -- obtain 12 lines of text segment
  7573.         -----------------------------------
  7574.         if (CURRENT_BEGIN_RANGE + SEGMENT_OF_DELETED_LINES - 1) >=
  7575.            BODY_BUFFER_ARRAY_COUNTER then
  7576.         CURRENT_END_RANGE := BODY_BUFFER_ARRAY_COUNTER;
  7577.         else
  7578.         CURRENT_END_RANGE :=
  7579.           CURRENT_BEGIN_RANGE + SEGMENT_OF_DELETED_LINES - 1;
  7580.         end if;
  7581.         --------------------------------------------------
  7582.         -- output the segment to screen, each line begins
  7583.         -- with a numerical value of 1 .. 12 for all
  7584.         -- regular 12 line segment.
  7585.         --------------------------------------------------
  7586.         declare
  7587.         CHOICE_NUMBER           : INTEGER := 1;
  7588.         NUMBER_OF_DELETED_LINES : INTEGER := 0;
  7589.         begin
  7590.  
  7591.         -----------------------------------
  7592.         -- output section of text to screen
  7593.         -----------------------------------
  7594.         TEXT_IO.NEW_PAGE;
  7595.         TEXT_IO.NEW_LINE (6);
  7596.         TEXT_IO.PUT ("  Option# ");
  7597.         TEXT_IO.SET_COL (TO => 40);
  7598.         TEXT_IO.PUT_LINE ("Activity Name");
  7599.         TEXT_IO.NEW_LINE;
  7600.  
  7601.         for LINE_INDEX in CURRENT_BEGIN_RANGE .. CURRENT_END_RANGE loop
  7602.             CURRENT_INPUT_LINE := BODY_BUFFER_ARRAY.all (LINE_INDEX);
  7603.             TEXT_IO.SET_COL (TO => 3);
  7604.             I_NUMBER.PUT (CHOICE_NUMBER, WIDTH => 4);
  7605.             TEXT_IO.SET_COL (TO => 20);
  7606.             TEXT_IO.PUT_LINE (CURRENT_INPUT_LINE.ACTIVITY_NAME);
  7607.             CHOICE_NUMBER := CHOICE_NUMBER + 1;
  7608.         end loop;
  7609.  
  7610.         NUMBER_OF_DELETED_LINES := HOW_MANY_TO_BE_DELETED;
  7611.  
  7612.         ---------------------------------------------------------
  7613.         -- return to calling program when there is no deleted input
  7614.         ---------------------------------------------------------
  7615.         if NUMBER_OF_DELETED_LINES > 0 then
  7616.  
  7617.                 ---------------------------------------------------
  7618.                 -- process deleted request by replacing
  7619.                 -- unwanted record with aggregate of delete_record.
  7620.                 ---------------------------------------------------
  7621.             declare
  7622.             DELETE_LINE : INTEGER;
  7623.  
  7624.             begin
  7625.             for DELETE_INDEX in 1 .. NUMBER_OF_DELETED_LINES loop
  7626.                 DELETE_LINE :=
  7627.                   RETURN_INTEGER
  7628.                  (INPUT_PROMPT  =>
  7629.                     "     <-- Enter option# for " &
  7630.                     "one of the " &
  7631.                     INTEGER'IMAGE (NUMBER_OF_DELETED_LINES) &
  7632.                     "'s  unwanted activities",
  7633.                   START_INTEGER => 1,
  7634.                   END_INTEGER   => SEGMENT_OF_DELETED_LINES);
  7635.                 BODY_BUFFER_ARRAY.all
  7636.                    (CURRENT_BEGIN_RANGE + DELETE_LINE - 1) :=
  7637.                   DELETE_RECORD;
  7638.             end loop;
  7639.             end;
  7640.         end if;
  7641.         end;
  7642.  
  7643.         CURRENT_BEGIN_RANGE := CURRENT_END_RANGE + 1;
  7644.         exit when CURRENT_END_RANGE >= BODY_BUFFER_ARRAY_COUNTER;
  7645.     end loop;
  7646.  
  7647.     ----------------------------------------------
  7648.     -- remove delete record from body_buffer_array
  7649.     ----------------------------------------------
  7650.     declare
  7651.         NEXT_POINTER : INTEGER := 0;
  7652.     begin
  7653.         for CURRENT_POINTER in 1 .. BODY_BUFFER_ARRAY_COUNTER loop
  7654.         if BODY_BUFFER_ARRAY.all (CURRENT_POINTER) /= DELETE_RECORD then
  7655.             NEXT_POINTER := NEXT_POINTER + 1;
  7656.  
  7657.             if NEXT_POINTER /= CURRENT_POINTER then
  7658.             BODY_BUFFER_ARRAY (NEXT_POINTER) :=
  7659.               BODY_BUFFER_ARRAY (CURRENT_POINTER);
  7660.             end if;
  7661.         end if;
  7662.         end loop;
  7663.  
  7664.         BODY_BUFFER_ARRAY_COUNTER := NEXT_POINTER;
  7665.     end;
  7666.  
  7667.     TEXT_IO.NEW_LINE;
  7668.  
  7669.  
  7670.     end PROCESS_DELETION;
  7671.  
  7672.  
  7673.  
  7674.     -------------------------------------------------------------
  7675.     -- add records to the record buffer as per user request.
  7676.     -------------------------------------------------------------
  7677.     procedure PROCESS_ADDITION is
  7678.  
  7679.     NUMBER_ADDED                  : INTEGER := 0;
  7680.     NUMBER_OF_ACTIVITIES_INPUTTED : INTEGER := BODY_BUFFER_ARRAY_COUNTER;
  7681.  
  7682.     WBS_CODE                      : STRING (1 .. MAX_LINE);  
  7683.     CODE_LAST                     : NATURAL;
  7684.     ACTIVITY_NAME                 : STRING (1 .. MAX_LINE);  
  7685.     NAME_LAST                     : NATURAL;
  7686.  
  7687.     HEAD_NODE, TAIL_NODE          : INTEGER := 0;  
  7688.  
  7689.     OPTIMISTICS                   : FLOAT;
  7690.     MOST_LIKELY                   : FLOAT;
  7691.     PESSIMISTICS                  : FLOAT;
  7692.     STAFFING                      : FLOAT;
  7693.     RATE                          : FLOAT;  
  7694.  
  7695.  
  7696.     ------------------------------------------------
  7697.     -- prompt user for how many to be added
  7698.     ------------------------------------------------
  7699.     function HOW_MANY_TO_BE_ADDED return INTEGER is
  7700.  
  7701.     begin
  7702.  
  7703.         TEXT_IO.NEW_PAGE;
  7704.         TEXT_IO.NEW_LINE (3);
  7705.         return (RETURN_INTEGER
  7706.                (INPUT_PROMPT =>
  7707.               ASCII.LF & ASCII.CR &
  7708.               "      <-- How many activities will be added?" &
  7709.               ASCII.LF & ASCII.CR,
  7710.             END_INTEGER  => 999));
  7711.         TEXT_IO.NEW_LINE;
  7712.     end HOW_MANY_TO_BE_ADDED;
  7713.  
  7714.  
  7715.     --------------------------------------------------
  7716.     -- prompt user for pertinent information to create
  7717.     -- new record adding to existing input buffer
  7718.     --------------------------------------------------
  7719.     procedure ADD_TO_BUFFER_ARRAY is
  7720.  
  7721.         type DUMMIES is (DUMMY);
  7722.  
  7723.  
  7724.  
  7725.         -------------------------------------------------------
  7726.         -- function verifies string called "dummy" ...
  7727.         -------------------------------------------------------
  7728.         function IN_DUMMIES return BOOLEAN is
  7729.         D_TEMP : DUMMIES;
  7730.  
  7731.         begin
  7732.         D_TEMP := DUMMIES'VALUE (ACTIVITY_NAME (1 .. 5));
  7733.         return TRUE;
  7734.         exception
  7735.         when CONSTRAINT_ERROR =>  return FALSE;
  7736.         end IN_DUMMIES;
  7737.  
  7738.  
  7739.  
  7740.         ---------------------------------------------
  7741.         -- prompt user for all estimates
  7742.         -- input data must be in float number ...
  7743.         ---------------------------------------------
  7744.         procedure NEW_SIMPERT_LINE is
  7745.  
  7746.  
  7747.             ---------------------------------------------
  7748.             -- process to receive a float number
  7749.             --------------------------------------------
  7750.         function RETURN_ESTIMATE (INPUT_PROMPT : STRING;
  7751.                       BEGIN_AT     : FLOAT := 0.0;
  7752.                       LIMIT_FLOAT  : FLOAT := 999.90000)
  7753.                        return FLOAT is
  7754.  
  7755.         begin
  7756.             return SCREEN_IO.RETURNED_FLOAT
  7757.                   (PROMPT     => ASCII.LF & ASCII.CR &
  7758.                          INPUT_PROMPT & ASCII.LF & ASCII.CR,
  7759.                    FROM_VALUE => BEGIN_AT,
  7760.                        CONFIRM    => FALSE,
  7761.                    TO_VALUE   => LIMIT_FLOAT);
  7762.         end RETURN_ESTIMATE;
  7763.  
  7764.  
  7765.         begin
  7766.  
  7767.         OPTIMISTICS :=
  7768.           RETURN_ESTIMATE
  7769.              (INPUT_PROMPT => "XXX.X  <--ENTER optimistic (1%) " &
  7770.                       "time estimate");
  7771.  
  7772.         MOST_LIKELY :=
  7773.           RETURN_ESTIMATE
  7774.              (INPUT_PROMPT => "XXX.X  <--ENTER most likely (1%) " &
  7775.                       "time estimate");
  7776.  
  7777.         PESSIMISTICS :=
  7778.           RETURN_ESTIMATE
  7779.              (INPUT_PROMPT => "XXX.X  <--ENTER pessimistic (1%) " &
  7780.                       "time estimate");
  7781.  
  7782.         ---------------------------------------------
  7783.         -- when time estimates are zero skip the rest
  7784.         ---------------------------------------------
  7785.         if OPTIMISTICS = 0.0 and
  7786.            MOST_LIKELY = 0.0 and PESSIMISTICS = 0.0 then
  7787.             STAFFING := 0.0;
  7788.             RATE := 0.0;
  7789.         else
  7790.             STAFFING :=
  7791.               RETURN_ESTIMATE
  7792.              (INPUT_PROMPT =>
  7793.                 "XX.X  <--ENTER average number of " &
  7794.                 "equivalent of full-time personnel",
  7795.               LIMIT_FLOAT  => 99.90000);
  7796.  
  7797.             RATE := RETURN_ESTIMATE
  7798.                    (INPUT_PROMPT =>
  7799.                   "XXXXXXX.X  <--ENTER average cost per " &
  7800.                   "man-time unit",
  7801.                 BEGIN_AT     => 1.0,
  7802.                 LIMIT_FLOAT  => 999999.90000);
  7803.         end if;
  7804.  
  7805.         end NEW_SIMPERT_LINE;
  7806.  
  7807.         -------------------------------------------------------
  7808.         -- Reads activity name & node numbers from screen ...
  7809.         -- uses NEW_SIMPERT_LINE to collect estimates
  7810.         -------------------------------------------------------
  7811.         procedure DATA_ENTRY is
  7812.  
  7813.         procedure TAKE_INPUT is
  7814.  
  7815.         begin
  7816.             ----------------------------------------------
  7817.             -- NAME is a MAX_ACT_NAME = 32 character 
  7818.             -- string ACTIVITY CODE is an MAX_ACT_CODE = 8
  7819.             -- character string
  7820.             ----------------------------------------------
  7821.             TEXT_IO.NEW_PAGE;
  7822.             TEXT_IO.NEW_LINE (2);
  7823.  
  7824.             TEXT_IO.SET_COL (TO => 15);
  7825.             TEXT_IO.PUT ("Activity [arc] number ");
  7826.             I_NUMBER.PUT (NUMBER_OF_ACTIVITIES_INPUTTED);
  7827.             TEXT_IO.NEW_LINE (2);
  7828.  
  7829.             OBTAIN_NAME
  7830.                (WITH_PROMPT     =>
  7831.               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  " &
  7832.               "<-- ENTER name of activity",
  7833.             THE_NAME        => ACTIVITY_NAME,
  7834.             END_OF_THE_NAME => NAME_LAST,
  7835.             MAX_OF_THE_NAME => MAX_ACT_NAME);
  7836.  
  7837.             if NAME_LAST < MAX_ACT_NAME then
  7838.             ACTIVITY_NAME (NAME_LAST + 1 .. MAX_ACT_NAME) :=
  7839.               (NAME_LAST + 1 .. MAX_ACT_NAME => ' ');
  7840.             end if;
  7841.  
  7842.             if IN_DUMMIES then
  7843.             CODE_LAST := MAX_ACT_CODE;
  7844.             WBS_CODE (1 .. CODE_LAST) := (1 .. CODE_LAST => ' ');
  7845.             else
  7846.             OBTAIN_NAME
  7847.                (WITH_PROMPT     =>
  7848.                   "XXXXXXXX  <-- ENTER arc code [WBS]",
  7849.                 THE_NAME        => WBS_CODE,
  7850.                 END_OF_THE_NAME => CODE_LAST,
  7851.                 MAX_OF_THE_NAME => MAX_ACT_CODE);
  7852.  
  7853.             if CODE_LAST < MAX_ACT_CODE then
  7854.                 WBS_CODE (CODE_LAST + 1 .. MAX_ACT_CODE) :=
  7855.                   (CODE_LAST + 1 .. MAX_ACT_CODE => ' ');
  7856.             end if;
  7857.             end if;
  7858.  
  7859.             -------------------------------------------------------
  7860.             -- TAIL and HEAD nodes must be greater than zero .......
  7861.             -------------------------------------------------------
  7862.  
  7863.             TAIL_NODE :=
  7864.               RETURN_INTEGER
  7865.              (INPUT_PROMPT  => "XXXX  <--ENTER tail node",
  7866.               START_INTEGER => 1,
  7867.               END_INTEGER   => MAXIMUM_NUMBER_OF_NAME_NODES);
  7868.             TEXT_IO.NEW_LINE;
  7869.  
  7870.             HEAD_NODE :=
  7871.               RETURN_INTEGER
  7872.              (INPUT_PROMPT  => "XXXX  <--ENTER head node",
  7873.               START_INTEGER => 1,
  7874.               END_INTEGER   => MAXIMUM_NUMBER_OF_NAME_NODES);
  7875.  
  7876.             TEXT_IO.NEW_PAGE;
  7877.             -- 
  7878.             --   CHECK FOR STRING "DUMMY" IN FIRST 5 CHARACTERS of ACT 
  7879.             -- 
  7880.             if IN_DUMMIES then
  7881.             OPTIMISTICS := 0.0;
  7882.             MOST_LIKELY := 0.0;
  7883.             PESSIMISTICS := 0.0;
  7884.             STAFFING := 0.0;
  7885.             RATE := 0.0;
  7886.             TEXT_IO.NEW_LINE (5);
  7887.             else
  7888.             TEXT_IO.NEW_LINE (3);
  7889.             TEXT_IO.SET_COL (TO => 10);
  7890.             TEXT_IO.PUT_LINE
  7891.                ("ENTER following parameters for activity:");
  7892.  
  7893.             TEXT_IO.SET_COL (TO => 14);
  7894.             TEXT_IO.PUT_LINE (ACTIVITY_NAME (1 .. NAME_LAST));
  7895.             TEXT_IO.NEW_LINE (3);
  7896.             -- 
  7897.             --          NEW line SIMPERT .....
  7898.             -- 
  7899.             -------------------------------------------------------
  7900.             -- MOST_LIKELY must be within the range of OPTI..PESSI
  7901.             -------------------------------------------------------
  7902.             NEW_SIMPERT_LINE;
  7903.  
  7904.             loop
  7905.                 if OPTIMISTICS > MOST_LIKELY or
  7906.                    MOST_LIKELY > PESSIMISTICS then
  7907.                 TEXT_IO.NEW_LINE;
  7908.                 TEXT_IO.PUT_LINE ("INPUT ERROR:");
  7909.  
  7910.                 TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7911.                 TEXT_IO.PUT_LINE
  7912.                    ("Relative size of input is inconsistent.");
  7913.                 TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7914.                 TEXT_IO.PUT_LINE
  7915.                     ("  Optimistics must be <= most likely " &
  7916.                     " <= pessimistic");
  7917.  
  7918.                 TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  7919.                 TEXT_IO.PUT_LINE ("Please try again.");
  7920.                 TEXT_IO.NEW_LINE (2);
  7921.                 NEW_SIMPERT_LINE;
  7922.                 else
  7923.                 exit;
  7924.                 end if;
  7925.             end loop;
  7926.             end if;
  7927.  
  7928.         end TAKE_INPUT;
  7929.  
  7930.  
  7931.         begin
  7932.         TAKE_INPUT;
  7933.  
  7934.         loop
  7935.             declare
  7936.             LOOP_ANSWER : constant STRING :=
  7937.                       SCREEN_IO.RETURNED_STRING
  7938.                      (PROMPT =>
  7939.                         ASCII.LF & ASCII.CR &
  7940.                         "ENTER [r] to RE_ENTER parameters" &
  7941.                         " for this activity" & ASCII.LF &
  7942.                         ASCII.CR &
  7943.                         "or press RETURN to continue ...." &
  7944.                         ASCII.LF & ASCII.CR);
  7945.             begin
  7946.             if LOOP_ANSWER = "r" or LOOP_ANSWER = "R" then
  7947.                 TAKE_INPUT;
  7948.  
  7949.             elsif LOOP_ANSWER = "" then
  7950.                 exit;
  7951.             else
  7952.                 TEXT_IO.NEW_LINE;
  7953.                 TEXT_IO.PUT_LINE
  7954.                    ("INPUT ERROR:  Please try again.");
  7955.                 TEXT_IO.NEW_LINE;
  7956.             end if;
  7957.             end;
  7958.         end loop;
  7959.  
  7960.         TEXT_IO.NEW_LINE (1);
  7961.         end DATA_ENTRY;
  7962.  
  7963.  
  7964.     begin
  7965.  
  7966.         NUMBER_OF_ACTIVITIES_INPUTTED := NUMBER_OF_ACTIVITIES_INPUTTED + 1;
  7967.         DATA_ENTRY;
  7968.  
  7969.         BODY_BUFFER_ARRAY (BODY_BUFFER_ARRAY_COUNTER).WBS_CODE :=
  7970.           WBS_CODE (1 .. MAX_ACT_CODE);
  7971.         BODY_BUFFER_ARRAY (BODY_BUFFER_ARRAY_COUNTER).ACTIVITY_NAME :=
  7972.           ACTIVITY_NAME (1 .. MAX_ACT_NAME);
  7973.         BODY_BUFFER_ARRAY (BODY_BUFFER_ARRAY_COUNTER).TAIL_NODE :=
  7974.           TAIL_NODE;
  7975.         BODY_BUFFER_ARRAY (BODY_BUFFER_ARRAY_COUNTER).HEAD_NODE :=
  7976.           HEAD_NODE;
  7977.         BODY_BUFFER_ARRAY (BODY_BUFFER_ARRAY_COUNTER).OPTIMISTICS :=
  7978.           OPTIMISTICS;
  7979.         BODY_BUFFER_ARRAY (BODY_BUFFER_ARRAY_COUNTER).MOST_LIKELY :=
  7980.           MOST_LIKELY;
  7981.         BODY_BUFFER_ARRAY (BODY_BUFFER_ARRAY_COUNTER).PESSIMISTICS :=
  7982.           PESSIMISTICS;
  7983.         BODY_BUFFER_ARRAY (BODY_BUFFER_ARRAY_COUNTER).STAFFING := STAFFING;
  7984.         BODY_BUFFER_ARRAY (BODY_BUFFER_ARRAY_COUNTER).RATE := RATE;
  7985.  
  7986.     end ADD_TO_BUFFER_ARRAY;
  7987.  
  7988.     begin
  7989.  
  7990.     NUMBER_ADDED := HOW_MANY_TO_BE_ADDED;
  7991.  
  7992.     ---------------------------------------------------------
  7993.     -- return to calling program when there is no added input
  7994.     ---------------------------------------------------------
  7995.     if NUMBER_ADDED = 0 then
  7996.         return;
  7997.     end if;
  7998.  
  7999.     --------------------------------------------------------------
  8000.     -- terminate when the summation of new and existing activities
  8001.     -- exceeds the  maximum number of activities allowed.
  8002.     --------------------------------------------------------------
  8003.  
  8004.     if (BODY_BUFFER_ARRAY_COUNTER + NUMBER_ADDED) >
  8005.        MAXIMUM_NUMBER_OF_ACTIVITIES then
  8006.  
  8007.         TEXT_IO.NEW_LINE;
  8008.         TEXT_IO.PUT_LINE ("NETWORK CONSTRAINT ERROR:");
  8009.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  8010.         TEXT_IO.PUT ("Number of activities exceeds " &
  8011.              "the maximum limit of ");
  8012.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  8013.         I_NUMBER.PUT (MAXIMUM_NUMBER_OF_ACTIVITIES);
  8014.         TEXT_IO.PUT (".");
  8015.         raise MAX_ACT_ERROR;
  8016.     end if;
  8017.  
  8018.  
  8019.     --------------------------------------------------
  8020.     -- process new activities when all else is in order
  8021.     --------------------------------------------------
  8022.     for INDEX in 1 .. NUMBER_ADDED loop
  8023.         BODY_BUFFER_ARRAY_COUNTER := BODY_BUFFER_ARRAY_COUNTER + 1;
  8024.         ADD_TO_BUFFER_ARRAY;
  8025.     end loop;
  8026.  
  8027.  
  8028.     exception
  8029.     when MAX_ACT_ERROR => 
  8030.         TEXT_IO.PUT_LINE ("NETWORK CONSTRAINT ERROR:");
  8031.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  8032.         TEXT_IO.PUT ("The number of activities contained in " &
  8033.              INPUT_FILE (1 .. END_FILE_NAME));
  8034.         TEXT_IO.PUT_LINE (" exceeds the maximum limit of ");
  8035.         I_NUMBER.PUT (MAXIMUM_NUMBER_OF_ACTIVITIES);
  8036.         TEXT_IO.PUT_LINE (".");
  8037.         raise END_MODIFY;
  8038.  
  8039.     end PROCESS_ADDITION;
  8040.  
  8041.  
  8042.  
  8043.     -------------------------------------
  8044.     -- modify the input file to reflect
  8045.     -- new changes per user request.
  8046.     -------------------------------------
  8047.     procedure MODIFY_USER_INPUT_FILE is
  8048.  
  8049.     REVISED_INPUT_FILE : TEXT_IO.FILE_TYPE;
  8050.  
  8051.     begin
  8052.     TEXT_IO.CREATE (REVISED_INPUT_FILE, TEXT_IO.OUT_FILE,
  8053.             INPUT_FILE (1 .. END_FILE_NAME));
  8054.  
  8055.     for I in 1 .. 5 loop
  8056.         TEXT_IO.PUT_LINE (REVISED_INPUT_FILE, FILE_HEADER (I).VALUE);
  8057.     end loop;
  8058.  
  8059.     for I in 1 .. BODY_BUFFER_ARRAY_COUNTER loop
  8060.         CURRENT_INPUT_LINE := BODY_BUFFER_ARRAY.all (I);
  8061.         WRITE_ONE_LINE (TO_FILE  => REVISED_INPUT_FILE,
  8062.                 A_RECORD => CURRENT_INPUT_LINE);
  8063.     end loop;
  8064.  
  8065.     TEXT_IO.CLOSE (REVISED_INPUT_FILE);
  8066.  
  8067.     end MODIFY_USER_INPUT_FILE;
  8068.  
  8069. begin
  8070.  
  8071.     WELCOME_MESSAGE;
  8072.  
  8073.     TEXT_IO.NEW_LINE (4);
  8074.     OBTAIN_ADD_OR_DELETE;
  8075.  
  8076.     TEXT_IO.NEW_LINE (4);
  8077.     OBTAIN_INPUT_FILE_NAME;
  8078.  
  8079.     CREATE_INPUT_BUFFER_ARRAY;
  8080.  
  8081.     if A_OR_D'VALUE (ADD_DELETE_ANSWER) = REQUEST_FOR_DELETION then
  8082.     PROCESS_DELETION;
  8083.  
  8084.     elsif A_OR_D'VALUE (ADD_DELETE_ANSWER) = REQUEST_FOR_ADDITION then
  8085.     PROCESS_ADDITION;
  8086.     end if;
  8087.  
  8088.     MODIFY_USER_INPUT_FILE;
  8089.  
  8090.     if (RETURN_YESNO
  8091.        (PROMPT     => "Are you done modifying?" & "  (y/n) --> " &
  8092.               ASCII.LF & ASCII.CR,
  8093.         DEFAULT    => NONE,
  8094.         FROM_VALUE => Y,
  8095.         TO_VALUE   => NO,
  8096.         ERROR_TEXT => ASCII.LF & ASCII.CR &
  8097.               "INPUT ERROR:  Answer must be either Y or N." &
  8098.               ASCII.LF & ASCII.CR) in N .. NO) then
  8099.     MODIFY;
  8100.     end if;
  8101.  
  8102. exception
  8103.     when END_PER_USER_ERROR =>
  8104.         PRESS_RETURN_TO_CONTINUE;
  8105.  
  8106.     when END_MODIFY => 
  8107.         PRESS_RETURN_TO_CONTINUE;
  8108.     TEXT_IO.CLOSE (USER_INPUT_FILE);
  8109.  
  8110.     when others => 
  8111.     FATAL (UNIT => "Schedule Tool - Unit named " &
  8112.                "[MODIFY]");
  8113.  
  8114. end MODIFY;
  8115. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8116. --pert.ada
  8117. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8118. with GRAPHS,
  8119.      TEXT_IO,
  8120.      DATE_AND_TIME,
  8121.      SCREEN_IO,
  8122.      FILE_HANDLER;
  8123.  
  8124.  
  8125. separate (SCHEDULE)
  8126. procedure PERT is
  8127. --------------------------------------------------------------------------
  8128. -- Author:     Ken Lamarche
  8129. -- Source:     Division Software Technology and Support
  8130. --             Western Development Laboratories
  8131. --             Ford Aerospace & Communications Corporation
  8132. --             ATTN:  Ada Tools Group
  8133. -- Date  :     May 1985
  8134. -- Summary: 
  8135. -- This is the main program on the SIMPERT process. It contains the data
  8136. -- structures used for the Event Nodes, and the Activity Arc (stucture includes
  8137. -- the information stored for a given node or arc). This procedure calls
  8138. -- separate subprograms to perform the functions of PERT.
  8139. ---------------------------------------------------------------------------
  8140.  
  8141.     MAX_NUMBER_OF_EVENTS                 : constant POSITIVE := 3400;
  8142.     MAX_NUMBER_OF_ACTIVITIES             : constant POSITIVE := 4000;
  8143.     MAX_NUMBER_OF_ACTIVITIES_INTO_NODE   : constant POSITIVE := 25;
  8144.     MAX_NUMBER_OF_ACTIVITIES_OUT_OF_NODE : constant POSITIVE := 25;
  8145.     MAX_YEAR                             : constant INTEGER := 99;
  8146.  
  8147.     -------------------------------------------------------------------------
  8148.     -- Used for Outputing Messages.
  8149.     -------------------------------------------------------------------------
  8150.     ERROR_INDENTATION : TEXT_IO.COUNT := 15;
  8151.  
  8152.     subtype EVENT_ID_TYPE    is INTEGER range 1 .. MAX_NUMBER_OF_EVENTS;
  8153.     subtype ACTIVITY_ID_TYPE is INTEGER range 1 .. MAX_NUMBER_OF_ACTIVITIES;
  8154.  
  8155.  
  8156.     type ACTIVITY_TYPE is
  8157.     record
  8158.         NAME               : STRING (1 .. 42);
  8159.         ACTIVITY_ID        : ACTIVITY_ID_TYPE;
  8160.         OPTIMISTIC_TIME    : FLOAT := 0.0;
  8161.         MOST_PROBABLE_TIME : FLOAT := 0.0;
  8162.         PESSIMISTIC_TIME   : FLOAT := 0.0;
  8163.         DURATION_TIME      : FLOAT := 0.0;
  8164.         ON_CP_COUNT        : FLOAT := 0.0;
  8165.         ESTIMATE_START     : FLOAT := 0.0;
  8166.         ESTIMATE_STOP      : FLOAT := 0.0;
  8167.         STAFFING           : FLOAT := 0.0;
  8168.         RATE               : FLOAT := 0.0;
  8169.     end record;
  8170.  
  8171.     type EVENT_TYPE is
  8172.     record
  8173.         EVENT_ID               : INTEGER := 0;
  8174.         DET_TIME_OF_EVENT      : FLOAT := 0.0;
  8175.         DET_LATE_TIME_OF_EVENT : FLOAT := -1.0;
  8176.         SIM_TIME_OF_EVENT      : FLOAT := 0.0;
  8177.         SUM_OF_TIMES           : FLOAT := 0.0;
  8178.         SUM_OF_SQUARES         : FLOAT := 0.0;
  8179.         VARIANCE               : FLOAT := 0.0;
  8180.         ESTIMATE_TIME_OF_EVENT : FLOAT := 0.0;
  8181.         CRIT_PATH_INDEX        : FLOAT := 0.0;
  8182.         MOST_CRIT_INBOUND_ARC  : NATURAL := 0;
  8183.         LONGEST_PATH_TO_EVENT  : INTEGER := 0;
  8184.     end record;
  8185.  
  8186.     -------------------------------------------------------------------------
  8187.     -- Time unit is a Day or Week.
  8188.     -------------------------------------------------------------------------
  8189.     type TIME_UNIT_TYPE is (D, W);
  8190.  
  8191.  
  8192.     -------------------------------------------------------------------------
  8193.     -- Some variables used in PERT, or in more than one separate subprogram.
  8194.     -------------------------------------------------------------------------
  8195.     GRAPH_IS_OK         : BOOLEAN;
  8196.  
  8197.     TIME_UNIT_CODE      : TIME_UNIT_TYPE := D;
  8198.     JULIAN_START_DATE   : DATE_AND_TIME.JULIAN_TYPE;
  8199.     WORKDAYS_PER_WEEK   : constant POSITIVE := 
  8200.                  SCREEN_IO.RETURNED_INTEGER
  8201.                 (PROMPT      =>
  8202.                    ASCII.LF & ASCII.CR & ASCII.LF &
  8203.                    ASCII.CR & ASCII.LF & ASCII.CR & ASCII.LF &
  8204.                    ASCII.CR & ASCII.LF & ASCII.CR &
  8205.                    "ENTER the number of workdays " &
  8206.                    "per week -->  ",
  8207.                  from_value  => 5,
  8208.                  to_value    => 7,
  8209.                  DEFAULT     => 5,
  8210.                  USE_DEFAULT => TRUE,
  8211.                  CONFIRM     => FALSE);
  8212.     CONFIDENCE_INTERVAL : FLOAT := 0.0;
  8213.  
  8214.  
  8215.     -------------------------------------------------------------------------
  8216.     -- The PERT process can be run in SIMULATION (Summing the results for
  8217.     -- later averaging), or DETERMINISTIC (uses three point averages, and
  8218.     -- the PERT process is only run once to determine a result).
  8219.     -------------------------------------------------------------------------
  8220.     type RUN_TYPE is (SIMULATION, DETERMINISTIC);
  8221.  
  8222.  
  8223.  
  8224.     NUMBER_OF_ITERATIONS   : constant INTEGER :=
  8225.                  SCREEN_IO.RETURNED_INTEGER
  8226.                 (PROMPT      =>
  8227.                    ASCII.LF & ASCII.CR & ASCII.LF &
  8228.                    ASCII.CR & ASCII.LF & ASCII.CR & ASCII.LF &
  8229.                    ASCII.CR & ASCII.LF & ASCII.CR &
  8230.                    "ENTER the number of iterations " &
  8231.                    "in the PERT simulation",
  8232.                  from_value  => 2,
  8233.                  to_value    => 5000,
  8234.                  DEFAULT     => 1000,
  8235.                  USE_DEFAULT => TRUE,
  8236.                  CONFIRM     => FALSE);
  8237.  
  8238.     PROBABILITY_FOR_OUTPUT : constant FLOAT :=
  8239.                  SCREEN_IO.RETURNED_FLOAT
  8240.                 (PROMPT      =>
  8241.                    ASCII.LF & ASCII.CR & ASCII.LF & ASCII.CR &
  8242.                    ASCII.LF & ASCII.CR &
  8243.                    "ENTER the desired probability for output",
  8244.                  DEFAULT     => 0.90,
  8245.                  FROM_VALUE  => 0.05,
  8246.                  TO_VALUE    => 0.95,
  8247.                  USE_DEFAULT => TRUE,
  8248.                  CONFIRM     => FALSE);
  8249.  
  8250.     -------------------------------------------------------------------------
  8251.     -- Get values for program constants:
  8252.     --   The input files,
  8253.     --   The number of iterations,
  8254.     --   The probability for the output display.
  8255.     -------------------------------------------------------------------------
  8256.     PERT_FILE        : constant STRING :=
  8257.                FILE_HANDLER.VERIFY_INPUT
  8258.               (FILE_PROMPT          =>
  8259.                  ASCII.LF & ASCII.CR & ASCII.LF & ASCII.CR &
  8260.                  ASCII.LF & ASCII.CR & ASCII.LF & ASCII.CR &
  8261.                  "Enter the name of the file containing " &
  8262.                  "Activity Information" & ASCII.LF & ASCII.CR &
  8263.                  "[32 characters or less].",
  8264.                MAX_FILE_NAME_LENGTH => 32);
  8265.  
  8266.     FILE_OF_HOLIDAYS : constant STRING :=
  8267.                FILE_HANDLER.VERIFY_INPUT
  8268.               (FILE_PROMPT          =>
  8269.                  ASCII.LF & ASCII.CR & ASCII.LF & ASCII.CR &
  8270.                  ASCII.LF & ASCII.CR &
  8271.                  "Enter the name of the file containing " &
  8272.                  "Holiday date" & ASCII.LF & ASCII.CR &
  8273.                  "[32 character or less].",
  8274.                MAX_FILE_NAME_LENGTH => 32);
  8275.  
  8276.     -------------------------------------------------------------------------
  8277.     -- File type object for Random Number File. This file is only used in 
  8278.     -- testing the pert program...
  8279.     -------------------------------------------------------------------------
  8280.     RANDOM_FILE : TEXT_IO.FILE_TYPE;
  8281.  
  8282.  
  8283.     STOP_SIMPERT      : exception;
  8284.     END_VERIFY_OUTPUT : exception;
  8285.  
  8286.  
  8287.  
  8288.  
  8289.  
  8290.     package PERT_OPS is new GRAPHS (ACTIVITY_TYPE, EVENT_TYPE);
  8291.  
  8292.     NETWORK : PERT_OPS.GRAPH_TYPE;
  8293.  
  8294.     -------------------------------------------------------------------------
  8295.     -- Function returns a GRAPH_TYPE data structure that is the graph
  8296.     -- described in the PERT_FILE input file. Exceptions are raised if
  8297.     -- the data in the file is not legal.
  8298.     -------------------------------------------------------------------------
  8299.     function PERT_NETWORK return PERT_OPS.GRAPH_TYPE is separate;
  8300.  
  8301.  
  8302.  
  8303.     -------------------------------------------------------------------------
  8304.     -- Procedure check the graph data structure for correctnes, ie,
  8305.     -- 1 source and sink, no cycles. OK is false on a bad graph.
  8306.     -------------------------------------------------------------------------
  8307.     procedure IS_GOOD (PERT_NETWORK : in out PERT_OPS.GRAPH_TYPE;
  8308.                OK           : out BOOLEAN) is separate;
  8309.  
  8310.  
  8311.  
  8312.     -------------------------------------------------------------------------
  8313.     -- Procedure does the PERT run. It does a traversal of the graph
  8314.     -- structure and sets times for the events, and starting/stopping
  8315.     -- times for the activities.
  8316.     -------------------------------------------------------------------------
  8317.     procedure PROCESS (IN_NETWORK : PERT_OPS.GRAPH_TYPE;
  8318.                FOR_RUN    : RUN_TYPE) is separate;
  8319.  
  8320.  
  8321.  
  8322.     -------------------------------------------------------------------------
  8323.     -- Procedure is used to perform calculations following the simulation
  8324.     -- of PERT. Calculations include averages, stnd dev, start and stop times
  8325.     -- (The "times" are floating values that are events in time. These values
  8326.     -- are translated to the approriate work unit (day or week) and calendar
  8327.     -- date when the values are printed.
  8328.     -------------------------------------------------------------------------
  8329.     procedure OVERALL_CALCS (PERT_NETWORK : PERT_OPS.GRAPH_TYPE) is separate;
  8330.  
  8331.  
  8332.     -------------------------------------------------------------------------
  8333.     -- Procedure prints the output reports. This procedure contains
  8334.     -- further separate subprograms to output each report.
  8335.     -------------------------------------------------------------------------
  8336.     procedure OUTPUT_VALUES is separate;
  8337.  
  8338.  
  8339. begin
  8340.  
  8341.     if (PERT_FILE = " ") or (FILE_OF_HOLIDAYS = " ") then
  8342.     TEXT_IO.NEW_LINE (2);
  8343.     TEXT_IO.PUT_LINE ("MISSING REQUIRED INPUT-FILE(s) !!!");
  8344.     TEXT_IO.NEW_LINE;
  8345.     TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  8346.     TEXT_IO.PUT_LINE ("PERT terminates on user request");
  8347.         PRESS_RETURN_TO_CONTINUE;
  8348.     else
  8349.  
  8350.     ------------------------------------------------------------------------
  8351.     -- Validate Output files. Make sure user wants to write over them.
  8352.     ------------------------------------------------------------------------
  8353.     FILE_HANDLER.VERIFY_OUTPUT;
  8354.  
  8355.     ------------------------------------------------------------------------
  8356.     -- Read file and check if graph is correct.
  8357.     ------------------------------------------------------------------------
  8358.     TEXT_IO.NEW_PAGE;
  8359.     TEXT_IO.SET_LINE (9);
  8360.     TEXT_IO.SET_COL (3);
  8361.     TEXT_IO.PUT_LINE ("Reading the Activity Info file, and checking" &
  8362.               " for correct graph structure.");
  8363.     NETWORK := PERT_NETWORK;
  8364.     IS_GOOD (PERT_NETWORK => NETWORK, OK => GRAPH_IS_OK);
  8365.  
  8366.     if GRAPH_IS_OK then
  8367.         PROCESS (IN_NETWORK => NETWORK, FOR_RUN => DETERMINISTIC);
  8368.  
  8369.         -----**********************************************************----
  8370.         --   Open a file of random numbers. This file is only used for
  8371.         --   testing the PERT program. Take these out on delivery.
  8372.         ------------------------------------------------------------------
  8373.         --   TEXT_IO.OPEN (RANDOM_FILE, TEXT_IO.IN_FILE, "random.num");
  8374.         -----**********************************************************----
  8375.  
  8376.  
  8377.         DO_SIMULATION:
  8378.         declare
  8379.         procedure SET_UP_DISPLAY is
  8380.         begin
  8381.             TEXT_IO.NEW_PAGE;
  8382.             TEXT_IO.SET_LINE (9);
  8383.             TEXT_IO.SET_COL (5);
  8384.             TEXT_IO.PUT_LINE
  8385.                ("Pert Simulation is now running, " &
  8386.             "(star represents another iteration).");
  8387.             TEXT_IO.NEW_LINE;
  8388.             TEXT_IO.SET_COL (10);
  8389.         end SET_UP_DISPLAY;
  8390.  
  8391.         begin
  8392.  
  8393.         SET_UP_DISPLAY;
  8394.  
  8395.         for ITERATIONS in 1 .. NUMBER_OF_ITERATIONS loop
  8396.             if ITERATIONS mod 600 = 0 then
  8397.             SET_UP_DISPLAY;
  8398.  
  8399.             elsif ITERATIONS mod 60 = 0 then
  8400.             TEXT_IO.NEW_LINE;
  8401.             TEXT_IO.SET_COL (10);
  8402.             end if;
  8403.  
  8404.             TEXT_IO.PUT ('*');
  8405.             PROCESS (IN_NETWORK => NETWORK, FOR_RUN => SIMULATION);
  8406.         end loop;
  8407.  
  8408.         end DO_SIMULATION;
  8409.  
  8410.         -----**********************************************************----
  8411.         --   Close the file of random numbers. Only used in testing pert.
  8412.         -------------------------------------------------------------------
  8413.         --   TEXT_IO.CLOSE (RANDOM_FILE);
  8414.         -----**********************************************************----
  8415.  
  8416.         --------------------------------------------------------------------
  8417.         -- Notify user of doing overall calculations.
  8418.         --------------------------------------------------------------------
  8419.         TEXT_IO.NEW_PAGE;
  8420.         TEXT_IO.SET_LINE (9);
  8421.         TEXT_IO.SET_COL (17);
  8422.         TEXT_IO.PUT_LINE ("Performing calculations for Simpert results.");
  8423.         OVERALL_CALCS (PERT_NETWORK => NETWORK);
  8424.  
  8425.         --------------------------------------------------------------------
  8426.         -- Generate output reports.
  8427.         --------------------------------------------------------------------
  8428.         OUTPUT_VALUES;
  8429.  
  8430.         OUTPUT_SUMMARY_ON_SCREEN:
  8431.         declare
  8432.         type ANSWER is (Y, YES, N, NO);
  8433.  
  8434.         function RETURNED_ANSWER is new SCREEN_IO.RETURNED_ENUMERATION
  8435.                (ANSWER);
  8436.  
  8437.         THE_SUMMARY_REPORT : TEXT_IO.FILE_TYPE;
  8438.         ONE_LINE           : STRING (1 .. 132);
  8439.         LAST_OF_LINE       : NATURAL;
  8440.         begin
  8441.         if RETURNED_ANSWER
  8442.               (PROMPT      =>
  8443.              ASCII.LF & ASCII.CR & ASCII.LF & ASCII.CR &
  8444.              ASCII.LF & ASCII.CR &
  8445.              "Do you wish to see the [Network Summary] on your " &
  8446.              "screen?  " & ASCII.LF & ASCII.CR & "ENTER [y/n] --> ",
  8447.                DEFAULT     => N,
  8448.                USE_DEFAULT => TRUE,
  8449.                ERROR_TEXT  =>
  8450.              ASCII.LF & ASCII.CR &
  8451.              "INPUT ERROR:  Please ENTER  either [y] or [n] ...") =
  8452.            Y then
  8453.  
  8454.             TEXT_IO.OPEN
  8455.                (THE_SUMMARY_REPORT, TEXT_IO.IN_FILE,
  8456.             FILE_HANDLER.OUTFILE_ARRAY (FILE_HANDLER.TOUT).VALUE);
  8457.  
  8458.             while not TEXT_IO.END_OF_FILE (THE_SUMMARY_REPORT) loop
  8459.             TEXT_IO.GET_LINE
  8460.                (THE_SUMMARY_REPORT, ONE_LINE, LAST_OF_LINE);
  8461.             TEXT_IO.PUT_LINE (ONE_LINE (1 .. LAST_OF_LINE));
  8462.             end loop;
  8463.  
  8464.             TEXT_IO.CLOSE (THE_SUMMARY_REPORT);
  8465.                     PRESS_RETURN_TO_CONTINUE;
  8466.         end if;
  8467.         end OUTPUT_SUMMARY_ON_SCREEN;
  8468.     else
  8469.  
  8470.         --------------------------------------------------------------------
  8471.         -- On bad graph...
  8472.         --------------------------------------------------------------------
  8473.         raise STOP_SIMPERT;
  8474.     end if;
  8475.     end if;
  8476.  
  8477. exception
  8478.     when FILE_HANDLER.STOP_ON_USER_REQUEST => 
  8479.     TEXT_IO.NEW_LINE;
  8480.     TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  8481.     TEXT_IO.PUT_LINE ("PERT terminated on user request.");
  8482.         PRESS_RETURN_TO_CONTINUE;
  8483.  
  8484.     when STOP_SIMPERT | FILE_HANDLER.END_FILE_HANDLER_REQUEST => 
  8485.     TEXT_IO.NEW_LINE;
  8486.     TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  8487.     TEXT_IO.PUT_LINE ("A fatal error ocurred. PERT cannot continue.");
  8488.         PRESS_RETURN_TO_CONTINUE;
  8489.  
  8490.     when END_VERIFY_OUTPUT => 
  8491.     null;
  8492.  
  8493.     when others => 
  8494.     FATAL (UNIT => "Schedule Tool - Unit named " & "[PERT]");
  8495.  
  8496. end PERT;
  8497.  
  8498.  
  8499.  
  8500.  
  8501. with PERT_IO,
  8502.      TEXT_IO,
  8503.      SCREEN_IO,
  8504.      STRING_UTILITIES;
  8505.  
  8506. separate (SCHEDULE.PERT)
  8507. function PERT_NETWORK return PERT_OPS.GRAPH_TYPE is
  8508. ----------------------------------------------------------------------------
  8509. -- Author:  Ken Lamarche
  8510. -- Source:     Division Software Technology and Support
  8511. --             Western Development Laboratories
  8512. --             Ford Aerospace & Communications Corporation
  8513. --             ATTN:  Ada Tools Group
  8514. -- Date:    May 1985
  8515. -- Summary:
  8516. -- This function reads the file of activities, and creates a graph from it.
  8517. -- This function does not check the graph for validity, it just constructs it.
  8518. ----------------------------------------------------------------------------
  8519.  
  8520.     ACTIVITY_FILE  : TEXT_IO.FILE_TYPE;
  8521.     ACTIVITY       : ACTIVITY_TYPE;
  8522.     EVENT          : EVENT_TYPE;
  8523.     HEADER_SET     : PERT_IO.HEADER_BUFFER_ARRAY;
  8524.     ACTIVITY_SET   : PERT_IO.INPUT_LINE_RECORD_TYPE;
  8525.     NETWORK        : PERT_OPS.GRAPH_TYPE;
  8526.  
  8527.     ACTIVITY_READ  : BOOLEAN := FALSE;  -- Set true when first activity is read
  8528.                        -- from the file.
  8529.     ERROR_ACTIVITY : PERT_IO.NAME_TYPE; -- Equals name of last entered activity.
  8530.  
  8531. ------------------------------------------
  8532. -- Exceptions raised by this procedure:
  8533. ------------------------------------------
  8534.     BAD_DATE_INFO      : exception;
  8535.     BAD_TIME_CODE_UNIT : exception;
  8536.  
  8537.  
  8538.  
  8539. ----------------------------------------------------------------------------
  8540. -- This function will create a node in the graph structure given the event
  8541. -- record. (If the node doesn't exist it will create it and return the
  8542. -- NODE_TYPE. If it does exist, it will just return the existing NODE_TYPE.)
  8543. ----------------------------------------------------------------------------
  8544.     function NODE (WITH_ID : INTEGER) return PERT_OPS.NODE_TYPE is
  8545.     ID        : INTEGER renames WITH_ID;
  8546.     EVENT     : EVENT_TYPE;
  8547.     NODE_LIST : constant PERT_OPS.NODE_LIST_TYPE :=
  8548.             PERT_OPS.NODES (ON_GRAPH => NETWORK);
  8549.     begin
  8550.  
  8551.     for INDEX in NODE_LIST'RANGE loop
  8552.         if PERT_OPS.VALUE (NODE_LIST (INDEX)).EVENT_ID = ID then
  8553.         return NODE_LIST (INDEX);
  8554.         end if;
  8555.     end loop;
  8556.  
  8557.     EVENT.EVENT_ID := ID;
  8558.     return PERT_OPS.NEW_NODE
  8559.           (WITH_VALUE                      => EVENT,
  8560.            MAXIMUM_NUMBER_OF_INCOMING_ARCS =>
  8561.              MAX_NUMBER_OF_ACTIVITIES_INTO_NODE,
  8562.            MAXIMUM_NUMBER_OF_OUTGOING_ARCS =>
  8563.              MAX_NUMBER_OF_ACTIVITIES_OUT_OF_NODE,
  8564.            IN_GRAPH                        => NETWORK);
  8565.     end NODE;
  8566.  
  8567.  
  8568.  
  8569. --------------------------------------------------------------------
  8570. -- This procedure is used to zero the values of a "dummy" activity.
  8571. -- If the activity name is "dummy", all numeric components of the
  8572. -- activity are set to zero.
  8573. --------------------------------------------------------------------
  8574.     procedure ZERO_DUMMY
  8575.          (ACTIVITY_SET : in out PERT_IO.INPUT_LINE_RECORD_TYPE) is
  8576.  
  8577.     begin
  8578.     if STRING_UTILITIES.LOWER_TO_UPPER
  8579.           (STRING_UTILITIES.REMOVE_LEADING_AND_TRAILING_BLANKS
  8580.           (ACTIVITY_SET.ACTIVITY_NAME)) = "DUMMY" then
  8581.         ACTIVITY_SET.OPTIMISTICS := 0.0;
  8582.         ACTIVITY_SET.MOST_LIKELY := 0.0;
  8583.         ACTIVITY_SET.PESSIMISTICS := 0.0;
  8584.         ACTIVITY_SET.STAFFING := 0.0;
  8585.         ACTIVITY_SET.RATE := 0.0;
  8586.     end if;
  8587.  
  8588.     return;
  8589.     end ZERO_DUMMY;
  8590.  
  8591.  
  8592.  
  8593. begin
  8594.     PERT_OPS.CREATE
  8595.        (A_GRAPH                 => NETWORK,
  8596.     WITH_START_NODE         => null,
  8597.     WITH_END_NODE           => null,
  8598.     MAXIMUM_NUMBER_OF_NODES => MAX_NUMBER_OF_EVENTS);
  8599.  
  8600.     TEXT_IO.OPEN (FILE => ACTIVITY_FILE,
  8601.           MODE => TEXT_IO.IN_FILE,
  8602.           NAME => STRING_UTILITIES.REMOVE_LEADING_AND_TRAILING_BLANKS
  8603.                  (PERT_FILE));
  8604.  
  8605.     PERT_IO.READ_HEADER (ACTIVITY_FILE, HEADER_SET);
  8606.  
  8607.     LOAD_HEADER_INFORMATION:
  8608.     declare
  8609.     LAST_INDEX, START_CHAR : POSITIVE := 1;
  8610.     DATE_INFO              : array (1 .. 3) of INTEGER;
  8611.     DATE_SPEC              : DATE_AND_TIME.CALENDAR_TYPE;
  8612.  
  8613.     package INT_IO is new TEXT_IO.INTEGER_IO (INTEGER);
  8614.     begin
  8615.     TIME_UNIT_CODE := TIME_UNIT_TYPE'VALUE
  8616.                 (STRING_UTILITIES
  8617.                   .REMOVE_LEADING_AND_TRAILING_BLANKS
  8618.                 (HEADER_SET (2).VALUE));
  8619.  
  8620.     for I in 1 .. 3 loop
  8621.         INT_IO.GET (FROM => HEADER_SET (3).VALUE
  8622.                    (START_CHAR .. HEADER_SET (3).LENGTH),
  8623.             ITEM => DATE_INFO (I),
  8624.             LAST => LAST_INDEX);
  8625.         START_CHAR := LAST_INDEX + 1;
  8626.     end loop;
  8627.  
  8628.     DATE_SPEC := (DAY   => DATE_INFO (1),
  8629.               MONTH => DATE_INFO (2),
  8630.               YEAR  => DATE_INFO (3));
  8631.     JULIAN_START_DATE := DATE_AND_TIME.JULIAN_DATE (DATE_SPEC);
  8632.  
  8633.     exception
  8634.     when CONSTRAINT_ERROR => 
  8635.         raise BAD_TIME_CODE_UNIT;
  8636.  
  8637.     when TEXT_IO.DATA_ERROR => 
  8638.         raise BAD_DATE_INFO;
  8639.     end LOAD_HEADER_INFORMATION;
  8640.  
  8641.  
  8642.     loop
  8643.  
  8644.     PERT_IO.READ_ONE_ACTIVITY_LINE (ACTIVITY_FILE, ACTIVITY_SET);
  8645.     ZERO_DUMMY (ACTIVITY_SET);
  8646.  
  8647.     ACTIVITY.NAME := (ACTIVITY_SET.WBS_CODE & "  " &
  8648.               ACTIVITY_SET.ACTIVITY_NAME);
  8649.     ACTIVITY.OPTIMISTIC_TIME := ACTIVITY_SET.OPTIMISTICS;
  8650.     ACTIVITY.MOST_PROBABLE_TIME := ACTIVITY_SET.MOST_LIKELY;
  8651.     ACTIVITY.PESSIMISTIC_TIME := ACTIVITY_SET.PESSIMISTICS;
  8652.     ACTIVITY.STAFFING := ACTIVITY_SET.STAFFING;
  8653.     ACTIVITY.RATE := ACTIVITY_SET.RATE;
  8654.  
  8655.     ACTIVITY_READ := TRUE;
  8656.     ERROR_ACTIVITY := ACTIVITY_SET.ACTIVITY_NAME;
  8657.  
  8658.     ---------------------------------------
  8659.     -- insert new activity into network
  8660.     ---------------------------------------
  8661.     PERT_OPS.CREATE_ARC (WITH_VALUE   => ACTIVITY,
  8662.                  BETWEEN_NODE => NODE (ACTIVITY_SET.TAIL_NODE),
  8663.                  AND_NODE     => NODE (ACTIVITY_SET.HEAD_NODE));
  8664.     end loop;
  8665.  
  8666.  
  8667. exception
  8668.     when PERT_IO.END_OF_ACTIVITY_FILE_REACHED => 
  8669.     if ACTIVITY_READ then
  8670.         TEXT_IO.CLOSE (ACTIVITY_FILE);
  8671.         return NETWORK;
  8672.     else
  8673.         TEXT_IO.NEW_LINE;
  8674.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  8675.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  8676.         TEXT_IO.PUT_LINE ("File " & TEXT_IO.NAME (ACTIVITY_FILE) &
  8677.                   " contains no activity information.");
  8678.         TEXT_IO.NEW_LINE;
  8679.         TEXT_IO.CLOSE (ACTIVITY_FILE);
  8680.             PRESS_RETURN_TO_CONTINUE;
  8681.         raise STOP_SIMPERT;
  8682.     end if;
  8683.  
  8684.     when PERT_IO.BAD_DATA | PERT_IO.VALUE_OUTSIDE_LEGAL_RANGE |
  8685.      BAD_TIME_CODE_UNIT | BAD_DATE_INFO => 
  8686.  
  8687.     TEXT_IO.NEW_LINE;
  8688.     TEXT_IO.PUT_LINE ("INPUT ERROR:");
  8689.     TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  8690.     TEXT_IO.PUT_LINE ("File " & TEXT_IO.NAME (ACTIVITY_FILE) &
  8691.               " contains unexpected data ");
  8692.     TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  8693.  
  8694.     if ACTIVITY_READ then
  8695.         TEXT_IO.PUT_LINE ("at line following activity " &
  8696.                   STRING_UTILITIES
  8697.                    .REMOVE_LEADING_AND_TRAILING_BLANKS
  8698.                  (ERROR_ACTIVITY) & ".");
  8699.     else
  8700.         TEXT_IO.PUT_LINE ("in or following the header information.");
  8701.     end if;
  8702.  
  8703.     TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  8704.     TEXT_IO.PUT_LINE ("Please CORRECT the Activity file and " &
  8705.               "RE-RUN the program.");
  8706.     TEXT_IO.CLOSE (ACTIVITY_FILE);
  8707.         PRESS_RETURN_TO_CONTINUE;
  8708.     raise STOP_SIMPERT;
  8709.  
  8710.     when PERT_OPS.MAXIMUM_NUMBER_OF_NODES_SPECIFIED_IN_GRAPH => 
  8711.  
  8712.     TEXT_IO.NEW_LINE;
  8713.     TEXT_IO.PUT_LINE ("INPUT ERROR:");
  8714.     TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  8715.     TEXT_IO.PUT_LINE ("File " & TEXT_IO.NAME (ACTIVITY_FILE) &
  8716.               " specifies too many Event Nodes.");
  8717.         PRESS_RETURN_TO_CONTINUE;
  8718.     raise STOP_SIMPERT;
  8719.  
  8720.     when PERT_OPS.NOT_ENOUGH_STORAGE_REMAINING => 
  8721.  
  8722.     TEXT_IO.NEW_LINE;
  8723.     TEXT_IO.PUT_LINE ("INPUT ERROR:");
  8724.     TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  8725.     TEXT_IO.PUT_LINE ("File " & TEXT_IO.NAME (ACTIVITY_FILE) &
  8726.               " specifies a graph too big for available memory.");
  8727.     TEXT_IO.CLOSE (ACTIVITY_FILE);
  8728.         PRESS_RETURN_TO_CONTINUE;
  8729.     raise STOP_SIMPERT;
  8730.  
  8731.  
  8732.     when PERT_OPS.MAXIMUM_NUMBER_OF_ARCS_SPECIFIED_BETWEEN_THESE_NODES => 
  8733.  
  8734.     TEXT_IO.NEW_LINE;
  8735.     TEXT_IO.PUT_LINE ("INPUT ERROR:");
  8736.     TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  8737.     TEXT_IO.PUT_LINE ("File " & TEXT_IO.NAME (ACTIVITY_FILE) &
  8738.               " specifies an event with too many activity " &
  8739.               "in and/or out.");
  8740.     TEXT_IO.CLOSE (ACTIVITY_FILE);
  8741.         PRESS_RETURN_TO_CONTINUE;
  8742.     raise STOP_SIMPERT;
  8743.  
  8744.     when others => 
  8745.     FATAL (UNIT => "Schedule Tool - Unit named " & "[PERT.PERT_NETWORK]");
  8746.  
  8747. end PERT_NETWORK;
  8748.  
  8749.  
  8750.  
  8751.  
  8752.  
  8753. with NUMERIC_PRIMITIVES;
  8754.  
  8755. separate (SCHEDULE.PERT)
  8756. procedure PROCESS (IN_NETWORK : PERT_OPS.GRAPH_TYPE; FOR_RUN : RUN_TYPE) is
  8757. -----------------------------------------------------------------
  8758. -- Author:  Ken Lamarche
  8759. -- Source:     Division Software Technology and Support
  8760. --             Western Development Laboratories
  8761. --             Ford Aerospace & Communications Corporation
  8762. --             ATTN:  Ada Tools Group
  8763. -- Date  :  May 1985
  8764. -- Summary:
  8765. -----------------------------------------------------------------
  8766.  
  8767.     NETWORK   : PERT_OPS.GRAPH_TYPE renames IN_NETWORK;
  8768.     NODE_LIST : constant PERT_OPS.NODE_LIST_TYPE :=
  8769.         PERT_OPS.NODES (ON_GRAPH => NETWORK);
  8770.     RUN       : RUN_TYPE renames FOR_RUN;
  8771.  
  8772.     function "=" (LEFT, RIGHT : PERT_OPS.NODE_TYPE) return BOOLEAN
  8773.            renames PERT_OPS."=";
  8774.  
  8775.     -- Set up a Floating Point IO package for reading random numbers
  8776.     -- from a file. This is temporary code for testing purposes only.
  8777.     -- The code line below should be taken out on delivery.
  8778.     package FLT_IO is new TEXT_IO.FLOAT_IO (FLOAT);
  8779.  
  8780.     --------------------------------------------------------------------
  8781.     -- calculate the distribution of optimistics, pessimisstics, and
  8782.     -- most likely estimates
  8783.     --------------------------------------------------------------------
  8784.     function TRIANGULAR_DISTRIBUTION
  8785.             (LOW_VALUE, MIDDLE_VALUE, HIGH_VALUE : FLOAT) return FLOAT is
  8786.     TEMP, F, HEIGHT : FLOAT;
  8787.  
  8788.     -----**********************************************************----
  8789.     --   Function used for testing purposes to return a random
  8790.     --   number from a file.
  8791.         --------------------------------------------------------------------
  8792.     --   function GIVE_RANDOM return FLOAT is
  8793.     --       R1 : FLOAT;
  8794.     --   begin
  8795.     --       FLT_IO.GET (RANDOM_FILE, R1);
  8796.     --       return R1;
  8797.     --   end GIVE_RANDOM;
  8798.     -----**********************************************************----
  8799.  
  8800.     begin
  8801.     HEIGHT := 2.0 / (HIGH_VALUE - LOW_VALUE);
  8802.  
  8803.     loop
  8804.         -----**********************************************************----
  8805.         --   For testing purposes, a random number is read in from a file.
  8806.         -------------------------------------------------------------------
  8807.         --   TEMP := LOW_VALUE + GIVE_RANDOM * (HIGH_VALUE - LOW_VALUE);
  8808.         -----**********************************************************----
  8809.  
  8810.         TEMP := LOW_VALUE +
  8811.                  NUMERIC_PRIMITIVES.RAN * (HIGH_VALUE - LOW_VALUE);
  8812.  
  8813.         if TEMP < MIDDLE_VALUE then
  8814.         F := HEIGHT * (TEMP - LOW_VALUE) / (MIDDLE_VALUE - LOW_VALUE);
  8815.         else
  8816.         F := HEIGHT * (TEMP - HIGH_VALUE) / (MIDDLE_VALUE - HIGH_VALUE);
  8817.         end if;
  8818.  
  8819.         -----**********************************************************----
  8820.         --   For testing purposes, read the random number from a file.
  8821.         -------------------------------------------------------------------
  8822.         --   exit when GIVE_RANDOM <= (F / HEIGHT);
  8823.         -----**********************************************************----
  8824.  
  8825.         exit when NUMERIC_PRIMITIVES.RAN <= (F / HEIGHT);
  8826.     end loop;
  8827.  
  8828.     return TEMP;
  8829.     end TRIANGULAR_DISTRIBUTION;
  8830.  
  8831.  
  8832.     --------------------------------------------------------------------------
  8833.     -- This procedure will handle the determined "Time Of The Event" depending
  8834.     -- on the type of run... Deterministic, or Simulation.
  8835.     --------------------------------------------------------------------------
  8836.     procedure HANDLE_TIME_OF_EVENT (EVENT_TIME : FLOAT;
  8837.                     EVENT      : in out EVENT_TYPE) is
  8838.     begin
  8839.     case RUN is
  8840.         when SIMULATION => 
  8841.         EVENT.SIM_TIME_OF_EVENT := EVENT_TIME;
  8842.         EVENT.SUM_OF_TIMES := EVENT.SUM_OF_TIMES + EVENT_TIME;
  8843.         EVENT.SUM_OF_SQUARES := EVENT.SUM_OF_SQUARES + EVENT_TIME ** 2;
  8844.  
  8845.         when DETERMINISTIC => 
  8846.         EVENT.DET_TIME_OF_EVENT := EVENT_TIME;
  8847.         EVENT.SIM_TIME_OF_EVENT := EVENT_TIME;
  8848.     end case;
  8849.     end HANDLE_TIME_OF_EVENT;
  8850.  
  8851.  
  8852.     --------------------------------------------------------------------
  8853.     -- This function produces a duration time for an arc, depending on
  8854.     -- whether this is a deterministic run or not. On a deterministic
  8855.     -- pert run, the duration is a three point average. On a non deter-
  8856.     -- ministic run, the duration is triangular distributed random #.
  8857.     --------------------------------------------------------------------
  8858.     function PRODUCE_DURATION (OPTIM, MOST_PROB, PESSIM : FLOAT) return FLOAT is
  8859.     begin
  8860.     if OPTIM = PESSIM then
  8861.         return OPTIM;
  8862.     else
  8863.         case RUN is
  8864.         when DETERMINISTIC => 
  8865.             return (OPTIM + MOST_PROB + PESSIM) / 3.0;
  8866.  
  8867.         when SIMULATION => 
  8868.             return TRIANGULAR_DISTRIBUTION (OPTIM, MOST_PROB, PESSIM);
  8869.         end case;
  8870.     end if;
  8871.     end PRODUCE_DURATION;
  8872.  
  8873.  
  8874.  
  8875.  
  8876. begin
  8877.     for NODE_INDEX in NODE_LIST'RANGE loop
  8878.     declare
  8879.         EVENT_IMAGE : PERT_OPS.NODE_TYPE renames NODE_LIST (NODE_INDEX);
  8880.         EVENT       : EVENT_TYPE := PERT_OPS.VALUE (EVENT_IMAGE);
  8881.     begin
  8882.         if EVENT_IMAGE /= PERT_OPS.START_NODE (NETWORK) then
  8883.         declare
  8884.             ARC_LIST                  : constant PERT_OPS
  8885.                               .ARC_LIST_TYPE :=
  8886.                         PERT_OPS.INCOMING_ARCS
  8887.                            (ON_NODE => EVENT_IMAGE);
  8888.             TEMP_EVENT_TIME           : FLOAT := 0.0;
  8889.             CRITICAL_ACTIVITY         : ACTIVITY_TYPE;
  8890.             MOST_CRITICAL_INBOUND_ARC : PERT_OPS.ARC_TYPE;
  8891.         begin
  8892.             for ARC_INDEX in ARC_LIST'RANGE loop
  8893.  
  8894.             EXAMINE_EACH_INCOMING_ARC:
  8895.             declare
  8896.                 ACTIVITY       : ACTIVITY_TYPE :=
  8897.                          PERT_OPS.VALUE
  8898.                         (ARC_LIST (ARC_INDEX));
  8899.                 EARLIEST_START : FLOAT :=
  8900.                          PERT_OPS.VALUE
  8901.                         (PERT_OPS.TAIL_NODE
  8902.                             (ARC_LIST (ARC_INDEX)))
  8903.                           .SIM_TIME_OF_EVENT;
  8904.                 DURATION_TIME  : FLOAT :=
  8905.                          PRODUCE_DURATION
  8906.                         (ACTIVITY.OPTIMISTIC_TIME,
  8907.                          ACTIVITY.MOST_PROBABLE_TIME,
  8908.                          ACTIVITY.PESSIMISTIC_TIME);
  8909.  
  8910.             begin
  8911.  
  8912.                 if (DURATION_TIME + EARLIEST_START) >
  8913.                    TEMP_EVENT_TIME then
  8914.                 TEMP_EVENT_TIME :=
  8915.                   DURATION_TIME + EARLIEST_START;
  8916.                 MOST_CRITICAL_INBOUND_ARC :=
  8917.                   ARC_LIST (ARC_INDEX);
  8918.                 end if;
  8919.             end EXAMINE_EACH_INCOMING_ARC;
  8920.  
  8921.             end loop;
  8922.  
  8923.             CRITICAL_ACTIVITY :=
  8924.               PERT_OPS.VALUE (MOST_CRITICAL_INBOUND_ARC);
  8925.  
  8926.             if RUN = SIMULATION then
  8927.             CRITICAL_ACTIVITY.ON_CP_COUNT :=
  8928.               CRITICAL_ACTIVITY.ON_CP_COUNT + 1.0;
  8929.             end if;
  8930.  
  8931.             PERT_OPS.ASSIGN
  8932.                (CRITICAL_ACTIVITY, MOST_CRITICAL_INBOUND_ARC);
  8933.  
  8934.             HANDLE_TIME_OF_EVENT (TEMP_EVENT_TIME, EVENT);
  8935.             PERT_OPS.ASSIGN (EVENT, EVENT_IMAGE);
  8936.         end;
  8937.         -- processing for a given node
  8938.         end if;
  8939.         -- node processed was not the start node
  8940.     end;
  8941.     -- block for node processing declarations
  8942.     end loop;
  8943.  
  8944. exception
  8945.     when others => 
  8946.     FATAL (UNIT => "Schedule Tool - Unit named " & "[PERT.PROCESS]");
  8947.  
  8948. end PROCESS;
  8949.  
  8950.  
  8951.  
  8952.  
  8953.  
  8954. with TEXT_IO;
  8955.  
  8956. separate (SCHEDULE.PERT)
  8957. procedure IS_GOOD (PERT_NETWORK : in out PERT_OPS.GRAPH_TYPE;
  8958.            OK           : out BOOLEAN) is
  8959. -----------------------------------------------------------
  8960. -- Author:     Larry Yelowitz
  8961. -- Source:     Division Software Technology and Support
  8962. --             Western Development Laboratories
  8963. --             Ford Aerospace & Communications Corporation
  8964. --             ATTN:  Ada Tools Group
  8965. -- Date  :     May 25 1985
  8966. -- Summary:    This procedure verifies the validity of a network
  8967. -----------------------------------------------------------
  8968.  
  8969.     SINK_LIST   : constant PERT_OPS.NODE_LIST_TYPE :=
  8970.           PERT_OPS.LIST_OF_SINKS (IN_GRAPH => PERT_NETWORK);
  8971.     SOURCE_LIST : constant PERT_OPS.NODE_LIST_TYPE :=
  8972.           PERT_OPS.LIST_OF_SOURCES (IN_GRAPH => PERT_NETWORK);
  8973.  
  8974.     package INT_IO is new TEXT_IO.INTEGER_IO (INTEGER);
  8975.  
  8976.  
  8977. begin
  8978.  
  8979.     OK := TRUE;
  8980.  
  8981.     begin
  8982.     PERT_OPS.TOPSORT (PERT_NETWORK.NODE_LIST);
  8983.     exception
  8984.     when PERT_OPS.CYCLE_EXISTS => 
  8985.  
  8986.         TEXT_IO.NEW_LINE;
  8987.         TEXT_IO.PUT_LINE ("PERT NETWORK ERROR:");
  8988.  
  8989.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  8990.         TEXT_IO.PUT_LINE ("Cycles were found in your network.");
  8991.             PRESS_RETURN_TO_CONTINUE;
  8992.         OK := FALSE;
  8993.     end;
  8994.  
  8995.  
  8996.     case SINK_LIST'LENGTH is
  8997.     when 0 => 
  8998.         TEXT_IO.NEW_LINE;
  8999.         TEXT_IO.PUT_LINE ("PERT NETWORK ERROR:");
  9000.  
  9001.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  9002.         TEXT_IO.PUT_LINE
  9003.            ("You have not specified an ending event in the network.");
  9004.             PRESS_RETURN_TO_CONTINUE;
  9005.         OK := FALSE;
  9006.  
  9007.     when 1 =>  PERT_OPS.SET_END_NODE (SINK_LIST (1), PERT_NETWORK);
  9008.  
  9009.     when others => 
  9010.         OK := FALSE;
  9011.         TEXT_IO.NEW_LINE;
  9012.         TEXT_IO.PUT_LINE ("PERT NETWORK ERROR:");
  9013.  
  9014.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  9015.         TEXT_IO.PUT_LINE ("You have specified more than one ending event.");
  9016.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  9017.         TEXT_IO.PUT_LINE ("These are event numbers:");
  9018.  
  9019.         for INDEX in SINK_LIST'RANGE loop
  9020.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  9021.         INT_IO.PUT (PERT_OPS.VALUE (SINK_LIST (INDEX)).EVENT_ID);
  9022.         TEXT_IO.NEW_LINE;
  9023.         end loop;
  9024.             PRESS_RETURN_TO_CONTINUE;
  9025.     end case;
  9026.  
  9027.     case SOURCE_LIST'LENGTH is
  9028.     when 0 => 
  9029.         TEXT_IO.NEW_LINE;
  9030.         TEXT_IO.PUT_LINE ("PERT NETWORK ERROR:");
  9031.  
  9032.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  9033.         TEXT_IO.PUT_LINE
  9034.            ("You have not specified a starting event in the network.");
  9035.             PRESS_RETURN_TO_CONTINUE;
  9036.         OK := FALSE;
  9037.  
  9038.     when 1 =>  PERT_OPS.SET_START_NODE (SOURCE_LIST (1), PERT_NETWORK);
  9039.  
  9040.     when others => 
  9041.         OK := FALSE;
  9042.         TEXT_IO.NEW_LINE;
  9043.         TEXT_IO.PUT_LINE ("PERT NETWORK ERROR:");
  9044.  
  9045.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  9046.         TEXT_IO.PUT_LINE ("You have specified more than one " &
  9047.                   "starting event in the network.");
  9048.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  9049.         TEXT_IO.PUT_LINE ("These are event numbers:");
  9050.  
  9051.         for INDEX in SOURCE_LIST'RANGE loop
  9052.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  9053.         INT_IO.PUT (PERT_OPS.VALUE (SOURCE_LIST (INDEX)).EVENT_ID);
  9054.         TEXT_IO.NEW_LINE;
  9055.         end loop;
  9056.             PRESS_RETURN_TO_CONTINUE;
  9057.     end case;
  9058.  
  9059. exception
  9060.     when others => 
  9061.     FATAL (UNIT => "Schedule Tool - Unit named " & "[PERT.IS_GOOD]");
  9062.  
  9063. end IS_GOOD;
  9064.  
  9065.  
  9066.  
  9067.  
  9068.  
  9069. with MATH_FUNCTIONS;
  9070.  
  9071. separate (SCHEDULE.PERT)
  9072. procedure OVERALL_CALCS (PERT_NETWORK : PERT_OPS.GRAPH_TYPE) is
  9073. ---------------------------------------------------------------------------
  9074. -- Author:  Ken Lamarche
  9075. -- Source:     Division Software Technology and Support
  9076. --             Western Development Laboratories
  9077. --             Ford Aerospace & Communications Corporation
  9078. --             ATTN:  Ada Tools Group
  9079. -- Date  :  May 1985
  9080. -- Summary:
  9081. -- This procedure is called to perform overall calculations for the SIMPERT
  9082. -- process following the iterations of the pert program. The calculations
  9083. -- include setting averages and variances of event times, criticallity
  9084. -- values for nodes and arcs, start and stop times for the activities.
  9085. ---------------------------------------------------------------------------
  9086.  
  9087.     NETWORK : PERT_OPS.GRAPH_TYPE renames PERT_NETWORK;
  9088.  
  9089.  
  9090.     function PROB_TIME (TIME, VARIANCE_OF_TIME : FLOAT) return FLOAT is
  9091.  
  9092.     begin
  9093.     if PROBABILITY_FOR_OUTPUT = 0.5 then
  9094.         return TIME;
  9095.     else
  9096.         return MATH_FUNCTIONS.INVERSE_NORMAL_FUNCTION
  9097.               (PROBABILITY_FOR_OUTPUT, TIME, VARIANCE_OF_TIME);
  9098.     end if;
  9099.     end PROB_TIME;
  9100.  
  9101.  
  9102.  
  9103.  
  9104. begin
  9105.  
  9106.     declare
  9107.     NODE_LIST : constant PERT_OPS.NODE_LIST_TYPE :=
  9108.             PERT_OPS.NODES (ON_GRAPH => NETWORK);
  9109.  
  9110.     function "=" (LEFT, RIGHT : PERT_OPS.NODE_TYPE) return BOOLEAN
  9111.                renames PERT_OPS."=";
  9112.     begin
  9113.     for NODE_INDEX in NODE_LIST'RANGE loop
  9114.  
  9115.         PROCESS_THE_NODE:
  9116.         declare
  9117.         EVENT_IMAGE                       : PERT_OPS.NODE_TYPE
  9118.                              renames NODE_LIST
  9119.                                 (NODE_INDEX);
  9120.         EVENT                             : EVENT_TYPE :=
  9121.                             PERT_OPS.VALUE
  9122.                                (EVENT_IMAGE);
  9123.         INDEX_OF_ARC_WITH_HIGH_CRIT_COUNT : NATURAL := 0;
  9124.         begin
  9125.         EVENT.SIM_TIME_OF_EVENT :=
  9126.           EVENT.SUM_OF_TIMES / FLOAT (NUMBER_OF_ITERATIONS);
  9127.         EVENT.VARIANCE :=
  9128.           (EVENT.SUM_OF_SQUARES -
  9129.            FLOAT (NUMBER_OF_ITERATIONS) *
  9130.            (EVENT.SIM_TIME_OF_EVENT ** 2)) /
  9131.           FLOAT (NUMBER_OF_ITERATIONS - 1);
  9132.  
  9133.         -- variance might go negative due to round-off
  9134.         -- for this case variance is reset to 0.0
  9135.  
  9136.         if EVENT.VARIANCE < 0.0 then
  9137.             EVENT.VARIANCE := 0.0;
  9138.         end if;
  9139.  
  9140.         if EVENT_IMAGE /= PERT_OPS.START_NODE (NETWORK) then
  9141.  
  9142.             EVENT.ESTIMATE_TIME_OF_EVENT :=
  9143.               PROB_TIME (EVENT.SIM_TIME_OF_EVENT, EVENT.VARIANCE);
  9144.  
  9145.             HANDLE_INCOMING_ARCS:
  9146.             declare
  9147.             ARC_LIST           : constant PERT_OPS.ARC_LIST_TYPE :=
  9148.                          PERT_OPS.INCOMING_ARCS
  9149.                         (ON_NODE => EVENT_IMAGE);
  9150.             HIGHEST_CRIT_COUNT : FLOAT := 0.0;
  9151.             ACTIVITY           : ACTIVITY_TYPE;
  9152.             TAIL_OF_ACT        : EVENT_TYPE;
  9153.             begin
  9154.             for ARC_INDEX in ARC_LIST'RANGE loop
  9155.                 ACTIVITY := PERT_OPS.VALUE (ARC_LIST (ARC_INDEX));
  9156.                 ACTIVITY.ON_CP_COUNT :=
  9157.                   ACTIVITY.ON_CP_COUNT /
  9158.                   FLOAT (NUMBER_OF_ITERATIONS);
  9159.  
  9160.                 if ACTIVITY.ON_CP_COUNT > HIGHEST_CRIT_COUNT then
  9161.                 INDEX_OF_ARC_WITH_HIGH_CRIT_COUNT := ARC_INDEX;
  9162.                 HIGHEST_CRIT_COUNT := ACTIVITY.ON_CP_COUNT;
  9163.                 end if;
  9164.  
  9165.                 PERT_OPS.ASSIGN (ACTIVITY, ARC_LIST (ARC_INDEX));
  9166.                 TAIL_OF_ACT :=
  9167.                   PERT_OPS.VALUE
  9168.                  (PERT_OPS.TAIL_NODE (ARC_LIST (ARC_INDEX)));
  9169.  
  9170.                 if TAIL_OF_ACT.LONGEST_PATH_TO_EVENT + 1 >
  9171.                    EVENT.LONGEST_PATH_TO_EVENT then
  9172.                 EVENT.LONGEST_PATH_TO_EVENT :=
  9173.                   TAIL_OF_ACT.LONGEST_PATH_TO_EVENT + 1;
  9174.                 end if;
  9175.             end loop;
  9176.  
  9177.             ACTIVITY :=
  9178.               PERT_OPS.VALUE
  9179.                  (ARC_LIST (INDEX_OF_ARC_WITH_HIGH_CRIT_COUNT));
  9180.             ACTIVITY.ESTIMATE_STOP := EVENT.ESTIMATE_TIME_OF_EVENT;
  9181.             PERT_OPS.ASSIGN
  9182.                (ACTIVITY,
  9183.                 ARC_LIST (INDEX_OF_ARC_WITH_HIGH_CRIT_COUNT));
  9184.             end HANDLE_INCOMING_ARCS;
  9185.  
  9186.         else
  9187.  
  9188.             EVENT.ESTIMATE_TIME_OF_EVENT := 0.0;
  9189.  
  9190.         end if;
  9191.  
  9192.         EVENT.MOST_CRIT_INBOUND_ARC :=
  9193.           INDEX_OF_ARC_WITH_HIGH_CRIT_COUNT;
  9194.  
  9195.         if EVENT_IMAGE /= PERT_OPS.END_NODE (OF_GRAPH => NETWORK) then
  9196.  
  9197.             HANDLE_OUTGOING_ARCS:
  9198.             declare
  9199.             ARC_LIST         : constant PERT_OPS.ARC_LIST_TYPE :=
  9200.                        PERT_OPS.OUTGOING_ARCS
  9201.                           (ON_NODE => EVENT_IMAGE);
  9202.             ACTIVITY         : ACTIVITY_TYPE;
  9203.             TIME             : FLOAT;
  9204.             VARIANCE_OF_TIME : FLOAT;
  9205.             begin
  9206.             for ARC_INDEX in ARC_LIST'RANGE loop
  9207.                 ACTIVITY := PERT_OPS.VALUE (ARC_LIST (ARC_INDEX));
  9208.                 ACTIVITY.DURATION_TIME :=
  9209.                   (ACTIVITY.OPTIMISTIC_TIME +
  9210.                    ACTIVITY.MOST_PROBABLE_TIME +
  9211.                    ACTIVITY.PESSIMISTIC_TIME) / 3.0;
  9212.  
  9213.                 ACTIVITY.ESTIMATE_START :=
  9214.                   EVENT.ESTIMATE_TIME_OF_EVENT;
  9215.  
  9216.                 TIME := EVENT.SIM_TIME_OF_EVENT +
  9217.                     ACTIVITY.DURATION_TIME;
  9218.                 VARIANCE_OF_TIME :=
  9219.                   EVENT.VARIANCE +
  9220.                   (((ACTIVITY.PESSIMISTIC_TIME -
  9221.                  ACTIVITY.OPTIMISTIC_TIME) ** 2 +
  9222.                 (ACTIVITY.MOST_PROBABLE_TIME -
  9223.                  ACTIVITY.OPTIMISTIC_TIME) *
  9224.                 (ACTIVITY.MOST_PROBABLE_TIME -
  9225.                  ACTIVITY.PESSIMISTIC_TIME)) / 18.0);
  9226.                 ACTIVITY.ESTIMATE_STOP :=
  9227.                   PROB_TIME (TIME, VARIANCE_OF_TIME);
  9228.  
  9229.                 PERT_OPS.ASSIGN (ACTIVITY, ARC_LIST (ARC_INDEX));
  9230.             end loop;
  9231.             end HANDLE_OUTGOING_ARCS;
  9232.  
  9233.         end if;
  9234.  
  9235.         PERT_OPS.ASSIGN (EVENT, EVENT_IMAGE);
  9236.         end PROCESS_THE_NODE;
  9237.  
  9238.     end loop;
  9239.  
  9240.     -----------------------------------------------------------
  9241.     -- Figure the Node and Activity Critical Path Index. 
  9242.     -- Go through the nodes in reverse order.
  9243.     -----------------------------------------------------------
  9244.     for NODE_INDEX in reverse NODE_LIST'RANGE loop
  9245.  
  9246.         FIGURE_CRITS_FOR_EACH_NODE:
  9247.         declare
  9248.         EVENT_IMAGE : PERT_OPS.NODE_TYPE renames NODE_LIST (NODE_INDEX);
  9249.         EVENT       : EVENT_TYPE := PERT_OPS.VALUE (EVENT_IMAGE);
  9250.         begin
  9251.         if EVENT_IMAGE = PERT_OPS.END_NODE (NETWORK) then
  9252.             EVENT.CRIT_PATH_INDEX := 1.0;
  9253.         end if;
  9254.  
  9255.         if EVENT_IMAGE /= PERT_OPS.START_NODE (NETWORK) then
  9256.             SET_CRIT_INDEX_FOR_EACH_INCOMING_ARC:
  9257.             declare
  9258.             ARC_LIST : constant PERT_OPS.ARC_LIST_TYPE :=
  9259.                    PERT_OPS.INCOMING_ARCS
  9260.                       (ON_NODE => EVENT_IMAGE);
  9261.             ACTIVITY : ACTIVITY_TYPE;
  9262.             begin
  9263.             for ARC_INDEX in ARC_LIST'RANGE loop
  9264.                 ACTIVITY := PERT_OPS.VALUE (ARC_LIST (ARC_INDEX));
  9265.                 ACTIVITY.ON_CP_COUNT :=
  9266.                   ACTIVITY.ON_CP_COUNT * EVENT.CRIT_PATH_INDEX;
  9267.  
  9268.                 GET_TAIL_EVENT_NODE:
  9269.                 declare
  9270.                 TAIL_IMAGE : PERT_OPS.NODE_TYPE :=
  9271.                          PERT_OPS.TAIL_NODE
  9272.                         (ARC_LIST (ARC_INDEX));
  9273.                 TAIL       : EVENT_TYPE :=
  9274.                          PERT_OPS.VALUE (TAIL_IMAGE);
  9275.                 begin
  9276.                 TAIL.CRIT_PATH_INDEX :=
  9277.                   TAIL.CRIT_PATH_INDEX + ACTIVITY.ON_CP_COUNT;
  9278.                 PERT_OPS.ASSIGN (TAIL, TAIL_IMAGE);
  9279.                 end GET_TAIL_EVENT_NODE;
  9280.  
  9281.                 PERT_OPS.ASSIGN (ACTIVITY, ARC_LIST (ARC_INDEX));
  9282.             end loop;
  9283.             end SET_CRIT_INDEX_FOR_EACH_INCOMING_ARC;
  9284.  
  9285.             ----------------------------------------------------------
  9286.             -- for critical arc into the given node, bump up the
  9287.             -- est. stop of the arc to be est. time of event of the node
  9288.             ----------------------------------------------------------
  9289.             declare
  9290.             ACTIVITY : ACTIVITY_TYPE;
  9291.             begin
  9292.             if EVENT.MOST_CRIT_INBOUND_ARC /= 0 then
  9293.                 ACTIVITY :=
  9294.                   PERT_OPS.VALUE
  9295.                  (EVENT_IMAGE.INCOMING_ARCS
  9296.                      (EVENT.MOST_CRIT_INBOUND_ARC));
  9297.  
  9298.                 ACTIVITY.ESTIMATE_STOP :=
  9299.                   EVENT.ESTIMATE_TIME_OF_EVENT;
  9300.                 PERT_OPS.ASSIGN
  9301.                    (ACTIVITY,
  9302.                 EVENT_IMAGE.INCOMING_ARCS
  9303.                    (EVENT.MOST_CRIT_INBOUND_ARC));
  9304.             end if;
  9305.             end;
  9306.  
  9307.         end if;
  9308.  
  9309.         PERT_OPS.ASSIGN (EVENT, EVENT_IMAGE);
  9310.         end FIGURE_CRITS_FOR_EACH_NODE;
  9311.  
  9312.     end loop;
  9313.  
  9314.     ---------------------------------------------------------------------
  9315.     -- Loop through the nodes of the graph in reverse order to figure the
  9316.     -- deterministic late time of each event. This is the latest time the
  9317.     -- event can happen and still not affect the completion date of the 
  9318.     -- whole project.
  9319.     ---------------------------------------------------------------------
  9320.     for NODE_INDEX in reverse NODE_LIST'RANGE loop
  9321.         FIGURE_DET_LATE_TIMES_FOR_EVENTS:
  9322.         declare
  9323.         EVENT_IMAGE : PERT_OPS.NODE_TYPE renames NODE_LIST (NODE_INDEX);
  9324.         EVENT       : EVENT_TYPE := PERT_OPS.VALUE (EVENT_IMAGE);
  9325.         begin
  9326.         if EVENT_IMAGE = PERT_OPS.END_NODE (NETWORK) then
  9327.             EVENT.DET_LATE_TIME_OF_EVENT := EVENT.DET_TIME_OF_EVENT;
  9328.         else
  9329.             FIND_LATEST_SAFE_TIME_FOR_EVENT:
  9330.             declare
  9331.             ARC_LIST : constant PERT_OPS.ARC_LIST_TYPE :=
  9332.                    PERT_OPS.OUTGOING_ARCS
  9333.                       (ON_NODE => EVENT_IMAGE);
  9334.             ACTIVITY : ACTIVITY_TYPE;
  9335.             begin
  9336.             for ARC_INDEX in ARC_LIST'RANGE loop
  9337.                 ACTIVITY := PERT_OPS.VALUE (ARC_LIST (ARC_INDEX));
  9338.  
  9339.                 GET_HEAD_EVENT:
  9340.                 declare
  9341.                 HEAD_IMAGE : PERT_OPS.NODE_TYPE :=
  9342.                          PERT_OPS.HEAD_NODE
  9343.                         (ARC_LIST (ARC_INDEX));
  9344.                 HEAD       : EVENT_TYPE :=
  9345.                          PERT_OPS.VALUE (HEAD_IMAGE);
  9346.                 begin
  9347.                 if (EVENT.DET_LATE_TIME_OF_EVENT = -1.0) or
  9348.                    (HEAD.DET_LATE_TIME_OF_EVENT -
  9349.                     ACTIVITY.DURATION_TIME <
  9350.                     EVENT.DET_LATE_TIME_OF_EVENT) then
  9351.                     EVENT.DET_LATE_TIME_OF_EVENT :=
  9352.                       HEAD.DET_LATE_TIME_OF_EVENT -
  9353.                       ACTIVITY.DURATION_TIME;
  9354.                 end if;
  9355.                 end GET_HEAD_EVENT;
  9356.             end loop;
  9357.             end FIND_LATEST_SAFE_TIME_FOR_EVENT;
  9358.         end if;
  9359.  
  9360.         PERT_OPS.ASSIGN (EVENT, EVENT_IMAGE);
  9361.  
  9362.         end FIGURE_DET_LATE_TIMES_FOR_EVENTS;
  9363.     end loop;
  9364.  
  9365.  
  9366.     FIGURE_CONFIDENCE_INTERVAL:
  9367.     declare
  9368.         EVENT_IMAGE : PERT_OPS.NODE_TYPE renames NODE_LIST (NODE_LIST'LAST);
  9369.         EVENT       : EVENT_TYPE := PERT_OPS.VALUE (EVENT_IMAGE);
  9370.  
  9371.         function "**" (X, Y : FLOAT) return FLOAT
  9372.                 renames MATH_FUNCTIONS."**";
  9373.     begin
  9374.         CONFIDENCE_INTERVAL :=
  9375.           1.645 * (EVENT.VARIANCE ** 0.5) /
  9376.           ((FLOAT (NUMBER_OF_ITERATIONS)) ** 0.5);
  9377.     end FIGURE_CONFIDENCE_INTERVAL;
  9378.  
  9379.     end;
  9380.  
  9381. exception
  9382.     when others => 
  9383.     FATAL (UNIT => "Schedule Tool - Unit named " & "[PERT.OVERALL_CALCS]");
  9384.  
  9385.  
  9386. end OVERALL_CALCS;
  9387.  
  9388.  
  9389.  
  9390.  
  9391.  
  9392. with MATH_FUNCTIONS,
  9393.      CALENDAR,
  9394.      TEXT_IO,
  9395.      SCREEN_IO,
  9396.      DATE_AND_TIME,
  9397.      STRING_UTILITIES;
  9398.  
  9399. separate (SCHEDULE.PERT)
  9400. procedure OUTPUT_VALUES is
  9401. ------------------------------------------------------------------
  9402. -- Author: K. Lamarche and T. C. Bryan
  9403. -- Source:     Division Software Technology and Support
  9404. --             Western Development Laboratories
  9405. --             Ford Aerospace & Communications Corporation
  9406. --             ATTN:  Ada Tools Group
  9407. -- Date  : May 1985
  9408. -- Summary:
  9409. -- This procedure is used to output the reports of the SIMPERT run.
  9410. -- A separate procedure is used to print every report.
  9411. ------------------------------------------------------------------
  9412.  
  9413.     subtype INT_NUM is INTEGER range 0 .. 1000000;
  9414.  
  9415.     package I_NUMBER is new TEXT_IO.INTEGER_IO (INT_NUM);
  9416.  
  9417.     subtype FLOAT_NUM is FLOAT range 0.0 .. 100_000.0;
  9418.  
  9419.     package F_NUMBER is new TEXT_IO.FLOAT_IO (FLOAT_NUM);
  9420.  
  9421.     --------------------------------------------------------------
  9422.     -- names of various reports that are outputted by SIMPERT run
  9423.     --------------------------------------------------------------
  9424.     THE_SUMMARY_REPORT_NAME  : constant STRING :=
  9425.                    FILE_HANDLER.OUTFILE_ARRAY (FILE_HANDLER.TOUT)
  9426.                 .VALUE;
  9427.  
  9428.     THE_ACTIVITY_REPORT_NAME : constant STRING :=
  9429.                    FILE_HANDLER.OUTFILE_ARRAY (FILE_HANDLER.ACT)
  9430.                 .VALUE;
  9431.  
  9432.     THE_NODE_REPORT_NAME     : constant STRING :=
  9433.                    FILE_HANDLER.OUTFILE_ARRAY (FILE_HANDLER.NODE)
  9434.                 .VALUE;
  9435.  
  9436.     THE_MANPOWER_REPORT_NAME : constant STRING :=
  9437.                    FILE_HANDLER.OUTFILE_ARRAY (FILE_HANDLER.MAN)
  9438.                 .VALUE;
  9439.  
  9440.     THE_GANTT_REPORT_NAME    : constant STRING :=
  9441.                    FILE_HANDLER.OUTFILE_ARRAY (FILE_HANDLER.BARIN)
  9442.                 .VALUE;
  9443.  
  9444.     TIME_NOW                 : CALENDAR.TIME := CALENDAR.CLOCK;
  9445.     DATE_SPEC_NOW            : DATE_AND_TIME.CALENDAR_TYPE :=
  9446.                    (DAY   => CALENDAR.DAY (TIME_NOW),
  9447.                 MONTH => CALENDAR.MONTH (TIME_NOW),
  9448.                 YEAR  => CALENDAR.YEAR (TIME_NOW) - 1900);
  9449.     JULIAN_DATE_NOW          : DATE_AND_TIME.JULIAN_TYPE :=
  9450.                    DATE_AND_TIME.JULIAN_DATE (DATE_SPEC_NOW);
  9451.  
  9452.     BIG_ACTIVITY_LIST        : PERT_OPS.ARC_LIST_TYPE (ACTIVITY_ID_TYPE);
  9453.     BIG_LIST_INDEX           : NATURAL := 0;
  9454.     TOTAL_FREE_SLACK         : FLOAT := 0.0;
  9455.     CRIT_PATH_HEAD_NODE      : INTEGER :=
  9456.                    SCREEN_IO.RETURNED_INTEGER
  9457.                   (PROMPT      =>
  9458.                      ASCII.FF & ASCII.LF & ASCII.CR &
  9459.                      "ENTER the last event for the " &
  9460.                      "critical path to be returned  ",
  9461.                    DEFAULT     =>
  9462.                      PERT_OPS.VALUE
  9463.                     (PERT_OPS.END_NODE
  9464.                         (OF_GRAPH => NETWORK)).EVENT_ID,
  9465.                    USE_DEFAULT => TRUE);
  9466.  
  9467.     MAX_NUM_HOLIDAYS         : constant := 200;
  9468.  
  9469.     type HOLIDAY_ARRAY is array (1 .. MAX_NUM_HOLIDAYS)
  9470.                  of DATE_AND_TIME.JULIAN_TYPE;
  9471.  
  9472.     HOLIDAYS            : HOLIDAY_ARRAY;
  9473.     ACTUAL_NUM_HOLIDAYS : INTEGER := 0;
  9474.  
  9475.     OUTPUT_REPORT_TITLE : constant STRING :=
  9476.               FILE_HANDLER.VERIFY_LABEL
  9477.                  (WITH_PROMPT     =>
  9478.                 "ENTER a Title for the output reports." &
  9479.                 "  [60 characters or less]",
  9480.                   STRING_TYPE     => "Title",
  9481.                   LENGTH_OF_LABEL => 60);
  9482.  
  9483.  
  9484.  
  9485.     function "**" (X, Y : FLOAT) return FLOAT renames MATH_FUNCTIONS."**";
  9486.  
  9487.  
  9488.  
  9489.     -------------------------------------------------------
  9490.     -- convert a julian date into a 9 character field
  9491.     -- representing a date.  The resulted date is given in the
  9492.     -- format dd/name_month/yy where:
  9493.     -- dd is the day, name_month is the first 3 characters
  9494.     -- of a month name, and yy is the last two digits of the
  9495.     -- 4 digit year.
  9496.     -- e.g. 14 Mar 85, if dd is a one non-blank character then
  9497.     -- dd contains one blank and following by a digit.
  9498.     -- 
  9499.     -- Author: T. C. Bryan
  9500.     -- Source:     Division Software Technology and Support
  9501.     --             Western Development Laboratories
  9502.     --             Ford Aerospace & Communications Corporation
  9503.     --             ATTN:  Ada Tools Group
  9504.     -- Library use : date_and_time.
  9505.     -- Date:  17 May 85
  9506.     -------------------------------------------------------
  9507.     function CONVERT_TO_NORMAL_DATE
  9508.             (THE_JULIAN_IS : DATE_AND_TIME.JULIAN_TYPE) return STRING is
  9509.  
  9510.     DATE_SPEC : DATE_AND_TIME.CALENDAR_TYPE :=
  9511.             DATE_AND_TIME.CALENDAR_DATE (THE_JULIAN_IS);
  9512.     WANT_DATE : constant STRING :=
  9513.             (DATE_AND_TIME.DATE
  9514.             (DATE_SPEC.DAY, DATE_SPEC.MONTH,
  9515.              DATE_SPEC.YEAR + 1900));
  9516.     begin
  9517.     if WANT_DATE'LENGTH = 11 then
  9518.         return (WANT_DATE (1 .. 2) & " " & WANT_DATE (4 .. 6) & " " &
  9519.             WANT_DATE (10 .. 11));
  9520.     else
  9521.         return (WANT_DATE (2 .. 3) & " " & WANT_DATE (5 .. 7) & " " &
  9522.             WANT_DATE (11 .. 12));
  9523.     end if;
  9524.     end CONVERT_TO_NORMAL_DATE;
  9525.  
  9526.  
  9527.  
  9528.  
  9529.     ------------------------------------------------------------
  9530.     -- write a common header report for all reports derived
  9531.     -- from SIMPERT run.  Handle different page width with default
  9532.     -- set for 132 column-page.  Report title, if any, will be
  9533.     -- centered according to page width inputted.
  9534.     ------------------------------------------------------------
  9535.     procedure WRITE_HEADER_REPORT
  9536.          (TO_FILE       : TEXT_IO.FILE_TYPE :=
  9537.                   TEXT_IO.CURRENT_OUTPUT;
  9538.           FORM_NAME     : STRING := " ";
  9539.           PAGE_WIDTH    : INTEGER := 132;
  9540.           TITLE         : STRING :=
  9541.                   STRING_UTILITIES
  9542.                    .REMOVE_LEADING_AND_TRAILING_BLANKS
  9543.                      (OUTPUT_REPORT_TITLE);
  9544.           ESTIMATE      : STRING :=
  9545.                   STRING_UTILITIES
  9546.                    .REMOVE_LEADING_AND_TRAILING_BLANKS
  9547.                      (PERT_FILE);
  9548.           PROBABILITY   : STRING :=
  9549.                   INTEGER'IMAGE
  9550.                     (INTEGER (100.0 *
  9551.                           PROBABILITY_FOR_OUTPUT)) & "%";
  9552.           ITERATIONS    : INTEGER := NUMBER_OF_ITERATIONS;
  9553.           INTERVAL_IS   : FLOAT := CONFIDENCE_INTERVAL;
  9554.           TODAY_IS      : DATE_AND_TIME.JULIAN_TYPE :=
  9555.                   JULIAN_DATE_NOW;
  9556.           TIME_IS       : STRING := DATE_AND_TIME.CURRENT_TIME;
  9557.           START_DATE_IS : DATE_AND_TIME.JULIAN_TYPE :=
  9558.                   JULIAN_START_DATE) is
  9559.  
  9560.     CENTER_HEADING              : INTEGER := FORM_NAME'LENGTH;
  9561.     RIGHT_MARGIN                : constant INTEGER :=
  9562.                       (PAGE_WIDTH - CENTER_HEADING) / 2;
  9563.     LEFT_MARGIN                 : constant INTEGER := PAGE_WIDTH - 31;
  9564.     COLON_INDENT                : TEXT_IO.COUNT := 18;
  9565.  
  9566.     RIGHT_MARGIN_FOR_FORM_TITLE : TEXT_IO.COUNT :=
  9567.                       TEXT_IO.COUNT (RIGHT_MARGIN);
  9568.     LEFT_TEXT_MARGIN            : TEXT_IO.COUNT :=
  9569.                       TEXT_IO.COUNT (LEFT_MARGIN);
  9570.  
  9571.     begin
  9572.  
  9573.     TEXT_IO.NEW_PAGE (TO_FILE);
  9574.     TEXT_IO.NEW_LINE (TO_FILE, 5);
  9575.     TEXT_IO.SET_COL (TO_FILE, TO => RIGHT_MARGIN_FOR_FORM_TITLE);
  9576.     TEXT_IO.PUT_LINE (TO_FILE, FORM_NAME);
  9577.     TEXT_IO.NEW_LINE (TO_FILE, 2);
  9578.  
  9579.     TEXT_IO.PUT (TO_FILE, "SIMPERT Version 1.0");
  9580.     TEXT_IO.SET_COL (TO_FILE, TO => LEFT_TEXT_MARGIN);
  9581.     TEXT_IO.PUT_LINE (TO_FILE,
  9582.               "        Date Today:  " &
  9583.               CONVERT_TO_NORMAL_DATE (TODAY_IS));
  9584.  
  9585.     TEXT_IO.SET_COL (TO_FILE, TO => LEFT_TEXT_MARGIN);
  9586.     TEXT_IO.PUT_LINE (TO_FILE, "              Time: " & TIME_IS);
  9587.  
  9588.     TEXT_IO.PUT (TO_FILE, "Title");
  9589.     TEXT_IO.SET_COL (TO_FILE, TO => COLON_INDENT);
  9590.     TEXT_IO.PUT_LINE (TO_FILE, ":  " & TITLE);
  9591.  
  9592.     TEXT_IO.NEW_LINE (TO_FILE);
  9593.     TEXT_IO.PUT (TO_FILE, "Estimate file");
  9594.     TEXT_IO.SET_COL (TO_FILE, TO => COLON_INDENT);
  9595.     TEXT_IO.PUT (TO_FILE, ":  " & ESTIMATE);
  9596.     TEXT_IO.SET_COL (TO_FILE, TO => LEFT_TEXT_MARGIN);
  9597.     TEXT_IO.PUT_LINE (TO_FILE,
  9598.               "Date Project Start:  " &
  9599.               CONVERT_TO_NORMAL_DATE (START_DATE_IS));
  9600.  
  9601.     TEXT_IO.PUT (TO_FILE, "Probability");
  9602.     TEXT_IO.SET_COL (TO_FILE, TO => COLON_INDENT);
  9603.     TEXT_IO.PUT_LINE (TO_FILE, ":  " & PROBABILITY);
  9604.  
  9605.     TEXT_IO.PUT (TO_FILE, "Iterations");
  9606.     TEXT_IO.SET_COL (TO_FILE, TO => COLON_INDENT);
  9607.     TEXT_IO.PUT (TO_FILE, ":  ");
  9608.     I_NUMBER.PUT (TO_FILE, ITERATIONS, WIDTH => 4);
  9609.     TEXT_IO.NEW_LINE (TO_FILE);
  9610.  
  9611.     TEXT_IO.PUT (TO_FILE, "Conf Interval");
  9612.     TEXT_IO.SET_COL (TO_FILE, TO => COLON_INDENT);
  9613.     TEXT_IO.PUT (TO_FILE, ":  ");
  9614.  
  9615.     if (INTERVAL_IS <= 0.09) then
  9616.         TEXT_IO.PUT (TO_FILE, " 0.0");
  9617.     else
  9618.         F_NUMBER.PUT (TO_FILE, INTERVAL_IS, EXP => 0, FORE => 2, AFT => 1);
  9619.     end if;
  9620.  
  9621.     TEXT_IO.NEW_LINE (TO_FILE, 3);
  9622.     end WRITE_HEADER_REPORT;
  9623.  
  9624.  
  9625.  
  9626.     -----------------------------------------------------------------
  9627.     -- create a list of all activities excluding "dummy" activities
  9628.     -----------------------------------------------------------------
  9629.     procedure ADD_NON_DUMMY_ACTIVITY (ARC : PERT_OPS.ARC_TYPE) is
  9630.     begin
  9631.     if STRING_UTILITIES.LOWER_TO_UPPER
  9632.           (STRING_UTILITIES.REMOVE_LEADING_AND_TRAILING_BLANKS
  9633.           (PERT_OPS.VALUE (ARC).NAME (11 .. 42))) /= "DUMMY" then
  9634.         BIG_LIST_INDEX := BIG_LIST_INDEX + 1;
  9635.         BIG_ACTIVITY_LIST (BIG_LIST_INDEX) := ARC;
  9636.     end if;
  9637.     end ADD_NON_DUMMY_ACTIVITY;
  9638.  
  9639.  
  9640.  
  9641.     -----------------------------------------------------------------
  9642.     -- return a label for a unit of number of days or weeks
  9643.     -----------------------------------------------------------------
  9644.     function REQUESTED_UNIT_CODE return STRING is
  9645.     begin
  9646.     if TIME_UNIT_CODE = W then
  9647.         return ("Weeks");
  9648.     else
  9649.         return ("Days");
  9650.     end if;
  9651.     end REQUESTED_UNIT_CODE;
  9652.  
  9653.  
  9654.  
  9655.     ---------------------------------------------------
  9656.     -- compute the actual unit required in whole number
  9657.     ---------------------------------------------------
  9658.     function TO_DAYS (TIME_UNIT : INTEGER) return INTEGER is
  9659.     begin
  9660.     if TIME_UNIT_CODE = W then
  9661.         return WORKDAYS_PER_WEEK * TIME_UNIT;
  9662.     else
  9663.         return TIME_UNIT;
  9664.     end if;
  9665.     end TO_DAYS;
  9666.  
  9667.  
  9668. -------------------------------------------------------------------------
  9669. --  Procedure used to read the holidays file into an array. The array will
  9670. --  be used by subsequent functions to determine real dates from project
  9671. --  time offsets.
  9672. -------------------------------------------------------------------------
  9673.     procedure READ_HOLIDAY_FILE is
  9674.  
  9675.     HOLI         : DATE_AND_TIME.CALENDAR_TYPE;
  9676.     HOLIDAY_FILE : TEXT_IO.FILE_TYPE;
  9677.  
  9678.     begin
  9679.  
  9680.     TEXT_IO.OPEN (FILE => HOLIDAY_FILE,
  9681.               MODE => TEXT_IO.IN_FILE,
  9682.               NAME =>
  9683.             STRING_UTILITIES.REMOVE_LEADING_AND_TRAILING_BLANKS
  9684.                (FILE_OF_HOLIDAYS));
  9685.  
  9686.     while not TEXT_IO.END_OF_FILE (HOLIDAY_FILE) loop
  9687.         I_NUMBER.GET (HOLIDAY_FILE, HOLI.DAY, WIDTH => 2);
  9688.         TEXT_IO.SET_COL (HOLIDAY_FILE, 4);
  9689.         I_NUMBER.GET (HOLIDAY_FILE, HOLI.MONTH, WIDTH => 2);
  9690.         TEXT_IO.SET_COL (HOLIDAY_FILE, 7);
  9691.         I_NUMBER.GET (HOLIDAY_FILE, HOLI.YEAR, WIDTH => 2);
  9692.         ACTUAL_NUM_HOLIDAYS := ACTUAL_NUM_HOLIDAYS + 1;
  9693.  
  9694.         if ACTUAL_NUM_HOLIDAYS > MAX_NUM_HOLIDAYS then
  9695.         ACTUAL_NUM_HOLIDAYS := MAX_NUM_HOLIDAYS;
  9696.         exit;
  9697.         end if;
  9698.  
  9699.         HOLIDAYS (ACTUAL_NUM_HOLIDAYS) := DATE_AND_TIME.JULIAN_DATE (HOLI);
  9700.         TEXT_IO.SKIP_LINE (HOLIDAY_FILE);
  9701.     end loop;
  9702.  
  9703.  
  9704.     exception
  9705.     when TEXT_IO.DATA_ERROR => 
  9706.  
  9707.         TEXT_IO.NEW_LINE;
  9708.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  9709.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  9710.         TEXT_IO.PUT_LINE
  9711.            ("Holiday information file contains unexpected data");
  9712.         TEXT_IO.CLOSE (HOLIDAY_FILE);
  9713.             PRESS_RETURN_TO_CONTINUE;
  9714.  
  9715.     when TEXT_IO.END_ERROR => 
  9716.         TEXT_IO.CLOSE (HOLIDAY_FILE);
  9717.  
  9718.     end READ_HOLIDAY_FILE;
  9719.  
  9720.  
  9721.  
  9722.  
  9723. -------------------------------------------------------------------------
  9724. --  Compute number of working days between start and end inclusive.
  9725. --  This function assumes that a global variable HOLIDAYS is an array
  9726. --    which stores the julians of the holidays in increasing order,
  9727. --    and that the global variable ACTUAL_NUM_HOLIDAYS is an exact count
  9728. --    of the number of julian holidays stored.  Ie, HOLIDAYS is searched
  9729. --    from 1..ACTUAL_NUM_HOLIDAYS.
  9730. --  This function also assumes that a global variable WORKDAYS_PER_WEEK
  9731. --    is available, with a value of 5, 6, or 7.
  9732. -------------------------------------------------------------------------
  9733.     function WORKDAYS_BETWEEN (START  : DATE_AND_TIME.JULIAN_TYPE;
  9734.                    FINISH : DATE_AND_TIME.JULIAN_TYPE)
  9735.                     return DATE_AND_TIME.JULIAN_TYPE is
  9736.  
  9737.     ANSWER : DATE_AND_TIME.JULIAN_TYPE;
  9738.     WPW    : INTEGER renames WORKDAYS_PER_WEEK;
  9739.  
  9740.  
  9741.     function NPM (JULIAN_DAY : DATE_AND_TIME.JULIAN_TYPE)
  9742.                return DATE_AND_TIME.JULIAN_TYPE
  9743.                renames DATE_AND_TIME.NEAREST_PRECEDING_MONDAY;
  9744.  
  9745.  
  9746.  
  9747.     ------------------------------------------------------------
  9748.     -- return number of holidays between LOW and HIGH inclusive.
  9749.     ------------------------------------------------------------
  9750.     function NUMBER_HOLIDAYS (LOW, HIGH : DATE_AND_TIME.JULIAN_TYPE)
  9751.                    return INTEGER is
  9752.         COUNT : INTEGER := 0;
  9753.     begin
  9754.         for I in 1 .. ACTUAL_NUM_HOLIDAYS loop
  9755.         if HOLIDAYS (I) in LOW .. HIGH then
  9756.             COUNT := COUNT + 1;
  9757.         end if;
  9758.         end loop;
  9759.  
  9760.         return COUNT;
  9761.     end NUMBER_HOLIDAYS;
  9762.  
  9763.  
  9764.     begin
  9765.     if FINISH < START then
  9766.         return 0;
  9767.     end if;
  9768.  
  9769.     ANSWER := FINISH - START + 1; --begin with no. of calendar days
  9770.     ANSWER := ANSWER - ((NPM (FINISH) - NPM (START)) / 7) * (7 - WPW);
  9771.     --approx number of weekends have now been subtracted.
  9772.     if ((FINISH rem 7) = 6 and WPW < 6) then
  9773.         ANSWER := ANSWER - 1;
  9774.     end if;
  9775.     -- if FINISH is a Saturday, it has to be subtracted
  9776.     -- separately, which was just done.
  9777.     if ((START rem 7) = 0 and WPW < 7) then
  9778.         ANSWER := ANSWER - 1;
  9779.     end if;
  9780.     -- if START is a Sunday, then it has to be subtracted
  9781.     -- separately, since npm(sunday) returns following mon.
  9782.     ANSWER := ANSWER - NUMBER_HOLIDAYS (START, FINISH);
  9783.     return ANSWER;
  9784.     end WORKDAYS_BETWEEN;
  9785.  
  9786.  
  9787.  
  9788.     -----------------------------------------------
  9789.     -- return the Nth working day at or past J.
  9790.     -----------------------------------------------
  9791.     function FIND_PROPER_DATE (J : DATE_AND_TIME.JULIAN_TYPE;
  9792.                    N : POSITIVE) return DATE_AND_TIME.JULIAN_TYPE is
  9793.  
  9794.     GUESS : DATE_AND_TIME.JULIAN_TYPE; --Will contain returned value.
  9795.  
  9796.  
  9797.  
  9798.     -------------------------------------------------------
  9799.     -- figure out if the day is one of the recorded holiday
  9800.     -------------------------------------------------------
  9801.     function IS_HOLIDAY (DAY : DATE_AND_TIME.JULIAN_TYPE) return BOOLEAN is
  9802.     begin
  9803.         for I in 1 .. ACTUAL_NUM_HOLIDAYS loop
  9804.         if HOLIDAYS (I) = DAY then
  9805.             return TRUE;
  9806.  
  9807.         elsif HOLIDAYS (I) > DAY then
  9808.             return FALSE;
  9809.         end if;
  9810.         end loop;
  9811.  
  9812.         return FALSE; --DAY is beyond all recorded holidays
  9813.     end IS_HOLIDAY;
  9814.  
  9815.  
  9816.  
  9817.     -------------------------------------------------------
  9818.     -- 
  9819.     -------------------------------------------------------
  9820.     function PROPER_DATE (J : DATE_AND_TIME.JULIAN_TYPE;
  9821.                   N : POSITIVE) return DATE_AND_TIME.JULIAN_TYPE is
  9822.  
  9823.         N1 : NATURAL :=
  9824.          N - 1 + (N / WORKDAYS_PER_WEEK) * (7 - WORKDAYS_PER_WEEK);
  9825.         -- N1 is a guess as to be the returned value
  9826.         -- of this function, based on number of weekends.
  9827.         N2 : NATURAL := WORKDAYS_BETWEEN (J, J + N1);
  9828.     begin
  9829.         if N2 >= N then
  9830.         return J + N1;
  9831.         else
  9832.         return PROPER_DATE (J + N1 + 1, N - N2);
  9833.         end if;
  9834.     end PROPER_DATE;
  9835.  
  9836.  
  9837.  
  9838.     begin
  9839.     GUESS := PROPER_DATE (J, N);
  9840.     -- GUESS may have returned a holiday or weekend.
  9841.     -- Return first preceding workday.
  9842.     loop
  9843.         if (GUESS rem 7 = 6) and WORKDAYS_PER_WEEK < 6 then
  9844.         GUESS := GUESS - 1;      -- Sat., so try preceding day.
  9845.         elsif (GUESS rem 7 = 0) and WORKDAYS_PER_WEEK < 7 then
  9846.         GUESS := GUESS - 2;      -- Sun, so try preceding friday.
  9847.         elsif IS_HOLIDAY (GUESS) then
  9848.         GUESS := GUESS - 1;      -- holiday, so try preceding day.
  9849.         else
  9850.         exit;
  9851.         end if;
  9852.     end loop;
  9853.  
  9854.     return GUESS;
  9855.     end FIND_PROPER_DATE;
  9856.  
  9857.  
  9858.     function GET_NEW_DATE (WITH_YESNO_PROMPT : STRING;
  9859.                PASSED_DATE       : DATE_AND_TIME.JULIAN_TYPE;
  9860.                AND_TEXT_PROMPT   : STRING)
  9861.                 return DATE_AND_TIME.JULIAN_TYPE is
  9862.  
  9863.  
  9864.     type ANSWER is (Y, N);
  9865.  
  9866.     function RETURNED_ANSWER is new SCREEN_IO.RETURNED_ENUMERATION (ANSWER);
  9867.  
  9868.     DATE_SPEC : DATE_AND_TIME.CALENDAR_TYPE;
  9869.  
  9870.  
  9871.  
  9872.     function USE_DATE_STRING (DATE_STRING : STRING) return BOOLEAN is
  9873.         LAST_INDEX : POSITIVE;
  9874.         DATE_INFO  : array (1 .. 3) of INTEGER;
  9875.         EXCEED_MAX_YEAR : exception;
  9876.     begin
  9877.         if ( INTEGER'VALUE( DATE_STRING (7..8) ) ) not in 80..MAX_YEAR then
  9878.         raise EXCEED_MAX_YEAR;
  9879.         end if;
  9880.         for I in 1 .. 3 loop
  9881.         I_NUMBER.GET (FROM => DATE_STRING ((3 * I - 2) .. (3 * I - 1)),
  9882.                   ITEM => DATE_INFO (I),
  9883.                   LAST => LAST_INDEX);
  9884.         end loop;
  9885.  
  9886.         DATE_SPEC := (DAY   => DATE_INFO (1),
  9887.                   MONTH => DATE_INFO (2),
  9888.                   YEAR  => DATE_INFO (3));
  9889.         return TRUE;
  9890.     exception
  9891.         when EXCEED_MAX_YEAR | CONSTRAINT_ERROR | TEXT_IO.DATA_ERROR => 
  9892.         return FALSE;
  9893.     end USE_DATE_STRING;
  9894.  
  9895.     begin
  9896.     if RETURNED_ANSWER
  9897.           (PROMPT      => ASCII.LF & ASCII.CR & WITH_YESNO_PROMPT,
  9898.            DEFAULT     => N,
  9899.            USE_DEFAULT => TRUE,
  9900.            ERROR_TEXT  =>
  9901.          ASCII.LF & ASCII.CR &
  9902.          "INPUT ERROR:  Please ENTER  either [y] or [n] ...") = Y then
  9903.  
  9904.         while not USE_DATE_STRING
  9905.              (SCREEN_IO.RETURNED_STRING
  9906.              (PROMPT  => ASCII.LF & ASCII.CR & AND_TEXT_PROMPT &
  9907.                      " [in form dd/mm/yy] -->  ",
  9908.               CONFIRM => FALSE)) loop
  9909.  
  9910.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  9911.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  9912.         TEXT_IO.PUT_LINE ("Date needed must be in form [dd/mm/yy].");
  9913.  
  9914.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  9915.         TEXT_IO.PUT_LINE
  9916.            ("where [dd] is between 01..31 days, [mm] 01..12 months,");
  9917.  
  9918.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  9919.         TEXT_IO.PUT ("and [yy] 80..  " & 
  9920.             INTEGER'IMAGE (MAX_YEAR) & ".  ");
  9921.         TEXT_IO.PUT_LINE ("Please try again." & ASCII.LF & ASCII.CR);
  9922.  
  9923.         end loop;
  9924.  
  9925.         return (DATE_AND_TIME.JULIAN_DATE (DATE_SPEC));
  9926.     else
  9927.         return (PASSED_DATE);
  9928.     end if;
  9929.     end GET_NEW_DATE;
  9930.  
  9931.     -------------------------------------------------------
  9932.     -- Procedure is used to get a revised start date, then
  9933.     -- make the start date the 1st real working day at of
  9934.     -- following the calendar date specified.
  9935.     -------------------------------------------------------
  9936.     procedure REVISE_DATE is
  9937.  
  9938.     DATE_SPEC : DATE_AND_TIME.CALENDAR_TYPE :=
  9939.             DATE_AND_TIME.CALENDAR_DATE (JULIAN_START_DATE);
  9940.  
  9941.     begin
  9942.  
  9943.     JULIAN_START_DATE := GET_NEW_DATE
  9944.                 (WITH_YESNO_PROMPT =>
  9945.                    "Do you wish to change the " &
  9946.                    "project start date (currently " &
  9947.                    DATE_AND_TIME.DATE
  9948.                       (DATE_SPEC.DAY, DATE_SPEC.MONTH,
  9949.                        DATE_SPEC.YEAR + 1900) & ")." &
  9950.                    ASCII.LF & ASCII.CR & "ENTER [y/n] -->   ",
  9951.                  PASSED_DATE       => JULIAN_START_DATE,
  9952.                  AND_TEXT_PROMPT   =>
  9953.                    "ENTER new project start date ");
  9954.  
  9955.     JULIAN_START_DATE := FIND_PROPER_DATE (JULIAN_START_DATE, 1);
  9956.  
  9957.     end REVISE_DATE;
  9958.  
  9959.  
  9960.     -------------------------------------------------------
  9961.     -- Functions are used to map an integer project working
  9962.     -- day from a floating event time value.
  9963.     --------------------------------------------------------
  9964.     function TIME_UNIT_STARTED (ABSOLUTE_TIME : FLOAT) return INTEGER is
  9965.     begin
  9966.     if ABSOLUTE_TIME = 0.0 then
  9967.         return 1;
  9968.     else
  9969.         return MATH_FUNCTIONS.TRUNCATE (ABSOLUTE_TIME) + 2;
  9970.     end if;
  9971.     end TIME_UNIT_STARTED;
  9972.  
  9973.     function TIME_UNIT_DONE (ABSOLUTE_TIME : FLOAT) return INTEGER is
  9974.     begin
  9975.     return MATH_FUNCTIONS.TRUNCATE (ABSOLUTE_TIME) + 1;
  9976.     end TIME_UNIT_DONE;
  9977.  
  9978.  
  9979.     -------------------------------------------------------
  9980.     -- 
  9981.     -------------------------------------------------------
  9982.  
  9983.     procedure ACTIVITY_REPORT (FINAL_ACTIVITY_LIST : PERT_OPS.ARC_LIST_TYPE) is separate;
  9984.  
  9985.     procedure NODE_REPORT (FINAL_NODE_LIST : PERT_OPS.NODE_LIST_TYPE) is separate;
  9986.  
  9987.     procedure GANTT_REPORT (FINAL_ACTIVITY_LIST : PERT_OPS.ARC_LIST_TYPE) is separate;
  9988.  
  9989.     procedure SUM_MAN (FINAL_ACTIVITY_LIST : PERT_OPS.ARC_LIST_TYPE) is separate;
  9990.  
  9991.  
  9992.  
  9993.  
  9994. begin
  9995.  
  9996.  
  9997.  
  9998.     -----------------------------------------------------
  9999.     -- Set up holiday file
  10000.     -----------------------------------------------------
  10001.     READ_HOLIDAY_FILE;
  10002.  
  10003.  
  10004.     -----------------------------------------------------
  10005.     -- Set the julian start date to the 1st legal workday 
  10006.     -- following the julian start date.
  10007.     -----------------------------------------------------
  10008.     REVISE_DATE;
  10009.  
  10010.     -----------------------------------------------------
  10011.     -- Create a large list of activities.
  10012.     -- Visit each node, and add the activities
  10013.     -- comming into that node (except dummys) to a big list.
  10014.     -----------------------------------------------------
  10015.     declare
  10016.     NODE_LIST : constant PERT_OPS.NODE_LIST_TYPE :=
  10017.             PERT_OPS.NODES (ON_GRAPH => NETWORK);
  10018.  
  10019.     function "=" (LEFT, RIGHT : PERT_OPS.NODE_TYPE) return BOOLEAN
  10020.                renames PERT_OPS."=";
  10021.  
  10022.     FINAL_NODE_LIST : PERT_OPS.NODE_LIST_TYPE (NODE_LIST'RANGE) :=
  10023.               NODE_LIST (NODE_LIST'RANGE);
  10024.  
  10025.  
  10026.     procedure SORT_NODES (LIST : in out PERT_OPS.NODE_LIST_TYPE) is
  10027. --sort LIST into ascending order based on ESTIMATE_TIME_OF_EVENT
  10028. --use shell sort logic
  10029.  
  10030.         CURRENT_VALUE   : FLOAT;
  10031.         CURRENT_NODE    : PERT_OPS.NODE_TYPE;
  10032.         DISTANCE        : INTEGER range 0 .. LIST'LAST + 1 :=
  10033.                   (LIST'LAST + 1) / 3;
  10034.         PRECEDING_INDEX : INTEGER range -(LIST'LAST + 1) / 3 .. LIST'LAST;
  10035.  
  10036.     begin
  10037.         while DISTANCE > 0 loop
  10038.         for INDEX in DISTANCE + 1 .. LIST'LAST loop
  10039.             CURRENT_VALUE :=
  10040.               PERT_OPS.VALUE (LIST (INDEX)).ESTIMATE_TIME_OF_EVENT;
  10041.             PRECEDING_INDEX := INDEX - DISTANCE;
  10042.  
  10043.             if CURRENT_VALUE <
  10044.                PERT_OPS.VALUE (LIST (PRECEDING_INDEX))
  10045.             .ESTIMATE_TIME_OF_EVENT then
  10046.             CURRENT_NODE := LIST (INDEX);
  10047.  
  10048.             loop
  10049.                 LIST (PRECEDING_INDEX + DISTANCE) :=
  10050.                   LIST (PRECEDING_INDEX);
  10051.                 PRECEDING_INDEX := PRECEDING_INDEX - DISTANCE;
  10052.                 exit when PRECEDING_INDEX < LIST'FIRST or else
  10053.                       CURRENT_VALUE >=
  10054.                       PERT_OPS.VALUE (LIST (PRECEDING_INDEX))
  10055.                        .ESTIMATE_TIME_OF_EVENT;
  10056.             end loop;
  10057.  
  10058.             LIST (PRECEDING_INDEX + DISTANCE) := CURRENT_NODE;
  10059.             end if;
  10060.         end loop;
  10061.  
  10062.         DISTANCE := (DISTANCE + 1) / 3;
  10063.         end loop;
  10064.  
  10065.     end SORT_NODES;
  10066.  
  10067.     begin
  10068.     -- Sort FINAL_NODE_LIST on expected event time...
  10069.     SORT_NODES (FINAL_NODE_LIST);
  10070.  
  10071.     -----------------------------------------------------
  10072.     -- Output Node Report.
  10073.     -----------------------------------------------------
  10074.     NODE_REPORT (FINAL_NODE_LIST);
  10075.  
  10076.     for NODE_INDEX in NODE_LIST'RANGE loop
  10077.         if NODE_LIST (NODE_INDEX) /= PERT_OPS.START_NODE (NETWORK) then
  10078.         APPEND_THE_INCOMING_ARCS_TO_THE_BIG_LIST:
  10079.         declare
  10080.             ARC_LIST     : constant PERT_OPS.ARC_LIST_TYPE :=
  10081.                    PERT_OPS.INCOMING_ARCS
  10082.                       (ON_NODE => NODE_LIST (NODE_INDEX));
  10083.             END_ARC_LIST : NATURAL := ARC_LIST'LAST;
  10084.         begin
  10085.             for ARC_INDEX in ARC_LIST'RANGE loop
  10086.             ADD_NON_DUMMY_ACTIVITY (ARC_LIST (ARC_INDEX));
  10087.             end loop;
  10088.         end APPEND_THE_INCOMING_ARCS_TO_THE_BIG_LIST;
  10089.         end if;
  10090.     end loop;
  10091.     end;
  10092.  
  10093.     PROCESSING_FOR_ACTIVITY_LISTINGS:
  10094.     declare
  10095.     FINAL_ACTIVITY_LIST : PERT_OPS.ARC_LIST_TYPE (1 .. BIG_LIST_INDEX) :=
  10096.                   BIG_ACTIVITY_LIST (1 .. BIG_LIST_INDEX);
  10097.  
  10098.     procedure SORT_ACT_LIST (LIST : in out PERT_OPS.ARC_LIST_TYPE) is
  10099. --sort LIST into ascending order based on ESTIMATE_STOP
  10100. --use shell sort logic
  10101.  
  10102.         CURRENT_VALUE   : FLOAT;
  10103.         CURRENT_ARC     : PERT_OPS.ARC_TYPE;
  10104.         DISTANCE        : INTEGER range 0 .. LIST'LAST + 1 :=
  10105.                   (LIST'LAST + 1) / 3;
  10106.         PRECEDING_INDEX : INTEGER range -(LIST'LAST + 1) / 3 .. LIST'LAST;
  10107.  
  10108.     begin
  10109.         while DISTANCE > 0 loop
  10110.         for INDEX in DISTANCE + 1 .. LIST'LAST loop
  10111.             CURRENT_VALUE :=
  10112.               PERT_OPS.VALUE (LIST (INDEX)).ESTIMATE_STOP;
  10113.             PRECEDING_INDEX := INDEX - DISTANCE;
  10114.  
  10115.             if CURRENT_VALUE <
  10116.                PERT_OPS.VALUE (LIST (PRECEDING_INDEX))
  10117.             .ESTIMATE_STOP then
  10118.             CURRENT_ARC := LIST (INDEX);
  10119.  
  10120.             loop
  10121.                 LIST (PRECEDING_INDEX + DISTANCE) :=
  10122.                   LIST (PRECEDING_INDEX);
  10123.                 PRECEDING_INDEX := PRECEDING_INDEX - DISTANCE;
  10124.                 exit when PRECEDING_INDEX < LIST'FIRST or else
  10125.                       CURRENT_VALUE >=
  10126.                       PERT_OPS.VALUE (LIST (PRECEDING_INDEX))
  10127.                        .ESTIMATE_STOP;
  10128.             end loop;
  10129.  
  10130.             LIST (PRECEDING_INDEX + DISTANCE) := CURRENT_ARC;
  10131.             end if;
  10132.         end loop;
  10133.  
  10134.         DISTANCE := (DISTANCE + 1) / 3;
  10135.         end loop;
  10136.  
  10137.     end SORT_ACT_LIST;
  10138.  
  10139.     begin
  10140.     -- Sort the list of activities on ending date.
  10141.     SORT_ACT_LIST (FINAL_ACTIVITY_LIST);
  10142.  
  10143.     -----------------------------------------------------
  10144.     -- Output Activity Report.
  10145.     -----------------------------------------------------
  10146.     ACTIVITY_REPORT (FINAL_ACTIVITY_LIST);
  10147.  
  10148.     -----------------------------------------------------
  10149.     -- Output Gantt Report.
  10150.     -----------------------------------------------------
  10151.     GANTT_REPORT (FINAL_ACTIVITY_LIST);
  10152.  
  10153.     -----------------------------------------------------
  10154.     -- Output Summary Report and Manpower Report.
  10155.     -----------------------------------------------------
  10156.     SUM_MAN (FINAL_ACTIVITY_LIST);
  10157.  
  10158.     end PROCESSING_FOR_ACTIVITY_LISTINGS;
  10159.  
  10160. exception
  10161.     when others => 
  10162.     FATAL (UNIT => "Schedule Tool - Unit named " & "[PERT.OUTPUT_VALUES]");
  10163.  
  10164. end OUTPUT_VALUES;
  10165.  
  10166.  
  10167.  
  10168.  
  10169.  
  10170. separate (SCHEDULE.PERT.OUTPUT_VALUES)
  10171. procedure ACTIVITY_REPORT (FINAL_ACTIVITY_LIST : PERT_OPS.ARC_LIST_TYPE) is
  10172. -----------------------------------------------------------
  10173. -- Author:     K. Lamarche and T. C. Bryan
  10174. -- Source:     Division Software Technology and Support
  10175. --             Western Development Laboratories
  10176. --             Ford Aerospace & Communications Corporation
  10177. --             ATTN:  Ada Tools Group
  10178. -- Date  :     May 1985
  10179. -- Summary:    This procedure outputs the Activity Report
  10180. --             for the SIMPERT run.
  10181. ---------------------------------------------------------
  10182.  
  10183.     THE_ACT_REPORT : TEXT_IO.FILE_TYPE;
  10184.  
  10185.     type ACT_BODY_LINE_RECORD_TYPE is
  10186.     record
  10187.         WBS_CODE  : STRING (1 .. 8);
  10188.         ACT_NAME  : STRING (12 .. 43);
  10189.         TAIL      : INTEGER;
  10190.         HEAD      : INTEGER;
  10191.         STAFF     : FLOAT;
  10192.         LAB_HRS   : INTEGER;
  10193.         COST      : INTEGER;
  10194.         DAYS_STRT : INTEGER;
  10195.         DAYS_SPAN : INTEGER;
  10196.         STD_DEV   : INTEGER;
  10197.         TT_SLACK  : INTEGER;
  10198.         F_SLACK   : INTEGER;
  10199.         CRIT_INDX : FLOAT;
  10200.         STRT_DATE : DATE_AND_TIME.JULIAN_TYPE;
  10201.         THE_REM   : INTEGER;
  10202.         FIN_DATE  : DATE_AND_TIME.JULIAN_TYPE;
  10203.     end record;
  10204.  
  10205.  
  10206.  
  10207.     -------------------------------------------
  10208.     -- write one title line for column heading
  10209.     -------------------------------------------
  10210.     procedure WRITE_ACT_HEADER_LINE
  10211.          (TO_FILE   : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  10212.           WBS_CODE  : STRING;
  10213.           ACT_NAME  : STRING;
  10214.           TAIL      : STRING;
  10215.           HEAD      : STRING;
  10216.           STAFF     : STRING;
  10217.           LAB_HRS   : STRING;
  10218.           COST      : STRING;
  10219.           DAYS_STRT : STRING;
  10220.           DAYS_SPAN : STRING;
  10221.           STD_DEV   : STRING;
  10222.           TT_SLACK  : STRING;
  10223.           F_SLACK   : STRING;
  10224.           CRIT_INDX : STRING;
  10225.           STRT_DATE : STRING;
  10226.           THE_REM   : STRING;
  10227.           FIN_DATE  : STRING) is
  10228.  
  10229.     begin
  10230.  
  10231.     TEXT_IO.PUT (TO_FILE, WBS_CODE);
  10232.     TEXT_IO.SET_COL (TO_FILE, 12);
  10233.     TEXT_IO.PUT (TO_FILE, ACT_NAME);
  10234.     TEXT_IO.SET_COL (TO_FILE, 45);
  10235.     TEXT_IO.PUT (TO_FILE, TAIL);
  10236.     TEXT_IO.SET_COL (TO_FILE, 50);
  10237.     TEXT_IO.PUT (TO_FILE, HEAD);
  10238.     TEXT_IO.SET_COL (TO_FILE, 55);
  10239.     TEXT_IO.PUT (TO_FILE, STAFF);
  10240.     TEXT_IO.SET_COL (TO_FILE, 60);
  10241.     TEXT_IO.PUT (TO_FILE, LAB_HRS);
  10242.     TEXT_IO.SET_COL (TO_FILE, 66);
  10243.     TEXT_IO.PUT (TO_FILE, COST);
  10244.     TEXT_IO.SET_COL (TO_FILE, 73);
  10245.     TEXT_IO.PUT (TO_FILE, DAYS_STRT);
  10246.     TEXT_IO.SET_COL (TO_FILE, 78);
  10247.     TEXT_IO.PUT (TO_FILE, DAYS_SPAN);
  10248.     TEXT_IO.SET_COL (TO_FILE, 84);
  10249.     TEXT_IO.PUT (TO_FILE, STD_DEV);
  10250.     TEXT_IO.SET_COL (TO_FILE, 87);
  10251.     TEXT_IO.PUT (TO_FILE, TT_SLACK);
  10252.     TEXT_IO.SET_COL (TO_FILE, 92);
  10253.     TEXT_IO.PUT (TO_FILE, F_SLACK);
  10254.     TEXT_IO.SET_COL (TO_FILE, 97);
  10255.     TEXT_IO.PUT (TO_FILE, CRIT_INDX);
  10256.     TEXT_IO.SET_COL (TO_FILE, 105);
  10257.     TEXT_IO.PUT (TO_FILE, STRT_DATE);
  10258.     TEXT_IO.SET_COL (TO_FILE, 116);
  10259.     TEXT_IO.PUT (TO_FILE, THE_REM);
  10260.     TEXT_IO.SET_COL (TO_FILE, 122);
  10261.     TEXT_IO.PUT (TO_FILE, FIN_DATE);
  10262.     TEXT_IO.NEW_LINE (TO_FILE);
  10263.  
  10264.     end WRITE_ACT_HEADER_LINE;
  10265.  
  10266.  
  10267.  
  10268.     ---------------------------------------------------------------
  10269.     -- write one line of the report text.  The text is defined by
  10270.     -- "act_body_line_record_type
  10271.     ---------------------------------------------------------------
  10272.     procedure WRITE_ACT_BODY_LINE
  10273.          (TO_FILE : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  10274.           A_LINE  : ACT_BODY_LINE_RECORD_TYPE) is
  10275.  
  10276.     begin
  10277.     TEXT_IO.PUT (TO_FILE, A_LINE.WBS_CODE);
  10278.     TEXT_IO.SET_COL (TO_FILE, 12);
  10279.     TEXT_IO.PUT (TO_FILE, A_LINE.ACT_NAME);
  10280.     TEXT_IO.SET_COL (TO_FILE, 45);
  10281.     I_NUMBER.PUT (TO_FILE, A_LINE.TAIL, WIDTH => 4);
  10282.     TEXT_IO.SET_COL (TO_FILE, 50);
  10283.     I_NUMBER.PUT (TO_FILE, A_LINE.HEAD, WIDTH => 4);
  10284.     TEXT_IO.SET_COL (TO_FILE, 55);
  10285.  
  10286.     if A_LINE.STAFF <= 0.09 then
  10287.         TEXT_IO.PUT (TO_FILE, " 0.0");
  10288.     else
  10289.         F_NUMBER.PUT (TO_FILE, A_LINE.STAFF, EXP => 0, FORE => 2, AFT => 1);
  10290.     end if;
  10291.  
  10292.     TEXT_IO.SET_COL (TO_FILE, 60);
  10293.     I_NUMBER.PUT (TO_FILE, A_LINE.LAB_HRS, WIDTH => 5);
  10294.     TEXT_IO.SET_COL (TO_FILE, 66);
  10295.     I_NUMBER.PUT (TO_FILE, A_LINE.COST, WIDTH => 6);
  10296.     TEXT_IO.SET_COL (TO_FILE, 73);
  10297.     I_NUMBER.PUT (TO_FILE, A_LINE.DAYS_STRT, WIDTH => 4);
  10298.     TEXT_IO.SET_COL (TO_FILE, 78);
  10299.     I_NUMBER.PUT (TO_FILE, A_LINE.DAYS_SPAN, WIDTH => 4);
  10300.     TEXT_IO.SET_COL (TO_FILE, 84);
  10301.     I_NUMBER.PUT (TO_FILE, A_LINE.STD_DEV, WIDTH => 2);
  10302.     TEXT_IO.SET_COL (TO_FILE, 87);
  10303.     I_NUMBER.PUT (TO_FILE, A_LINE.TT_SLACK, WIDTH => 4);
  10304.     TEXT_IO.SET_COL (TO_FILE, 92);
  10305.     I_NUMBER.PUT (TO_FILE, A_LINE.F_SLACK, WIDTH => 4);
  10306.     TEXT_IO.SET_COL (TO_FILE, 97);
  10307.  
  10308.     if A_LINE.CRIT_INDX <= 0.009 then
  10309.         TEXT_IO.PUT (TO_FILE, "0.00");
  10310.     else
  10311.         F_NUMBER.PUT
  10312.            (TO_FILE, A_LINE.CRIT_INDX, EXP => 0, FORE => 1, AFT => 2);
  10313.     end if;
  10314.  
  10315.     TEXT_IO.SET_COL (TO_FILE, 105);
  10316.     TEXT_IO.PUT (TO_FILE, CONVERT_TO_NORMAL_DATE (A_LINE.STRT_DATE));
  10317.     TEXT_IO.SET_COL (TO_FILE, 116);
  10318.     I_NUMBER.PUT (TO_FILE, A_LINE.THE_REM, WIDTH => 3);
  10319.     TEXT_IO.SET_COL (TO_FILE, 122);
  10320.     TEXT_IO.PUT (TO_FILE, CONVERT_TO_NORMAL_DATE (A_LINE.FIN_DATE));
  10321.     TEXT_IO.NEW_LINE (TO_FILE);
  10322.  
  10323.     end WRITE_ACT_BODY_LINE;
  10324.  
  10325.  
  10326. begin
  10327.  
  10328.     -------------------------------
  10329.     -- create the  activity report
  10330.     -------------------------------
  10331.     TEXT_IO.CREATE (THE_ACT_REPORT, TEXT_IO.OUT_FILE, THE_ACTIVITY_REPORT_NAME);
  10332.     -------------------------
  10333.     -- the heading portion
  10334.     -------------------------
  10335.     WRITE_HEADER_REPORT (TO_FILE    => THE_ACT_REPORT,
  10336.              FORM_NAME  => "ACTIVITY REPORT",
  10337.              PAGE_WIDTH => 130);
  10338.  
  10339.  
  10340.     WRITE_ACT_HEADER_LINE
  10341.        (TO_FILE   => THE_ACT_REPORT,
  10342.     WBS_CODE  => "",
  10343.     ACT_NAME  => "",
  10344.     TAIL      => "",
  10345.     HEAD      => "",
  10346.     STAFF     => "",
  10347.     LAB_HRS   => "Labor",
  10348.     COST      => " Cost ",
  10349.     DAYS_STRT => REQUESTED_UNIT_CODE,
  10350.     DAYS_SPAN => REQUESTED_UNIT_CODE,
  10351.     STD_DEV   => "Sd",
  10352.     TT_SLACK  => "Totl",
  10353.     F_SLACK   => "Free",
  10354.     CRIT_INDX => "Crit",
  10355.     STRT_DATE => "  Start  ",
  10356.     THE_REM   => "",
  10357.     FIN_DATE  => " Finish  ");
  10358.  
  10359.  
  10360.     WRITE_ACT_HEADER_LINE
  10361.        (TO_FILE   => THE_ACT_REPORT,
  10362.     WBS_CODE  => "WBS Code",
  10363.     ACT_NAME  => "        Activity Title",
  10364.     TAIL      => "Tail",
  10365.     HEAD      => "Head",
  10366.     STAFF     => "Staf",
  10367.     LAB_HRS   => "Hours",
  10368.     COST      => "($100)",
  10369.     DAYS_STRT => "Strt",
  10370.     DAYS_SPAN => "Span",
  10371.     STD_DEV   => "Dv",
  10372.     TT_SLACK  => "Slck",
  10373.     F_SLACK   => "Slck",
  10374.     CRIT_INDX => "Indx",
  10375.     STRT_DATE => "  Date   ",
  10376.     THE_REM   => "Rem",
  10377.     FIN_DATE  => "  Date   ");
  10378.  
  10379.  
  10380.     WRITE_ACT_HEADER_LINE
  10381.        (TO_FILE   => THE_ACT_REPORT,
  10382.     WBS_CODE  => "________",
  10383.     ACT_NAME  => "________________________________",
  10384.     TAIL      => "____",
  10385.     HEAD      => "____",
  10386.     STAFF     => "____",
  10387.     LAB_HRS   => "_____",
  10388.     COST      => "______",
  10389.     DAYS_STRT => "____",
  10390.     DAYS_SPAN => "____",
  10391.     STD_DEV   => "__",
  10392.     TT_SLACK  => "____",
  10393.     F_SLACK   => "____",
  10394.     CRIT_INDX => "____",
  10395.     STRT_DATE => "_________",
  10396.     THE_REM   => "___",
  10397.     FIN_DATE  => "_________");
  10398.  
  10399.     TEXT_IO.NEW_LINE (THE_ACT_REPORT);
  10400.     TEXT_IO.PUT_LINE (THE_ACT_REPORT,
  10401.               "Data sorted on ---> Expected Finish Date");
  10402.     TEXT_IO.NEW_LINE (THE_ACT_REPORT);
  10403.  
  10404.     -------------------------
  10405.     -- the text portion
  10406.     -------------------------
  10407.     declare
  10408.     ACTIVITY      : ACTIVITY_TYPE;
  10409.     ACT_BODY_LINE : ACT_BODY_LINE_RECORD_TYPE;
  10410.     STOP_TICK     : INTEGER;
  10411.  
  10412.     begin
  10413.  
  10414.     for ACTIVITY_INDEX in FINAL_ACTIVITY_LIST'RANGE loop
  10415.  
  10416.         ACTIVITY := PERT_OPS.VALUE (FINAL_ACTIVITY_LIST (ACTIVITY_INDEX));
  10417.         ACT_BODY_LINE.WBS_CODE := ACTIVITY.NAME (1 .. 8);
  10418.         ACT_BODY_LINE.ACT_NAME := ACTIVITY.NAME (11 .. 42);
  10419.         ACT_BODY_LINE.TAIL :=
  10420.           PERT_OPS.VALUE (PERT_OPS.TAIL_NODE
  10421.                  (FINAL_ACTIVITY_LIST (ACTIVITY_INDEX)))
  10422.            .EVENT_ID;
  10423.         ACT_BODY_LINE.HEAD :=
  10424.           PERT_OPS.VALUE (PERT_OPS.HEAD_NODE
  10425.                  (FINAL_ACTIVITY_LIST (ACTIVITY_INDEX)))
  10426.            .EVENT_ID;
  10427.         ACT_BODY_LINE.STAFF := ACTIVITY.STAFFING;
  10428.  
  10429.         ACT_BODY_LINE.DAYS_STRT :=
  10430.           TIME_UNIT_STARTED (ACTIVITY.ESTIMATE_START);
  10431.         STOP_TICK := TIME_UNIT_DONE (ACTIVITY.ESTIMATE_STOP);
  10432.  
  10433.         if STOP_TICK < ACT_BODY_LINE.DAYS_STRT then
  10434.         STOP_TICK := ACT_BODY_LINE.DAYS_STRT;
  10435.         end if;
  10436.  
  10437.         if ACTIVITY.ESTIMATE_START = ACTIVITY.ESTIMATE_STOP then
  10438.         ACT_BODY_LINE.DAYS_SPAN := 0;
  10439.         else
  10440.         ACT_BODY_LINE.DAYS_SPAN :=
  10441.           STOP_TICK - ACT_BODY_LINE.DAYS_STRT + 1;
  10442.         end if;
  10443.  
  10444.         ACT_BODY_LINE.LAB_HRS :=
  10445.           ACT_BODY_LINE.DAYS_SPAN * INTEGER (ACTIVITY.STAFFING) *
  10446.           (TO_DAYS (1) * 8);
  10447.  
  10448.         if ACTIVITY.STAFFING = 0.0 then
  10449.         ACT_BODY_LINE.COST := INTEGER (ACTIVITY.RATE / 100.0);
  10450.         else
  10451.         ACT_BODY_LINE.COST :=
  10452.           INTEGER (FLOAT (ACT_BODY_LINE.DAYS_SPAN) * ACTIVITY.RATE *
  10453.                ACTIVITY.STAFFING / 100.0);
  10454.         end if;
  10455.  
  10456.         ACT_BODY_LINE.STD_DEV :=
  10457.           INTEGER (((((ACTIVITY.PESSIMISTIC_TIME -
  10458.                ACTIVITY.OPTIMISTIC_TIME) ** 2.0 +
  10459.               (ACTIVITY.MOST_PROBABLE_TIME -
  10460.                ACTIVITY.OPTIMISTIC_TIME) *
  10461.               (ACTIVITY.MOST_PROBABLE_TIME -
  10462.                ACTIVITY.PESSIMISTIC_TIME)) / 18.0) ** 0.5) + 0.5);
  10463.  
  10464.         ACT_BODY_LINE.TT_SLACK :=
  10465.           INTEGER (PERT_OPS.VALUE
  10466.               (PERT_OPS.HEAD_NODE
  10467.                   (FINAL_ACTIVITY_LIST (ACTIVITY_INDEX)))
  10468.             .DET_LATE_TIME_OF_EVENT -
  10469.                PERT_OPS.VALUE
  10470.               (PERT_OPS.TAIL_NODE
  10471.                   (FINAL_ACTIVITY_LIST (ACTIVITY_INDEX)))
  10472.             .DET_TIME_OF_EVENT - ACTIVITY.DURATION_TIME);
  10473.  
  10474.         CALCULATE_FREE_SLACK:
  10475.         declare
  10476.         FREE_SLACK : FLOAT :=
  10477.                  PERT_OPS.VALUE
  10478.                 (PERT_OPS.HEAD_NODE
  10479.                     (FINAL_ACTIVITY_LIST (ACTIVITY_INDEX)))
  10480.                   .DET_TIME_OF_EVENT -
  10481.                  PERT_OPS.VALUE
  10482.                 (PERT_OPS.TAIL_NODE
  10483.                     (FINAL_ACTIVITY_LIST (ACTIVITY_INDEX)))
  10484.                   .DET_TIME_OF_EVENT - ACTIVITY.DURATION_TIME;
  10485.         begin
  10486.         if FREE_SLACK < 0.0 then
  10487.             FREE_SLACK := 0.0;
  10488.         end if;
  10489.  
  10490.         ACT_BODY_LINE.F_SLACK := INTEGER (FREE_SLACK);
  10491.         TOTAL_FREE_SLACK := TOTAL_FREE_SLACK + FREE_SLACK;
  10492.         end CALCULATE_FREE_SLACK;
  10493.  
  10494.         ACT_BODY_LINE.CRIT_INDX := ACTIVITY.ON_CP_COUNT;
  10495.  
  10496.         ACT_BODY_LINE.STRT_DATE :=
  10497.           FIND_PROPER_DATE
  10498.          (JULIAN_START_DATE, TO_DAYS (ACT_BODY_LINE.DAYS_STRT));
  10499.         ACT_BODY_LINE.FIN_DATE :=
  10500.           FIND_PROPER_DATE (JULIAN_START_DATE, TO_DAYS (STOP_TICK));
  10501.  
  10502.         ACT_BODY_LINE.THE_REM :=
  10503.           WORKDAYS_BETWEEN (JULIAN_DATE_NOW, ACT_BODY_LINE.FIN_DATE);
  10504.  
  10505.         if ACT_BODY_LINE.THE_REM < 0 then
  10506.         ACT_BODY_LINE.THE_REM := 0;
  10507.         end if;
  10508.  
  10509.         WRITE_ACT_BODY_LINE
  10510.            (TO_FILE => THE_ACT_REPORT, A_LINE => ACT_BODY_LINE);
  10511.  
  10512.     end loop;
  10513.  
  10514.     TEXT_IO.CLOSE (THE_ACT_REPORT);
  10515.     end;
  10516.  
  10517. exception
  10518.     when others => 
  10519.     FATAL (UNIT => "Schedule Tool - Unit named " &
  10520.                "[PERT.OUTPUT_VALUES.ACTIVITY_REPORT]");
  10521.  
  10522. end ACTIVITY_REPORT;
  10523.  
  10524.  
  10525.  
  10526.  
  10527.  
  10528. separate (SCHEDULE.PERT.OUTPUT_VALUES)
  10529. procedure GANTT_REPORT (FINAL_ACTIVITY_LIST : PERT_OPS.ARC_LIST_TYPE) is
  10530. --------------------------------------------------------------------------
  10531. -- Author:  Ken Lamarche and T.C. Bryan
  10532. -- Source:     Division Software Technology and Support
  10533. --             Western Development Laboratories
  10534. --             Ford Aerospace & Communications Corporation
  10535. --             ATTN:  Ada Tools Group
  10536. -- Date  :  May 1985
  10537. -- Summary:  
  10538. -- This procedure is used to produce the Gantt Report. This output will be
  10539. -- used as a text report, and also to produce the Gantt Chart.
  10540. --------------------------------------------------------------------------
  10541.  
  10542.  
  10543.     THE_GANTT_REPORT : TEXT_IO.FILE_TYPE;
  10544.  
  10545.     type GANTT_BODY_LINE_RECORD_TYPE is
  10546.     record
  10547.         WBS_CODE   : STRING (1 .. 8);
  10548.         GANTT_NAME : STRING (12 .. 43);
  10549.         CRITICAL   : CHARACTER;
  10550.         TAIL       : INTEGER;
  10551.         HEAD       : INTEGER;
  10552.         STAFF      : INTEGER;
  10553.         START      : INTEGER;
  10554.         STOP       : INTEGER;
  10555.     end record;
  10556.  
  10557.  
  10558.     procedure WRITE_SECOND_HEADER_REPORT
  10559.          (TO_FILE       : TEXT_IO.FILE_TYPE := THE_GANTT_REPORT;
  10560.           TITLE         : STRING :=
  10561.                   STRING_UTILITIES
  10562.                    .REMOVE_LEADING_AND_TRAILING_BLANKS
  10563.                      (OUTPUT_REPORT_TITLE);
  10564.           SIMPERT_FILE  : STRING :=
  10565.                   STRING_UTILITIES
  10566.                    .REMOVE_LEADING_AND_TRAILING_BLANKS
  10567.                      (PERT_FILE);
  10568.           NUMBER_OF_ACT : INTEGER := FINAL_ACTIVITY_LIST'LENGTH;
  10569.           TT_PROJ_SCHED : FLOAT :=
  10570.                   PERT_OPS.VALUE (PERT_OPS.END_NODE (NETWORK))
  10571.                    .ESTIMATE_TIME_OF_EVENT;
  10572.           TIME_UNIT     : STRING :=
  10573.                   TIME_UNIT_TYPE'IMAGE (TIME_UNIT_CODE) &
  10574.                   INTEGER'IMAGE (WORKDAYS_PER_WEEK);
  10575.           PROBABILITY   : FLOAT := PROBABILITY_FOR_OUTPUT;
  10576.           START_DATE_IS : DATE_AND_TIME.JULIAN_TYPE :=
  10577.                   JULIAN_START_DATE) is
  10578.  
  10579.  
  10580. -------------------------------------------------------
  10581. -- convert a julian date into the format "dd mm yy"
  10582. -- 
  10583. -- Author: T. C. Bryan
  10584. -- Source:     Division Software Technology and Support
  10585. --             Western Development Laboratories
  10586. --             Ford Aerospace & Communications Corporation
  10587. --             ATTN:  Ada Tools Group
  10588. -- Library use : date_and_time.
  10589. -- Date:  17 May 85
  10590. -------------------------------------------------------
  10591.     function CONVERT_TO_DD_MM_YY_DATE
  10592.             (THE_JULIAN_IS : DATE_AND_TIME.JULIAN_TYPE) return STRING is
  10593.  
  10594.         DATE_SPEC : DATE_AND_TIME.CALENDAR_TYPE :=
  10595.             DATE_AND_TIME.CALENDAR_DATE (THE_JULIAN_IS);
  10596.  
  10597.  
  10598.     begin
  10599.  
  10600.         return (INTEGER'IMAGE (DATE_SPEC.DAY) &
  10601.             INTEGER'IMAGE (DATE_SPEC.MONTH) &
  10602.             INTEGER'IMAGE (DATE_SPEC.YEAR));
  10603.  
  10604.     end CONVERT_TO_DD_MM_YY_DATE;
  10605.  
  10606.  
  10607.  
  10608.     begin
  10609.  
  10610.  
  10611.     TEXT_IO.PUT (TO_FILE, TITLE);
  10612.     TEXT_IO.SET_COL (TO_FILE, TO => 81);
  10613.     TEXT_IO.PUT_LINE (TO_FILE, "Title");
  10614.  
  10615.     TEXT_IO.PUT (TO_FILE, SIMPERT_FILE);
  10616.     TEXT_IO.SET_COL (TO_FILE, TO => 68);
  10617.     TEXT_IO.PUT_LINE (TO_FILE, "SIMPERT input file");
  10618.  
  10619.     I_NUMBER.PUT (TO_FILE, NUMBER_OF_ACT, WIDTH => 4);
  10620.     TEXT_IO.SET_COL (TO_FILE, TO => 66);
  10621.     TEXT_IO.PUT_LINE (TO_FILE, "Number of activities");
  10622.  
  10623.     if TT_PROJ_SCHED <= 0.009 then
  10624.         TEXT_IO.PUT (TO_FILE, " 0.0");
  10625.     else
  10626.         F_NUMBER.PUT
  10627.            (TO_FILE, TT_PROJ_SCHED, EXP => 0, FORE => 4, AFT => 2);
  10628.     end if;
  10629.  
  10630.     TEXT_IO.SET_COL (TO_FILE, TO => 64);
  10631.     TEXT_IO.PUT_LINE (TO_FILE, "Total project schedule");
  10632.  
  10633.     TEXT_IO.PUT (TO_FILE, TIME_UNIT);
  10634.     TEXT_IO.SET_COL (TO_FILE, TO => 51);
  10635.     TEXT_IO.PUT_LINE (TO_FILE, "D = days, W = weeks, # = days/weeks");
  10636.  
  10637.     TEXT_IO.SET_COL (TO_FILE, TO => 4);
  10638.  
  10639.     if PROBABILITY <= 0.009 then
  10640.         TEXT_IO.PUT (TO_FILE, " 0.0");
  10641.     else
  10642.         F_NUMBER.PUT (TO_FILE, PROBABILITY, EXP => 0, FORE => 1, AFT => 2);
  10643.     end if;
  10644.  
  10645.     TEXT_IO.SET_COL (TO_FILE, TO => 66);
  10646.     TEXT_IO.PUT_LINE (TO_FILE, "Probability for time");
  10647.  
  10648.     TEXT_IO.PUT (TO_FILE, CONVERT_TO_DD_MM_YY_DATE (START_DATE_IS));
  10649.     TEXT_IO.SET_COL (TO_FILE, TO => 57);
  10650.     TEXT_IO.PUT_LINE (TO_FILE, "Project Start date {dd/mm/yy}");
  10651.  
  10652.     end WRITE_SECOND_HEADER_REPORT;
  10653.  
  10654.  
  10655.  
  10656.     procedure WRITE_GANTT_HEADER_LINE
  10657.          (TO_FILE    : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  10658.           WBS_CODE   : STRING;
  10659.           GANTT_NAME : STRING;
  10660.           CRITICAL   : STRING;
  10661.           TAIL       : STRING;
  10662.           HEAD       : STRING;
  10663.           STAFF      : STRING;
  10664.           START      : STRING;
  10665.           STOP       : STRING) is
  10666.  
  10667.     begin
  10668.  
  10669.     TEXT_IO.PUT (TO_FILE, WBS_CODE);
  10670.     TEXT_IO.SET_COL (TO_FILE, 12);
  10671.     TEXT_IO.PUT (TO_FILE, GANTT_NAME);
  10672.     TEXT_IO.SET_COL (TO_FILE, 45);
  10673.     TEXT_IO.PUT (TO_FILE, CRITICAL);
  10674.     TEXT_IO.SET_COL (TO_FILE, 51);
  10675.     TEXT_IO.PUT (TO_FILE, TAIL);
  10676.     TEXT_IO.SET_COL (TO_FILE, 58);
  10677.     TEXT_IO.PUT (TO_FILE, HEAD);
  10678.     TEXT_IO.SET_COL (TO_FILE, 65);
  10679.     TEXT_IO.PUT (TO_FILE, STAFF);
  10680.     TEXT_IO.SET_COL (TO_FILE, 72);
  10681.     TEXT_IO.PUT (TO_FILE, START);
  10682.     TEXT_IO.SET_COL (TO_FILE, 81);
  10683.     TEXT_IO.PUT (TO_FILE, STOP);
  10684.     TEXT_IO.NEW_LINE (TO_FILE);
  10685.  
  10686.     end WRITE_GANTT_HEADER_LINE;
  10687.  
  10688.  
  10689.  
  10690.     procedure WRITE_GANTT_BODY_LINE
  10691.          (TO_FILE : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  10692.           A_LINE  : GANTT_BODY_LINE_RECORD_TYPE) is
  10693.  
  10694.     begin
  10695.     TEXT_IO.PUT (TO_FILE, A_LINE.WBS_CODE);
  10696.     TEXT_IO.SET_COL (TO_FILE, 12);
  10697.     TEXT_IO.PUT (TO_FILE, A_LINE.GANTT_NAME);
  10698.     TEXT_IO.SET_COL (TO_FILE, 48);
  10699.     TEXT_IO.PUT (TO_FILE, A_LINE.CRITICAL);
  10700.     TEXT_IO.SET_COL (TO_FILE, 51);
  10701.     I_NUMBER.PUT (TO_FILE, A_LINE.TAIL, WIDTH => 4);
  10702.     TEXT_IO.SET_COL (TO_FILE, 58);
  10703.     I_NUMBER.PUT (TO_FILE, A_LINE.HEAD, WIDTH => 4);
  10704.     TEXT_IO.SET_COL (TO_FILE, 67);
  10705.     I_NUMBER.PUT (TO_FILE, A_LINE.STAFF, WIDTH => 3);
  10706.     TEXT_IO.SET_COL (TO_FILE, 74);
  10707.     I_NUMBER.PUT (TO_FILE, A_LINE.START, WIDTH => 3);
  10708.     TEXT_IO.SET_COL (TO_FILE, 82);
  10709.     I_NUMBER.PUT (TO_FILE, A_LINE.STOP, WIDTH => 3);
  10710.  
  10711.     TEXT_IO.NEW_LINE (TO_FILE);
  10712.     end WRITE_GANTT_BODY_LINE;
  10713.  
  10714.  
  10715.  
  10716. begin
  10717.     ------------------------
  10718.     -- Print Gantt report.
  10719.     ------------------------
  10720.     TEXT_IO.CREATE (THE_GANTT_REPORT, TEXT_IO.OUT_FILE, THE_GANTT_REPORT_NAME);
  10721.     WRITE_HEADER_REPORT (TO_FILE    => THE_GANTT_REPORT,
  10722.              FORM_NAME  => "GANTT INPUT FILE",
  10723.              PAGE_WIDTH => 86);
  10724.  
  10725.     TEXT_IO.NEW_LINE (THE_GANTT_REPORT, 2);
  10726.     WRITE_SECOND_HEADER_REPORT;
  10727.     TEXT_IO.NEW_LINE (THE_GANTT_REPORT, 2);
  10728.  
  10729.  
  10730.     WRITE_GANTT_HEADER_LINE
  10731.        (TO_FILE    => THE_GANTT_REPORT,
  10732.     WBS_CODE   => "WBS Code",
  10733.     GANTT_NAME => "        Activity Title",
  10734.     CRITICAL   => "Crit",
  10735.     TAIL       => "Tail",
  10736.     HEAD       => "Head",
  10737.     STAFF      => "Staff",
  10738.     START      => "Start",
  10739.     STOP       => "Stop");
  10740.  
  10741.  
  10742.     WRITE_GANTT_HEADER_LINE
  10743.        (TO_FILE    => THE_GANTT_REPORT,
  10744.     WBS_CODE   => "________",
  10745.     GANTT_NAME => "________________________________",
  10746.     CRITICAL   => "____",
  10747.     TAIL       => "____",
  10748.     HEAD       => "____",
  10749.     STAFF      => "_____",
  10750.     START      => "_____",
  10751.     STOP       => "____");
  10752.  
  10753.  
  10754.     TEXT_IO.NEW_LINE (THE_GANTT_REPORT, 2);
  10755.     TEXT_IO.PUT_LINE (THE_GANTT_REPORT, "Data sorted on ---> Finish Time");
  10756.     TEXT_IO.NEW_LINE (THE_GANTT_REPORT);
  10757.  
  10758.     declare
  10759.     ACTIVITY        : ACTIVITY_TYPE;
  10760.     GANTT_BODY_LINE : GANTT_BODY_LINE_RECORD_TYPE;
  10761.     begin
  10762.     for ACTIVITY_INDEX in FINAL_ACTIVITY_LIST'RANGE loop
  10763.         ACTIVITY := PERT_OPS.VALUE (FINAL_ACTIVITY_LIST (ACTIVITY_INDEX));
  10764.  
  10765.         GANTT_BODY_LINE.WBS_CODE := ACTIVITY.NAME (1 .. 8);
  10766.         GANTT_BODY_LINE.GANTT_NAME := ACTIVITY.NAME (11 .. 42);
  10767.  
  10768.         IS_ARC_ON_CRITICAL_PATH:
  10769.         declare
  10770.         EVENT_IMAGE : PERT_OPS.NODE_TYPE :=
  10771.                   PERT_OPS.HEAD_NODE
  10772.                  (FINAL_ACTIVITY_LIST (ACTIVITY_INDEX));
  10773.         ARC_LIST    : constant PERT_OPS.ARC_LIST_TYPE :=
  10774.                   PERT_OPS.INCOMING_ARCS (EVENT_IMAGE);
  10775.         begin
  10776.         if PERT_OPS."="
  10777.               (ARC_LIST (PERT_OPS.VALUE (EVENT_IMAGE)
  10778.                   .MOST_CRIT_INBOUND_ARC),
  10779.                FINAL_ACTIVITY_LIST (ACTIVITY_INDEX)) then
  10780.             GANTT_BODY_LINE.CRITICAL := 'C';
  10781.         else
  10782.             GANTT_BODY_LINE.CRITICAL := ' ';
  10783.         end if;
  10784.         end IS_ARC_ON_CRITICAL_PATH;
  10785.  
  10786.         GANTT_BODY_LINE.TAIL :=
  10787.           PERT_OPS.VALUE (PERT_OPS.TAIL_NODE
  10788.                  (FINAL_ACTIVITY_LIST (ACTIVITY_INDEX)))
  10789.            .EVENT_ID;
  10790.  
  10791.         GANTT_BODY_LINE.HEAD :=
  10792.           PERT_OPS.VALUE (PERT_OPS.HEAD_NODE
  10793.                  (FINAL_ACTIVITY_LIST (ACTIVITY_INDEX)))
  10794.            .EVENT_ID;
  10795.  
  10796.         GANTT_BODY_LINE.STAFF := INTEGER (ACTIVITY.STAFFING);
  10797.  
  10798.         GANTT_BODY_LINE.START :=
  10799.           TO_DAYS (TIME_UNIT_STARTED (ACTIVITY.ESTIMATE_START));
  10800.  
  10801.         GANTT_BODY_LINE.STOP :=
  10802.           TO_DAYS (TIME_UNIT_DONE (ACTIVITY.ESTIMATE_STOP));
  10803.  
  10804.         WRITE_GANTT_BODY_LINE
  10805.            (TO_FILE => THE_GANTT_REPORT, A_LINE => GANTT_BODY_LINE);
  10806.     end loop;
  10807.  
  10808.     end;
  10809.  
  10810.     TEXT_IO.CLOSE (THE_GANTT_REPORT);
  10811.  
  10812. exception
  10813.     when others => 
  10814.     FATAL (UNIT => "Schedule Tool - Unit named " &
  10815.                "[PERT.OUTPUT_VALUES.GANTT_REPORT]");
  10816.  
  10817. end GANTT_REPORT;
  10818.  
  10819.  
  10820.  
  10821.  
  10822.  
  10823. separate (SCHEDULE.PERT.OUTPUT_VALUES)
  10824. procedure NODE_REPORT (FINAL_NODE_LIST : PERT_OPS.NODE_LIST_TYPE) is
  10825. ------------------------------------------------------------------------------
  10826. -- Authors: K. Lamarche and T. C. Bryan
  10827. -- Source:     Division Software Technology and Support
  10828. --             Western Development Laboratories
  10829. --             Ford Aerospace & Communications Corporation
  10830. --             ATTN:  Ada Tools Group
  10831. -- Date:    May 1985
  10832. -- Summary:
  10833. -- This procedure is used to output the Node Information report. It Is
  10834. -- called with a sorted list of NODE_TYPES; pointers that point to the
  10835. -- information record of each node.
  10836. -------------------------------------------------------------------------------
  10837.  
  10838.  
  10839.     THE_NODE_REPORT : TEXT_IO.FILE_TYPE;
  10840.  
  10841.     type NODE_BODY_LINE_RECORD_TYPE is
  10842.     record
  10843.         NODE        : INTEGER;
  10844.         EXPECTED    : FLOAT;
  10845.         TIME_DATE   : DATE_AND_TIME.JULIAN_TYPE;
  10846.         STND_DEV    : FLOAT;
  10847.         PROBABILITY : FLOAT;
  10848.         PTIME_DATE  : DATE_AND_TIME.JULIAN_TYPE;
  10849.         CRIT_INDEX  : FLOAT;
  10850.     end record;
  10851.  
  10852.  
  10853.     procedure WRITE_NODE_HEADER_LINE
  10854.          (TO_FILE     : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  10855.           NODE        : STRING;
  10856.           EXPECTED    : STRING;
  10857.           TIME_DATE   : STRING;
  10858.           STND_DEV    : STRING;
  10859.           PROBABILITY : STRING;
  10860.           PTIME_DATE  : STRING;
  10861.           CRIT_INDEX  : STRING) is
  10862.  
  10863.     begin
  10864.  
  10865.     TEXT_IO.PUT (TO_FILE, NODE);
  10866.     TEXT_IO.SET_COL (TO_FILE, 10);
  10867.     TEXT_IO.PUT (TO_FILE, EXPECTED);
  10868.     TEXT_IO.SET_COL (TO_FILE, 20);
  10869.     TEXT_IO.PUT (TO_FILE, TIME_DATE);
  10870.     TEXT_IO.SET_COL (TO_FILE, 34);
  10871.     TEXT_IO.PUT (TO_FILE, STND_DEV);
  10872.     TEXT_IO.SET_COL (TO_FILE, 51);
  10873.     TEXT_IO.PUT (TO_FILE, PROBABILITY);
  10874.     TEXT_IO.SET_COL (TO_FILE, 60);
  10875.     TEXT_IO.PUT (TO_FILE, PTIME_DATE);
  10876.     TEXT_IO.SET_COL (TO_FILE, 73);
  10877.     TEXT_IO.PUT (TO_FILE, CRIT_INDEX);
  10878.  
  10879.     TEXT_IO.NEW_LINE (TO_FILE);
  10880.  
  10881.     end WRITE_NODE_HEADER_LINE;
  10882.  
  10883.  
  10884.  
  10885.     procedure WRITE_NODE_BODY_LINE
  10886.          (TO_FILE : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  10887.           A_LINE  : NODE_BODY_LINE_RECORD_TYPE) is
  10888.  
  10889.     begin
  10890.     I_NUMBER.PUT (TO_FILE, A_LINE.NODE, WIDTH => 4);
  10891.     TEXT_IO.SET_COL (TO_FILE, 10);
  10892.  
  10893.     if A_LINE.EXPECTED <= 0.009 then
  10894.         TEXT_IO.PUT (TO_FILE, "   0.00");
  10895.     else
  10896.         F_NUMBER.PUT
  10897.            (TO_FILE, A_LINE.EXPECTED, EXP => 0, FORE => 4, AFT => 2);
  10898.     end if;
  10899.  
  10900.     TEXT_IO.SET_COL (TO_FILE, 20);
  10901.     TEXT_IO.PUT (TO_FILE, CONVERT_TO_NORMAL_DATE (A_LINE.TIME_DATE));
  10902.     TEXT_IO.SET_COL (TO_FILE, 36);
  10903.  
  10904.     if A_LINE.STND_DEV <= 0.009 then
  10905.         TEXT_IO.PUT (TO_FILE, "   0.00");
  10906.     else
  10907.         F_NUMBER.PUT
  10908.            (TO_FILE, A_LINE.STND_DEV, EXP => 0, FORE => 4, AFT => 2);
  10909.     end if;
  10910.  
  10911.     TEXT_IO.SET_COL (TO_FILE, 50);
  10912.  
  10913.     if A_LINE.PROBABILITY <= 0.009 then
  10914.         TEXT_IO.PUT (TO_FILE, "   0.00");
  10915.     else
  10916.         F_NUMBER.PUT
  10917.            (TO_FILE, A_LINE.PROBABILITY, EXP => 0, FORE => 4, AFT => 2);
  10918.     end if;
  10919.  
  10920.     TEXT_IO.SET_COL (TO_FILE, 60);
  10921.     TEXT_IO.PUT (TO_FILE, CONVERT_TO_NORMAL_DATE (A_LINE.PTIME_DATE));
  10922.     TEXT_IO.SET_COL (TO_FILE, 79);
  10923.  
  10924.     if A_LINE.CRIT_INDEX <= 0.009 then
  10925.         TEXT_IO.PUT (TO_FILE, " 0.00");
  10926.     else
  10927.         F_NUMBER.PUT
  10928.            (TO_FILE, A_LINE.CRIT_INDEX, EXP => 0, FORE => 2, AFT => 2);
  10929.     end if;
  10930.  
  10931.     TEXT_IO.NEW_LINE (TO_FILE);
  10932.  
  10933.     end WRITE_NODE_BODY_LINE;
  10934.  
  10935.  
  10936.  
  10937. begin
  10938.  
  10939.     --------------------------------------------------
  10940.     -- create the Node report
  10941.     --------------------------------------------------
  10942.     TEXT_IO.CREATE (THE_NODE_REPORT, TEXT_IO.OUT_FILE, THE_NODE_REPORT_NAME);
  10943.  
  10944.     --------------------------------------------------
  10945.     -- Put the header to the file
  10946.     --------------------------------------------------
  10947.     WRITE_HEADER_REPORT (TO_FILE    => THE_NODE_REPORT,
  10948.              FORM_NAME  => "NODE_REPORT",
  10949.              PAGE_WIDTH => 89);
  10950.     TEXT_IO.NEW_LINE (THE_NODE_REPORT, 2);
  10951.  
  10952.     TEXT_IO.PUT (THE_NODE_REPORT, "Number of Nodes: ");
  10953.     I_NUMBER.PUT (THE_NODE_REPORT, FINAL_NODE_LIST'LENGTH, WIDTH => 4);
  10954.     TEXT_IO.NEW_LINE (THE_NODE_REPORT, 2);
  10955.  
  10956.  
  10957.     WRITE_NODE_HEADER_LINE
  10958.        (TO_FILE     => THE_NODE_REPORT,
  10959.     NODE        => "Node",
  10960.     EXPECTED    => "Expected",
  10961.     TIME_DATE   => "Time/Date",
  10962.     STND_DEV    => "Standard Dev.",
  10963.     PROBABILITY => INTEGER'IMAGE
  10964.              (INTEGER (PROBABILITY_FOR_OUTPUT * 100.0)) & "%",
  10965.     PTIME_DATE  => "Time/Date",
  10966.     CRIT_INDEX  => "Criticality Index");
  10967.  
  10968.     WRITE_NODE_HEADER_LINE
  10969.        (TO_FILE     => THE_NODE_REPORT,
  10970.     NODE        => "----",
  10971.     EXPECTED    => "--------",
  10972.     TIME_DATE   => "---------",
  10973.     STND_DEV    => "-------------",
  10974.     PROBABILITY => "------",
  10975.     PTIME_DATE  => "---------",
  10976.     CRIT_INDEX  => "-----------------");
  10977.  
  10978.     TEXT_IO.NEW_LINE (THE_NODE_REPORT, 2);
  10979.     TEXT_IO.PUT_LINE (THE_NODE_REPORT, "Data sorted on ---> network topology");
  10980.     TEXT_IO.NEW_LINE (THE_NODE_REPORT);
  10981.  
  10982.  
  10983.     declare
  10984.     EVENT          : EVENT_TYPE;
  10985.     NODE_BODY_LINE : NODE_BODY_LINE_RECORD_TYPE;
  10986.  
  10987.     begin
  10988.     for NODE_INDEX in FINAL_NODE_LIST'RANGE loop
  10989.  
  10990.         EVENT := PERT_OPS.VALUE (FINAL_NODE_LIST (NODE_INDEX));
  10991.  
  10992.         NODE_BODY_LINE.NODE := EVENT.EVENT_ID;
  10993.  
  10994.         NODE_BODY_LINE.EXPECTED := EVENT.SIM_TIME_OF_EVENT;
  10995.  
  10996.         NODE_BODY_LINE.TIME_DATE :=
  10997.           FIND_PROPER_DATE
  10998.          (JULIAN_START_DATE,
  10999.           TO_DAYS (TIME_UNIT_DONE (EVENT.SIM_TIME_OF_EVENT)));
  11000.  
  11001.         NODE_BODY_LINE.STND_DEV := EVENT.VARIANCE ** 0.5;
  11002.  
  11003.         if NODE_BODY_LINE.STND_DEV < 0.01 then
  11004.         NODE_BODY_LINE.STND_DEV := 0.0;
  11005.         end if;
  11006.  
  11007.         NODE_BODY_LINE.PROBABILITY := EVENT.ESTIMATE_TIME_OF_EVENT;
  11008.  
  11009.         NODE_BODY_LINE.PTIME_DATE :=
  11010.           FIND_PROPER_DATE
  11011.          (JULIAN_START_DATE,
  11012.           TO_DAYS (TIME_UNIT_DONE (EVENT.ESTIMATE_TIME_OF_EVENT)));
  11013.  
  11014.         NODE_BODY_LINE.CRIT_INDEX := EVENT.CRIT_PATH_INDEX;
  11015.  
  11016.  
  11017.         WRITE_NODE_BODY_LINE
  11018.            (TO_FILE => THE_NODE_REPORT, A_LINE => NODE_BODY_LINE);
  11019.  
  11020.     end loop;
  11021.  
  11022.     end;
  11023.  
  11024.     TEXT_IO.CLOSE (THE_NODE_REPORT);
  11025.  
  11026. exception
  11027.     when others => 
  11028.     FATAL (UNIT => "Schedule Tool - Unit named " &
  11029.                "[PERT.OUTPUT_VALUES.NODE_REPORT]");
  11030.  
  11031. end NODE_REPORT;
  11032.  
  11033.  
  11034.  
  11035.  
  11036.  
  11037. separate (SCHEDULE.PERT.OUTPUT_VALUES)
  11038. procedure SUM_MAN (FINAL_ACTIVITY_LIST : PERT_OPS.ARC_LIST_TYPE) is
  11039. --------------------------------------------------------------
  11040. -- Authors:  K. Lamarche and T.C. Bryan
  11041. -- Source:     Division Software Technology and Support
  11042. --             Western Development Laboratories
  11043. --             Ford Aerospace & Communications Corporation
  11044. --             ATTN:  Ada Tools Group
  11045. -- Date   :  May 1985
  11046. -- Summary:
  11047. -- This procedure is used to create 2 reports.
  11048. -- 1) a summary report which covers the following sub sections:
  11049. --     stochastic critical path, 
  11050. --     total schedule and associated risk
  11051. --     effort/manpower estimates
  11052. --     cost estimates
  11053. --     network summary metrics
  11054. -- and 2) a manpower report
  11055. --------------------------------------------------------------
  11056.  
  11057.  
  11058.     THE_SUMMARY_REPORT  : TEXT_IO.FILE_TYPE;
  11059.     THE_MANPOWER_REPORT : TEXT_IO.FILE_TYPE;
  11060.  
  11061.  
  11062.     type MANPOWER_REPORT_BODY_LINE_RECORD_TYPE is
  11063.     record
  11064.         WORKING_DAYS : INTEGER;
  11065.         MANPOWER     : FLOAT;
  11066.     end record;
  11067.  
  11068.  
  11069.     type STOCHA_BODY_LINE_RECORD_TYPE is
  11070.     record
  11071.         WBS_CODE : STRING (1 .. 8);
  11072.         ACT_NAME : STRING (12 .. 43);
  11073.         TAIL     : INTEGER;
  11074.         HEAD     : INTEGER;
  11075.         FIN_TIME : FLOAT;
  11076.         FIN_DATE : DATE_AND_TIME.JULIAN_TYPE;
  11077.     end record;
  11078.  
  11079.  
  11080.     type SCHED_A_RISK_BODY_LINE_RECORD_TYPE is
  11081.     record
  11082.         PROBABILITY            : FLOAT;
  11083.         PROBABILITY_DATE       : DATE_AND_TIME.JULIAN_TYPE;
  11084.         OPTIMISTICS            : FLOAT;
  11085.         OPTIMISTICS_DATE       : DATE_AND_TIME.JULIAN_TYPE;
  11086.         EXPECTATIONS           : FLOAT;
  11087.         EXPECTATIONS_DATE      : DATE_AND_TIME.JULIAN_TYPE;
  11088.         PESSIMISTICS           : FLOAT;
  11089.         PESSIMISTICS_DATE      : DATE_AND_TIME.JULIAN_TYPE;
  11090.         STANDARD_DEVIATION     : FLOAT;
  11091.         PROB_REQUIRED_COMPLETE : FLOAT;
  11092.         REQUIRED_DATE          : DATE_AND_TIME.JULIAN_TYPE;
  11093.         TOTAL_EFFORT           : FLOAT;
  11094.         AVERAGE_MANLOAD        : FLOAT;
  11095.         PEAK_MANLOAD_TIME      : FLOAT;
  11096.         PEAK_MANLOAD_DATE      : DATE_AND_TIME.JULIAN_TYPE;
  11097.         PEAK_MANLOAD           : FLOAT;
  11098.         LABOR_COST             : FLOAT;
  11099.         DIRECT_COST            : FLOAT;
  11100.         TOTAL_COST             : FLOAT;
  11101.         AVERAGE_COST           : FLOAT;
  11102.     end record;
  11103.  
  11104.  
  11105.     type NETWORK_SUMMARY_BODY_LINE_RECORD_TYPE is
  11106.     record
  11107.         NUMBER_OF_ARCS     : INTEGER;
  11108.         NUMBER_OF_NODES    : INTEGER;
  11109.         MAX_NUMBER_OF_ARCS : INTEGER;
  11110.         MAX_NUMBER_OF_PARA : INTEGER;
  11111.         MAX_OCCUR_DATE     : DATE_AND_TIME.JULIAN_TYPE;
  11112.         NET_COMPLEX        : FLOAT;
  11113.         STOCHA_COMPLEX     : FLOAT;
  11114.         STOCHA_FREE_SLCK   : FLOAT;
  11115.         SUM_OF_ACT_DURATS  : FLOAT;
  11116.         MAX_ARC            : STRING (1 .. 32);
  11117.         MAX_DURATIONS      : FLOAT;
  11118.         AVERAGE_DURATIONS  : FLOAT;
  11119.         STOCHASTIC_DENSITY : FLOAT;
  11120.         AVG_TIME_WIDTH     : FLOAT;
  11121.     end record;
  11122.  
  11123.  
  11124.  
  11125.     -----------------------------------------------------------------
  11126.     -- output one line of text for the "manpower report".  The text
  11127.     -- is defined by the "manpower_report_body_line_record_type"
  11128.     -----------------------------------------------------------------
  11129.     procedure WRITE_MANPOWER_REPORT_BODY_LINE
  11130.          (TO_FILE : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  11131.           A_LINE  : MANPOWER_REPORT_BODY_LINE_RECORD_TYPE) is
  11132.  
  11133.     WORKING_DAYS_COLUMN : TEXT_IO.COUNT := 14;
  11134.     MANPOWER_COLUMN     : TEXT_IO.COUNT := 44;
  11135.  
  11136.     begin
  11137.  
  11138.     TEXT_IO.SET_COL (TO_FILE, TO => WORKING_DAYS_COLUMN);
  11139.     I_NUMBER.PUT (TO_FILE, A_LINE.WORKING_DAYS, WIDTH => 4);
  11140.     TEXT_IO.SET_COL (TO_FILE, TO => MANPOWER_COLUMN);
  11141.  
  11142.     if A_LINE.MANPOWER <= 0.009 then
  11143.         TEXT_IO.PUT (TO_FILE, "  0.00");
  11144.     else
  11145.         F_NUMBER.PUT
  11146.            (TO_FILE, A_LINE.MANPOWER, EXP => 0, FORE => 3, AFT => 2);
  11147.     end if;
  11148.  
  11149.     TEXT_IO.NEW_LINE (TO_FILE);
  11150.  
  11151.     end WRITE_MANPOWER_REPORT_BODY_LINE;
  11152.  
  11153.  
  11154.  
  11155.     -----------------------------------------------------------
  11156.     -- output the header line for the subsection "Stochastic
  11157.     -- Critical Path" of the "summary report".
  11158.     -----------------------------------------------------------
  11159.     procedure WRITE_STOCHA_HEADER_LINE
  11160.          (TO_FILE  : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  11161.           WBS_CODE : STRING := "WBS Code";
  11162.           ACT_NAME : STRING := "Activity Title";
  11163.           TAIL     : STRING := "Tail";
  11164.           HEAD     : STRING := "Head";
  11165.           FIN_TIME : STRING := "Finish Time";
  11166.           FIN_DATE : STRING := "Finish Date") is
  11167.  
  11168.     begin
  11169.  
  11170.     TEXT_IO.PUT (TO_FILE, WBS_CODE);
  11171.     TEXT_IO.SET_COL (TO_FILE, 19);
  11172.     TEXT_IO.PUT (TO_FILE, ACT_NAME);
  11173.     TEXT_IO.SET_COL (TO_FILE, 45);
  11174.     TEXT_IO.PUT (TO_FILE, TAIL);
  11175.     TEXT_IO.SET_COL (TO_FILE, 51);
  11176.     TEXT_IO.PUT (TO_FILE, HEAD);
  11177.     TEXT_IO.SET_COL (TO_FILE, 57);
  11178.     TEXT_IO.PUT (TO_FILE, FIN_TIME);
  11179.     TEXT_IO.SET_COL (TO_FILE, 70);
  11180.     TEXT_IO.PUT (TO_FILE, FIN_DATE);
  11181.  
  11182.     TEXT_IO.NEW_LINE (TO_FILE);
  11183.  
  11184.     end WRITE_STOCHA_HEADER_LINE;
  11185.  
  11186.  
  11187.     -----------------------------------------------------------
  11188.     -- output a line of text for the subsection "Stochastic
  11189.     -- Critical Path" of the "summary report".  The text is 
  11190.     -- defined by "stocha_body_line_record_type"
  11191.     -----------------------------------------------------------
  11192.     procedure WRITE_STOCHA_BODY_LINE
  11193.          (TO_FILE : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  11194.           A_LINE  : STOCHA_BODY_LINE_RECORD_TYPE) is
  11195.  
  11196.     begin
  11197.     TEXT_IO.PUT (TO_FILE, A_LINE.WBS_CODE);
  11198.     TEXT_IO.SET_COL (TO_FILE, 12);
  11199.     TEXT_IO.PUT (TO_FILE, A_LINE.ACT_NAME);
  11200.     TEXT_IO.SET_COL (TO_FILE, 45);
  11201.     I_NUMBER.PUT (TO_FILE, A_LINE.TAIL, WIDTH => 4);
  11202.     TEXT_IO.SET_COL (TO_FILE, 51);
  11203.     I_NUMBER.PUT (TO_FILE, A_LINE.HEAD, WIDTH => 4);
  11204.     TEXT_IO.SET_COL (TO_FILE, 60);
  11205.  
  11206.     if A_LINE.FIN_TIME <= 0.009 then
  11207.         TEXT_IO.PUT (TO_FILE, " 0.0");
  11208.     else
  11209.         F_NUMBER.PUT
  11210.            (TO_FILE, A_LINE.FIN_TIME, EXP => 0, FORE => 4, AFT => 2);
  11211.     end if;
  11212.  
  11213.     TEXT_IO.SET_COL (TO_FILE, 70);
  11214.     TEXT_IO.PUT (TO_FILE, CONVERT_TO_NORMAL_DATE (A_LINE.FIN_DATE));
  11215.     TEXT_IO.NEW_LINE (TO_FILE);
  11216.  
  11217.     end WRITE_STOCHA_BODY_LINE;
  11218.  
  11219.  
  11220.  
  11221.     -----------------------------------------------------
  11222.     -- output a line of text for the subsections 
  11223.     --      Total Schedule and Associated Risk
  11224.     --      Effort/Manpower Estimates
  11225.     --      Cost Estimates
  11226.     -- of the "summary report".  The text is 
  11227.     -- defined by "sched_a_risk_body_line_record_type"
  11228.     ------------------------------------------------------
  11229.     procedure WRITE_SCHED_A_RISK_BODY_LINE
  11230.          (TO_FILE : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  11231.           A_LINE  : SCHED_A_RISK_BODY_LINE_RECORD_TYPE) is
  11232.  
  11233.  
  11234.     procedure WRITE_RESULT_AND_DATE
  11235.              (WITH_TEXT   : STRING := " ";
  11236.               WITH_RESULT : FLOAT := 0.0;
  11237.               WITH_DATE   : DATE_AND_TIME.JULIAN_TYPE) is
  11238.  
  11239.         LEFT_MARGIN       : TEXT_IO.COUNT := 5;
  11240.         EQUAL_SIGN_COLUMN : TEXT_IO.COUNT := 45;
  11241.         RESULT_COLUMN     : TEXT_IO.COUNT := 53;
  11242.         DATE_COLUMN       : TEXT_IO.COUNT := 68;
  11243.  
  11244.     begin
  11245.         TEXT_IO.SET_COL (TO_FILE, TO => LEFT_MARGIN);
  11246.         TEXT_IO.PUT (TO_FILE, WITH_TEXT);
  11247.         TEXT_IO.SET_COL (TO_FILE, TO => EQUAL_SIGN_COLUMN);
  11248.         TEXT_IO.PUT (TO_FILE, "=");
  11249.         TEXT_IO.SET_COL (TO_FILE, TO => RESULT_COLUMN);
  11250.  
  11251.         if WITH_RESULT <= 0.009 then
  11252.         TEXT_IO.PUT (TO_FILE, "  0.00");
  11253.         else
  11254.         F_NUMBER.PUT
  11255.            (TO_FILE, WITH_RESULT, EXP => 0, FORE => 3, AFT => 2);
  11256.         end if;
  11257.  
  11258.         if WITH_DATE > 0 then
  11259.         TEXT_IO.SET_COL (TO_FILE, TO => DATE_COLUMN);
  11260.         TEXT_IO.PUT (TO_FILE, CONVERT_TO_NORMAL_DATE (WITH_DATE));
  11261.         end if;
  11262.  
  11263.         TEXT_IO.NEW_LINE (TO_FILE, 2);
  11264.     end WRITE_RESULT_AND_DATE;
  11265.  
  11266.  
  11267.     begin
  11268.  
  11269.     TEXT_IO.NEW_LINE (TO_FILE, 2);
  11270.     TEXT_IO.PUT_LINE (TO_FILE, "TOTAL SCHEDULE AND ASSOCIATED RISK");
  11271.     TEXT_IO.PUT_LINE (TO_FILE, "----------------------------------");
  11272.     TEXT_IO.NEW_LINE (TO_FILE);
  11273.  
  11274.     WRITE_RESULT_AND_DATE (WITH_TEXT   =>
  11275.                  INTEGER'IMAGE
  11276.                    (INTEGER (PROBABILITY_FOR_OUTPUT *
  11277.                          100.0)) &
  11278.                  "% Probability Completion Time/Date",
  11279.                    WITH_RESULT => A_LINE.PROBABILITY,
  11280.                    WITH_DATE   => A_LINE.PROBABILITY_DATE);
  11281.  
  11282.     WRITE_RESULT_AND_DATE (WITH_TEXT   => "Optimistic Completion Time/Date",
  11283.                    WITH_RESULT => A_LINE.OPTIMISTICS,
  11284.                    WITH_DATE   => A_LINE.OPTIMISTICS_DATE);
  11285.  
  11286.     WRITE_RESULT_AND_DATE (WITH_TEXT   => "Expected Completion Time/Date",
  11287.                    WITH_RESULT => A_LINE.EXPECTATIONS,
  11288.                    WITH_DATE   => A_LINE.EXPECTATIONS_DATE);
  11289.  
  11290.     WRITE_RESULT_AND_DATE (WITH_TEXT   =>
  11291.                  "Pessimistic Completion Time/Date",
  11292.                    WITH_RESULT => A_LINE.PESSIMISTICS,
  11293.                    WITH_DATE   => A_LINE.PESSIMISTICS_DATE);
  11294.  
  11295.     WRITE_RESULT_AND_DATE (WITH_TEXT   => "Standard Deviation",
  11296.                    WITH_RESULT => A_LINE.STANDARD_DEVIATION,
  11297.                    WITH_DATE   => 0);
  11298.  
  11299.     WRITE_RESULT_AND_DATE (WITH_TEXT   =>
  11300.                  "Required Schedule with" & ASCII.LF &
  11301.                  ASCII.CR & "    probability of completion" &
  11302.                  ASCII.LF & ASCII.CR & "    by scheduled date",
  11303.                    WITH_RESULT => A_LINE.PROB_REQUIRED_COMPLETE,
  11304.                    WITH_DATE   => A_LINE.REQUIRED_DATE);
  11305.  
  11306.  
  11307.     TEXT_IO.NEW_LINE (TO_FILE, 2);
  11308.     TEXT_IO.PUT_LINE (TO_FILE, "EFFORT/MANPOWER ESTIMATES");
  11309.     TEXT_IO.PUT_LINE (TO_FILE, "-------------------------");
  11310.     TEXT_IO.NEW_LINE (TO_FILE);
  11311.     WRITE_RESULT_AND_DATE (WITH_TEXT   => "Total Effort (in man_days)",
  11312.                    WITH_RESULT => A_LINE.TOTAL_EFFORT,
  11313.                    WITH_DATE   => 0);
  11314.  
  11315.     WRITE_RESULT_AND_DATE (WITH_TEXT   => "Average Manload",
  11316.                    WITH_RESULT => A_LINE.AVERAGE_MANLOAD,
  11317.                    WITH_DATE   => 0);
  11318.  
  11319.     WRITE_RESULT_AND_DATE (WITH_TEXT   => "Peak Manload Time/Date",
  11320.                    WITH_RESULT => A_LINE.PEAK_MANLOAD_TIME,
  11321.                    WITH_DATE   => A_LINE.PEAK_MANLOAD_DATE);
  11322.  
  11323.     WRITE_RESULT_AND_DATE (WITH_TEXT   => "Peak Manload",
  11324.                    WITH_RESULT => A_LINE.PEAK_MANLOAD,
  11325.                    WITH_DATE   => 0);
  11326.  
  11327.     TEXT_IO.NEW_PAGE (TO_FILE);
  11328.     TEXT_IO.PUT_LINE (TO_FILE, "COST ESTIMATES");
  11329.     TEXT_IO.PUT_LINE (TO_FILE, "--------------");
  11330.     TEXT_IO.NEW_LINE (TO_FILE);
  11331.     WRITE_RESULT_AND_DATE (WITH_TEXT   => "Direct Labor Cost (in K $)",
  11332.                    WITH_RESULT => A_LINE.LABOR_COST,
  11333.                    WITH_DATE   => 0);
  11334.  
  11335.     WRITE_RESULT_AND_DATE (WITH_TEXT   => "Other Direct Cost (in K $)",
  11336.                    WITH_RESULT => A_LINE.DIRECT_COST,
  11337.                    WITH_DATE   => 0);
  11338.  
  11339.     WRITE_RESULT_AND_DATE (WITH_TEXT   => "Total Cost (in K $)",
  11340.                    WITH_RESULT => A_LINE.TOTAL_COST,
  11341.                    WITH_DATE   => 0);
  11342.  
  11343.     WRITE_RESULT_AND_DATE (WITH_TEXT   => "Average Cost per Man-Hour(in $)",
  11344.                    WITH_RESULT => A_LINE.AVERAGE_COST,
  11345.                    WITH_DATE   => 0);
  11346.  
  11347.     end WRITE_SCHED_A_RISK_BODY_LINE;
  11348.  
  11349.  
  11350.  
  11351.     -----------------------------------------------------
  11352.     -- output a line of text for the subsections 
  11353.     --      Network summary metrics
  11354.     -- of the "summary report".  The text is 
  11355.     -- defined by "network_summary_body_line_record_type"
  11356.     ------------------------------------------------------
  11357.     procedure WRITE_NETWORK_SUMMARY_BODY_LINE
  11358.          (TO_FILE : TEXT_IO.FILE_TYPE := TEXT_IO.CURRENT_OUTPUT;
  11359.           A_LINE  : NETWORK_SUMMARY_BODY_LINE_RECORD_TYPE) is
  11360.  
  11361.     LEFT_MARGIN       : TEXT_IO.COUNT := 5;
  11362.     EQUAL_SIGN_COLUMN : TEXT_IO.COUNT := 55;
  11363.     RESULT_COLUMN     : TEXT_IO.COUNT := 63;
  11364.  
  11365.     procedure WRITE_FLOAT_RESULT (WITH_TEXT   : STRING := " ";
  11366.                       WITH_RESULT : FLOAT := 0.0) is
  11367.  
  11368.  
  11369.     begin
  11370.         TEXT_IO.SET_COL (TO_FILE, TO => LEFT_MARGIN);
  11371.         TEXT_IO.PUT (TO_FILE, WITH_TEXT);
  11372.         TEXT_IO.SET_COL (TO_FILE, TO => EQUAL_SIGN_COLUMN);
  11373.         TEXT_IO.PUT (TO_FILE, "=");
  11374.         TEXT_IO.SET_COL (TO_FILE, TO => RESULT_COLUMN);
  11375.  
  11376.         if WITH_RESULT <= 0.009 then
  11377.         TEXT_IO.PUT (TO_FILE, "  0.00");
  11378.         else
  11379.         F_NUMBER.PUT
  11380.            (TO_FILE, WITH_RESULT, EXP => 0, FORE => 3, AFT => 2);
  11381.         end if;
  11382.  
  11383.         TEXT_IO.NEW_LINE (TO_FILE, 2);
  11384.     end WRITE_FLOAT_RESULT;
  11385.  
  11386.  
  11387.     procedure WRITE_INT_RESULT (WITH_TEXT   : STRING := " ";
  11388.                     WITH_RESULT : INTEGER := 0) is
  11389.  
  11390.  
  11391.     begin
  11392.         TEXT_IO.SET_COL (TO_FILE, TO => LEFT_MARGIN);
  11393.         TEXT_IO.PUT (TO_FILE, WITH_TEXT);
  11394.         TEXT_IO.SET_COL (TO_FILE, TO => EQUAL_SIGN_COLUMN);
  11395.         TEXT_IO.PUT (TO_FILE, "=");
  11396.         TEXT_IO.SET_COL (TO_FILE, TO => RESULT_COLUMN);
  11397.         I_NUMBER.PUT (TO_FILE, WITH_RESULT, WIDTH => 4);
  11398.         TEXT_IO.NEW_LINE (TO_FILE, 2);
  11399.     end WRITE_INT_RESULT;
  11400.     begin
  11401.  
  11402.     TEXT_IO.NEW_LINE (TO_FILE);
  11403.     TEXT_IO.PUT_LINE (TO_FILE, "NETWORK SUMMARY METRICS");
  11404.     TEXT_IO.PUT_LINE (TO_FILE, "-----------------------");
  11405.     TEXT_IO.NEW_LINE (TO_FILE);
  11406.  
  11407.     WRITE_INT_RESULT (WITH_TEXT   => "Number of ARCS  [excludes dummies]",
  11408.               WITH_RESULT => A_LINE.NUMBER_OF_ARCS);
  11409.  
  11410.     WRITE_INT_RESULT (WITH_TEXT   => "Number of NODES",
  11411.               WITH_RESULT => A_LINE.NUMBER_OF_NODES);
  11412.  
  11413.     WRITE_INT_RESULT (WITH_TEXT   =>
  11414.                 "MAX Number of ARCS in any path [includes dummies]",
  11415.               WITH_RESULT => A_LINE.MAX_NUMBER_OF_ARCS);
  11416.  
  11417.     TEXT_IO.SET_COL (TO_FILE, TO => LEFT_MARGIN);
  11418.     TEXT_IO.PUT (TO_FILE, "MAX Number of Parallel Paths");
  11419.     TEXT_IO.SET_COL (TO_FILE, TO => EQUAL_SIGN_COLUMN);
  11420.     TEXT_IO.PUT (TO_FILE, "=");
  11421.     TEXT_IO.SET_COL (TO_FILE, TO => RESULT_COLUMN);
  11422.     I_NUMBER.PUT (TO_FILE, A_LINE.MAX_NUMBER_OF_PARA, WIDTH => 4);
  11423.     TEXT_IO.NEW_LINE (TO_FILE);
  11424.     TEXT_IO.SET_COL (TO_FILE, 10);
  11425.     TEXT_IO.PUT_LINE (TO_FILE,
  11426.               "MAX occurs first on  " &
  11427.               CONVERT_TO_NORMAL_DATE (A_LINE.MAX_OCCUR_DATE));
  11428.     TEXT_IO.NEW_LINE (TO_FILE);
  11429.  
  11430.     WRITE_FLOAT_RESULT (WITH_TEXT   => "Network Complexity",
  11431.                 WITH_RESULT => A_LINE.NET_COMPLEX);
  11432.  
  11433.     WRITE_FLOAT_RESULT (WITH_TEXT   => "Stochastic Complexity",
  11434.                 WITH_RESULT => A_LINE.STOCHA_COMPLEX);
  11435.  
  11436.     WRITE_FLOAT_RESULT (WITH_TEXT   => "Total Stochastic Free Slack",
  11437.                 WITH_RESULT => A_LINE.STOCHA_FREE_SLCK);
  11438.  
  11439.     WRITE_FLOAT_RESULT (WITH_TEXT   => "Sum of all activity durations",
  11440.                 WITH_RESULT => A_LINE.SUM_OF_ACT_DURATS);
  11441.  
  11442.     TEXT_IO.SET_COL (TO_FILE, 5);
  11443.     TEXT_IO.PUT_LINE (TO_FILE, "MAX arc :  " & A_LINE.MAX_ARC);
  11444.     TEXT_IO.SET_COL (TO_FILE, 10);
  11445.     TEXT_IO.PUT (TO_FILE, "MAX duration  =      ");
  11446.  
  11447.     if A_LINE.MAX_DURATIONS <= 0.009 then
  11448.         TEXT_IO.PUT (TO_FILE, "  0.00");
  11449.     else
  11450.         F_NUMBER.PUT
  11451.            (TO_FILE, A_LINE.MAX_DURATIONS, EXP => 0, FORE => 3, AFT => 2);
  11452.     end if;
  11453.  
  11454.     TEXT_IO.NEW_LINE (TO_FILE, 2);
  11455.  
  11456.     WRITE_FLOAT_RESULT (WITH_TEXT   => "Average Duration [no dummies]",
  11457.                 WITH_RESULT => A_LINE.AVERAGE_DURATIONS);
  11458.  
  11459.     WRITE_FLOAT_RESULT (WITH_TEXT   => "Stochastic Density",
  11460.                 WITH_RESULT => A_LINE.STOCHASTIC_DENSITY);
  11461.  
  11462.     WRITE_FLOAT_RESULT (WITH_TEXT   => "Average Time Width",
  11463.                 WITH_RESULT => A_LINE.AVG_TIME_WIDTH);
  11464.     TEXT_IO.NEW_LINE (TO_FILE, 4);
  11465.  
  11466.     TEXT_IO.PUT_LINE (THE_SUMMARY_REPORT, "Note:");
  11467.     TEXT_IO.PUT_LINE (THE_SUMMARY_REPORT,
  11468.               "   (1) SIMPERT global report found in file " &
  11469.               "----------------->   " & THE_SUMMARY_REPORT_NAME);
  11470.  
  11471.     TEXT_IO.PUT_LINE (THE_SUMMARY_REPORT,
  11472.               "   (2) Activity report " &
  11473.               "------------------------------------->   " &
  11474.               THE_ACTIVITY_REPORT_NAME);
  11475.  
  11476.     TEXT_IO.PUT_LINE (THE_SUMMARY_REPORT,
  11477.               "   (3) Node report " &
  11478.               "----------------------------------------->   " &
  11479.               THE_NODE_REPORT_NAME);
  11480.  
  11481.     TEXT_IO.PUT_LINE (THE_SUMMARY_REPORT,
  11482.               "   (4) Data points for manpower curve " &
  11483.               "temporarily in file -->   " &
  11484.               THE_MANPOWER_REPORT_NAME);
  11485.  
  11486.     TEXT_IO.PUT_LINE (THE_SUMMARY_REPORT,
  11487.               "   (5) Input data for Gantt Chart are " &
  11488.               "found in file -------->   " & THE_GANTT_REPORT_NAME);
  11489.  
  11490.     TEXT_IO.PUT_LINE (THE_SUMMARY_REPORT,
  11491.               "   (6) RENAME any of the files.tem  " &
  11492.               "if you want to save them");
  11493.  
  11494.  
  11495.     end WRITE_NETWORK_SUMMARY_BODY_LINE;
  11496.  
  11497.  
  11498.  
  11499.  
  11500.  
  11501. begin
  11502.  
  11503.     TEXT_IO.CREATE (THE_SUMMARY_REPORT, TEXT_IO.OUT_FILE,
  11504.             THE_SUMMARY_REPORT_NAME);
  11505.  
  11506.     ------------------------------------------------------------
  11507.     -- Output the summary report.  A header is output first,
  11508.     -- then a line for each activity.
  11509.     ------------------------------------------------------------
  11510.     declare
  11511.     NODE_LIST    : constant PERT_OPS.NODE_LIST_TYPE :=
  11512.                PERT_OPS.NODES (ON_GRAPH => NETWORK);
  11513.     CURRENT_NODE : PERT_OPS.NODE_TYPE;
  11514.  
  11515.     begin
  11516.     WRITE_HEADER_REPORT (TO_FILE => THE_SUMMARY_REPORT, PAGE_WIDTH => 80);
  11517.  
  11518.     TEXT_IO.NEW_LINE (THE_SUMMARY_REPORT, 2);
  11519.     TEXT_IO.PUT_LINE (THE_SUMMARY_REPORT, "STOCHASTIC CRITICAL PATH:");
  11520.     TEXT_IO.NEW_LINE (THE_SUMMARY_REPORT, 2);
  11521.  
  11522.     WRITE_STOCHA_HEADER_LINE
  11523.        (TO_FILE  => THE_SUMMARY_REPORT,
  11524.         WBS_CODE => "WBS Code",
  11525.         ACT_NAME => "Activity Title",
  11526.         TAIL     => "Tail",
  11527.         HEAD     => "Head",
  11528.         FIN_TIME => "Finish Time",
  11529.         FIN_DATE => "Finish Date");
  11530.  
  11531.     declare
  11532.         THE_UNDER_LINE : STRING (1 .. 80) := (1 .. 80 => '_');
  11533.  
  11534.     begin
  11535.         TEXT_IO.PUT_LINE (THE_SUMMARY_REPORT, THE_UNDER_LINE);
  11536.     end;
  11537.  
  11538.     TEXT_IO.NEW_LINE (THE_SUMMARY_REPORT);
  11539.  
  11540.     ----------------------------------------------------
  11541.     -- Find the Head node for the desired critical path.
  11542.     ----------------------------------------------------
  11543.     for NODE_INDEX in NODE_LIST'RANGE loop
  11544.         CURRENT_NODE := NODE_LIST (NODE_INDEX);
  11545.  
  11546.         if PERT_OPS.VALUE (CURRENT_NODE).EVENT_ID = CRIT_PATH_HEAD_NODE then
  11547.         exit;
  11548.         end if;
  11549.     end loop;
  11550.  
  11551.     while not PERT_OPS."="
  11552.              (CURRENT_NODE, PERT_OPS.START_NODE (NETWORK)) loop
  11553.  
  11554.         declare
  11555.         CURRENT_EVENT_VALUE : EVENT_TYPE :=
  11556.                       PERT_OPS.VALUE (CURRENT_NODE);
  11557.         ARC_LIST            : constant PERT_OPS.ARC_LIST_TYPE :=
  11558.                       PERT_OPS.INCOMING_ARCS
  11559.                      (ON_NODE => CURRENT_NODE);
  11560.         ACTIVITY_ARC        : PERT_OPS.ARC_TYPE :=
  11561.                       ARC_LIST (CURRENT_EVENT_VALUE
  11562.                          .MOST_CRIT_INBOUND_ARC);
  11563.         ACTIVITY            : ACTIVITY_TYPE :=
  11564.                       PERT_OPS.VALUE (ACTIVITY_ARC);
  11565.         STOP_TICK           : INTEGER :=
  11566.                       TIME_UNIT_DONE (ACTIVITY.ESTIMATE_STOP);
  11567.         STOCHA_BODY_LINE    : STOCHA_BODY_LINE_RECORD_TYPE;
  11568.  
  11569.         begin
  11570.         STOCHA_BODY_LINE.WBS_CODE := ACTIVITY.NAME (1 .. 8);
  11571.         STOCHA_BODY_LINE.ACT_NAME := ACTIVITY.NAME (11 .. 42);
  11572.         STOCHA_BODY_LINE.TAIL :=
  11573.           PERT_OPS.VALUE (PERT_OPS.TAIL_NODE (ACTIVITY_ARC)).EVENT_ID;
  11574.         STOCHA_BODY_LINE.HEAD := CURRENT_EVENT_VALUE.EVENT_ID;
  11575.         STOCHA_BODY_LINE.FIN_TIME := ACTIVITY.ESTIMATE_STOP;
  11576.         STOCHA_BODY_LINE.FIN_DATE :=
  11577.           FIND_PROPER_DATE (JULIAN_START_DATE, STOP_TICK);
  11578.         WRITE_STOCHA_BODY_LINE
  11579.            (TO_FILE => THE_SUMMARY_REPORT, A_LINE => STOCHA_BODY_LINE);
  11580.  
  11581.         CURRENT_NODE := PERT_OPS.TAIL_NODE (ACTIVITY_ARC);
  11582.         end;
  11583.     end loop;
  11584.  
  11585.     end;
  11586.  
  11587.     --------------------------------------------
  11588.     -- Output the Risk Information, the Summary.
  11589.     --------------------------------------------
  11590.     OUTPUT_RISK_INFORMATION:
  11591.     declare
  11592.     JULIAN_REQ_COMPLETE                            : DATE_AND_TIME
  11593.                               .JULIAN_TYPE;
  11594.     COMPLETE_PROJECT                               : PERT_OPS.NODE_TYPE :=
  11595.                              PERT_OPS.END_NODE
  11596.                                 (OF_GRAPH =>
  11597.                                    NETWORK);
  11598.     COMPLETE_PROJECT_INFO                          : EVENT_TYPE :=
  11599.                              PERT_OPS.VALUE
  11600.                                 (COMPLETE_PROJECT);
  11601.     TIME_FOR_PROJECT                               : FLOAT;
  11602.     END_PROJECT_TIME_UNIT                          : constant INTEGER :=
  11603.                              TIME_UNIT_DONE
  11604.                                 (COMPLETE_PROJECT_INFO
  11605.                                   .ESTIMATE_TIME_OF_EVENT);
  11606.     LOAD_PER_TIME_UNIT                             : array (1 .. END_PROJECT_TIME_UNIT)
  11607.                                     of FLOAT :=
  11608.                              (1 .. END_PROJECT_TIME_UNIT =>
  11609.                                 0.0);
  11610.     TOTAL_LAB_COST, TOTAL_DIRECT_COST, TOTAL_LABOR : FLOAT := 0.0;
  11611.     PEAK_LOADING                                   : FLOAT := 0.0;
  11612.     PEAK_TIME_UNIT                                 : INTEGER;
  11613.     SUM_OF_ALL_ACTIVITY_TIMES                      : FLOAT := 0.0;
  11614.     NAME_OF_LONGEST_ACTIVITY                       : STRING (1 .. 32);
  11615.     MAX_ACTIVITY_TIME                              : FLOAT := 0.0;
  11616.     MAX_PARALLEL_PATHS                             : INTEGER := 0;
  11617.     MAX_PARALLEL_OCCURANCE                         : DATE_AND_TIME
  11618.                               .JULIAN_TYPE := 1;
  11619.     SCHED_A_RISK_BODY_LINE                         : SCHED_A_RISK_BODY_LINE_RECORD_TYPE;
  11620.  
  11621.     begin
  11622.     SCHED_A_RISK_BODY_LINE.PROBABILITY :=
  11623.       COMPLETE_PROJECT_INFO.ESTIMATE_TIME_OF_EVENT;
  11624.     SCHED_A_RISK_BODY_LINE.PROBABILITY_DATE :=
  11625.       FIND_PROPER_DATE (JULIAN_START_DATE,
  11626.                 TO_DAYS (TIME_UNIT_DONE
  11627.                     (SCHED_A_RISK_BODY_LINE.PROBABILITY)));
  11628.  
  11629.     SCHED_A_RISK_BODY_LINE.OPTIMISTICS :=
  11630.       COMPLETE_PROJECT_INFO.SIM_TIME_OF_EVENT -
  11631.       (3.0 * (COMPLETE_PROJECT_INFO.VARIANCE) ** 0.5);
  11632.     SCHED_A_RISK_BODY_LINE.OPTIMISTICS_DATE :=
  11633.       FIND_PROPER_DATE (JULIAN_START_DATE,
  11634.                 TO_DAYS (TIME_UNIT_DONE
  11635.                     (SCHED_A_RISK_BODY_LINE.OPTIMISTICS)));
  11636.  
  11637.     SCHED_A_RISK_BODY_LINE.EXPECTATIONS :=
  11638.       COMPLETE_PROJECT_INFO.SIM_TIME_OF_EVENT;
  11639.     SCHED_A_RISK_BODY_LINE.EXPECTATIONS_DATE :=
  11640.       FIND_PROPER_DATE (JULIAN_START_DATE,
  11641.                 TO_DAYS (TIME_UNIT_DONE
  11642.                     (SCHED_A_RISK_BODY_LINE.EXPECTATIONS)));
  11643.  
  11644.     SCHED_A_RISK_BODY_LINE.PESSIMISTICS :=
  11645.       COMPLETE_PROJECT_INFO.SIM_TIME_OF_EVENT +
  11646.       (3.0 * (COMPLETE_PROJECT_INFO.VARIANCE) ** 0.5);
  11647.     SCHED_A_RISK_BODY_LINE.PESSIMISTICS_DATE :=
  11648.       FIND_PROPER_DATE (JULIAN_START_DATE,
  11649.                 TO_DAYS (TIME_UNIT_DONE
  11650.                     (SCHED_A_RISK_BODY_LINE.PESSIMISTICS)));
  11651.  
  11652.     SCHED_A_RISK_BODY_LINE.STANDARD_DEVIATION :=
  11653.       COMPLETE_PROJECT_INFO.VARIANCE ** 0.5;
  11654.  
  11655.     -------------------------------------------------
  11656.     -- prompt user for a desired complete date,
  11657.     -- stop date will be used as default otherwise
  11658.     -------------------------------------------------
  11659.     JULIAN_REQ_COMPLETE :=
  11660.       GET_NEW_DATE (WITH_YESNO_PROMPT =>
  11661.               "Do you have " &
  11662.               "a required completion date?  ENTER [y/n]  -->   ",
  11663.             PASSED_DATE       =>
  11664.               SCHED_A_RISK_BODY_LINE.PROBABILITY_DATE,
  11665.             AND_TEXT_PROMPT   => "ENTER required project " &
  11666.                          "completion date");
  11667.  
  11668.     SCHED_A_RISK_BODY_LINE.REQUIRED_DATE :=
  11669.       FIND_PROPER_DATE (JULIAN_REQ_COMPLETE, 1);
  11670.  
  11671.     TIME_FOR_PROJECT := FLOAT (WORKDAYS_BETWEEN
  11672.                       (JULIAN_START_DATE, JULIAN_REQ_COMPLETE));
  11673.  
  11674.     if COMPLETE_PROJECT_INFO.VARIANCE = 0.0 then
  11675.         if TIME_FOR_PROJECT > COMPLETE_PROJECT_INFO.SIM_TIME_OF_EVENT then
  11676.         SCHED_A_RISK_BODY_LINE.PROB_REQUIRED_COMPLETE := 1.0;
  11677.         else
  11678.         SCHED_A_RISK_BODY_LINE.PROB_REQUIRED_COMPLETE := 0.0;
  11679.         end if;
  11680.     else
  11681.         SCHED_A_RISK_BODY_LINE.PROB_REQUIRED_COMPLETE :=
  11682.           MATH_FUNCTIONS.NORMAL_FUNCTION
  11683.          (TIME_DIFFERENCE    =>
  11684.             TIME_FOR_PROJECT - COMPLETE_PROJECT_INFO.SIM_TIME_OF_EVENT,
  11685.           STANDARD_DEVIATION => COMPLETE_PROJECT_INFO.VARIANCE ** 0.5);
  11686.  
  11687.         if SCHED_A_RISK_BODY_LINE.PROB_REQUIRED_COMPLETE < 0.01 then
  11688.         SCHED_A_RISK_BODY_LINE.PROB_REQUIRED_COMPLETE := 0.0;
  11689.         end if;
  11690.     end if;
  11691.  
  11692.     --------------------------------------------------------------
  11693.     -- Figure Total Cost, Total Labor, and Network Summery Metrics.
  11694.     --------------------------------------------------------------
  11695.     FIGURE_TOTALS_AND_MAXES_FROM_ACTIVITY_LIST:
  11696.     declare
  11697.         ACTIVITY             : ACTIVITY_TYPE;
  11698.         DURATION             : FLOAT;
  11699.         NET_ACTIVITY_GAIN    : array (1 .. END_PROJECT_TIME_UNIT)
  11700.                       of INTEGER :=
  11701.                    (1 .. END_PROJECT_TIME_UNIT => 0);
  11702.         PARALLEL_ACCUMULATOR : INTEGER := 0;
  11703.         ACTIVITY_STOP        : INTEGER := 0;
  11704.         ACTIVITY_START       : INTEGER := 0;
  11705.     begin
  11706.         for ACTIVITY_INDEX in FINAL_ACTIVITY_LIST'RANGE loop
  11707.         ACTIVITY := PERT_OPS.VALUE
  11708.                    (FINAL_ACTIVITY_LIST (ACTIVITY_INDEX));
  11709.  
  11710.         ACTIVITY_START := TIME_UNIT_STARTED (ACTIVITY.ESTIMATE_START);
  11711.         ACTIVITY_STOP := TIME_UNIT_DONE (ACTIVITY.ESTIMATE_STOP);
  11712.         DURATION := FLOAT (ACTIVITY_STOP - ACTIVITY_START + 1);
  11713.  
  11714.         TOTAL_LAB_COST :=
  11715.           TOTAL_LAB_COST + ACTIVITY.RATE * ACTIVITY.STAFFING * DURATION;
  11716.  
  11717.         TOTAL_LABOR := TOTAL_LABOR + ACTIVITY.STAFFING * DURATION;
  11718.  
  11719.         if ACTIVITY.STAFFING = 0.0 then
  11720.             TOTAL_DIRECT_COST := TOTAL_DIRECT_COST + ACTIVITY.RATE;
  11721.         end if;
  11722.  
  11723.         SUM_OF_ALL_ACTIVITY_TIMES :=
  11724.           SUM_OF_ALL_ACTIVITY_TIMES + DURATION;
  11725.  
  11726.         if DURATION > MAX_ACTIVITY_TIME then
  11727.             MAX_ACTIVITY_TIME := DURATION;
  11728.             NAME_OF_LONGEST_ACTIVITY := ACTIVITY.NAME (11 .. 42);
  11729.         end if;
  11730.  
  11731.         ACCOUNTING_FOR_STARTING_AND_STOPING_OF_ACTIVITY:
  11732.         begin
  11733.             for TIME_UNIT_INDEX in ACTIVITY_START .. ACTIVITY_STOP loop
  11734.             declare
  11735.                 STAFF : FLOAT
  11736.                      renames LOAD_PER_TIME_UNIT
  11737.                         (TIME_UNIT_INDEX);
  11738.             begin
  11739.                 STAFF := STAFF + ACTIVITY.STAFFING;
  11740.  
  11741.                 if STAFF > PEAK_LOADING then
  11742.                 PEAK_LOADING := STAFF;
  11743.                 PEAK_TIME_UNIT := TIME_UNIT_INDEX;
  11744.                 end if;
  11745.             end;
  11746.             end loop;
  11747.  
  11748.             NET_ACTIVITY_GAIN (ACTIVITY_START) :=
  11749.               NET_ACTIVITY_GAIN (ACTIVITY_START) + 1;
  11750.             NET_ACTIVITY_GAIN (ACTIVITY_STOP) :=
  11751.               NET_ACTIVITY_GAIN (ACTIVITY_STOP) - 1;
  11752.         end ACCOUNTING_FOR_STARTING_AND_STOPING_OF_ACTIVITY;
  11753.  
  11754.         end loop;
  11755.  
  11756.         for TIME_UNIT_INDEX in 1 .. END_PROJECT_TIME_UNIT loop
  11757.         PARALLEL_ACCUMULATOR :=
  11758.           PARALLEL_ACCUMULATOR + NET_ACTIVITY_GAIN (TIME_UNIT_INDEX);
  11759.  
  11760.         if PARALLEL_ACCUMULATOR > MAX_PARALLEL_PATHS then
  11761.             MAX_PARALLEL_PATHS := PARALLEL_ACCUMULATOR;
  11762.             MAX_PARALLEL_OCCURANCE := TIME_UNIT_INDEX;
  11763.         end if;
  11764.         end loop;
  11765.     end FIGURE_TOTALS_AND_MAXES_FROM_ACTIVITY_LIST;
  11766.  
  11767.     SCHED_A_RISK_BODY_LINE.TOTAL_EFFORT := TOTAL_LABOR;
  11768.  
  11769.     SCHED_A_RISK_BODY_LINE.AVERAGE_MANLOAD :=
  11770.       TOTAL_LABOR / COMPLETE_PROJECT_INFO.SIM_TIME_OF_EVENT;
  11771.  
  11772.     SCHED_A_RISK_BODY_LINE.PEAK_MANLOAD_TIME := FLOAT (PEAK_TIME_UNIT);
  11773.  
  11774.     SCHED_A_RISK_BODY_LINE.PEAK_MANLOAD_DATE :=
  11775.       FIND_PROPER_DATE (JULIAN_START_DATE, PEAK_TIME_UNIT);
  11776.  
  11777.     SCHED_A_RISK_BODY_LINE.PEAK_MANLOAD := PEAK_LOADING;
  11778.  
  11779.     SCHED_A_RISK_BODY_LINE.LABOR_COST := TOTAL_LAB_COST / 1000.0;
  11780.  
  11781.     SCHED_A_RISK_BODY_LINE.DIRECT_COST := TOTAL_DIRECT_COST / 1000.0;
  11782.  
  11783.     SCHED_A_RISK_BODY_LINE.TOTAL_COST :=
  11784.       (TOTAL_LAB_COST + TOTAL_DIRECT_COST) / 1000.0;
  11785.  
  11786.     if TOTAL_LABOR /= 0.0 then
  11787.         SCHED_A_RISK_BODY_LINE.AVERAGE_COST :=
  11788.           TOTAL_LAB_COST / (TOTAL_LABOR * FLOAT (TO_DAYS (1)) * 8.0);
  11789.     else
  11790.         SCHED_A_RISK_BODY_LINE.AVERAGE_COST := 0.0;
  11791.     end if;
  11792.  
  11793.  
  11794.     ------------------------------------------------------------------------
  11795.     -- Output the lines for the report: a header, and the report information
  11796.     ------------------------------------------------------------------------
  11797.     WRITE_HEADER_REPORT (TO_FILE => THE_SUMMARY_REPORT, PAGE_WIDTH => 80);
  11798.     TEXT_IO.NEW_LINE (THE_SUMMARY_REPORT, 2);
  11799.  
  11800.     WRITE_SCHED_A_RISK_BODY_LINE
  11801.        (TO_FILE => THE_SUMMARY_REPORT, A_LINE => SCHED_A_RISK_BODY_LINE);
  11802.  
  11803.  
  11804.     ------------------------------------------------------------------------
  11805.     -- Build the output report for the summary listings, output the headers
  11806.     -- and this report.
  11807.     ------------------------------------------------------------------------
  11808.     WRITE_NETWORK_SUMMARY:
  11809.     declare
  11810.         NODE_LIST                 : constant PERT_OPS.NODE_LIST_TYPE :=
  11811.                     PERT_OPS.NODES (ON_GRAPH => NETWORK);
  11812.         NETWORK_SUMMARY_BODY_LINE : NETWORK_SUMMARY_BODY_LINE_RECORD_TYPE;
  11813.     begin
  11814.         NETWORK_SUMMARY_BODY_LINE.NUMBER_OF_ARCS :=
  11815.           FINAL_ACTIVITY_LIST'LENGTH;
  11816.         NETWORK_SUMMARY_BODY_LINE.NUMBER_OF_NODES := NODE_LIST'LENGTH;
  11817.  
  11818.         NETWORK_SUMMARY_BODY_LINE.MAX_NUMBER_OF_ARCS :=
  11819.           COMPLETE_PROJECT_INFO.LONGEST_PATH_TO_EVENT;
  11820.         NETWORK_SUMMARY_BODY_LINE.MAX_NUMBER_OF_PARA := MAX_PARALLEL_PATHS;
  11821.         NETWORK_SUMMARY_BODY_LINE.MAX_OCCUR_DATE :=
  11822.           FIND_PROPER_DATE (JULIAN_START_DATE, MAX_PARALLEL_OCCURANCE);
  11823.  
  11824.         NETWORK_SUMMARY_BODY_LINE.NET_COMPLEX :=
  11825.           1.0 -
  11826.           FLOAT (NETWORK_SUMMARY_BODY_LINE.NUMBER_OF_NODES) /
  11827.           FLOAT (NETWORK_SUMMARY_BODY_LINE.NUMBER_OF_ARCS + 1);
  11828.  
  11829.         if COMPLETE_PROJECT_INFO.VARIANCE = 0.0 then
  11830.         NETWORK_SUMMARY_BODY_LINE.STOCHA_COMPLEX := 1.0;
  11831.         else
  11832.         NETWORK_SUMMARY_BODY_LINE.STOCHA_COMPLEX :=
  11833.           1.0 -
  11834.           2.0 *
  11835.           MATH_FUNCTIONS.NORMAL_FUNCTION
  11836.              ((COMPLETE_PROJECT_INFO.DET_TIME_OF_EVENT -
  11837.                COMPLETE_PROJECT_INFO.SIM_TIME_OF_EVENT),
  11838.               COMPLETE_PROJECT_INFO.VARIANCE ** 0.5);
  11839.  
  11840.         if NETWORK_SUMMARY_BODY_LINE.STOCHA_COMPLEX < 0.0 then
  11841.             NETWORK_SUMMARY_BODY_LINE.STOCHA_COMPLEX := 0.0;
  11842.         end if;
  11843.         end if;
  11844.  
  11845.         NETWORK_SUMMARY_BODY_LINE.STOCHA_FREE_SLCK := TOTAL_FREE_SLACK;
  11846.  
  11847.         NETWORK_SUMMARY_BODY_LINE.SUM_OF_ACT_DURATS :=
  11848.           SUM_OF_ALL_ACTIVITY_TIMES;
  11849.  
  11850.         NETWORK_SUMMARY_BODY_LINE.MAX_ARC := NAME_OF_LONGEST_ACTIVITY;
  11851.  
  11852.         NETWORK_SUMMARY_BODY_LINE.MAX_DURATIONS := MAX_ACTIVITY_TIME;
  11853.  
  11854.         NETWORK_SUMMARY_BODY_LINE.AVERAGE_DURATIONS :=
  11855.           SUM_OF_ALL_ACTIVITY_TIMES / FLOAT (FINAL_ACTIVITY_LIST'LENGTH);
  11856.  
  11857.         NETWORK_SUMMARY_BODY_LINE.STOCHASTIC_DENSITY :=
  11858.           SUM_OF_ALL_ACTIVITY_TIMES /
  11859.           (SUM_OF_ALL_ACTIVITY_TIMES + TOTAL_FREE_SLACK);
  11860.         NETWORK_SUMMARY_BODY_LINE.AVG_TIME_WIDTH :=
  11861.           SUM_OF_ALL_ACTIVITY_TIMES /
  11862.           COMPLETE_PROJECT_INFO.SIM_TIME_OF_EVENT;
  11863.  
  11864.  
  11865.         ------------------------------------------------------
  11866.         -- Write the summary information to the report file.
  11867.         ------------------------------------------------------
  11868.         WRITE_HEADER_REPORT
  11869.            (TO_FILE => THE_SUMMARY_REPORT, PAGE_WIDTH => 80);
  11870.         TEXT_IO.NEW_LINE (THE_SUMMARY_REPORT, 2);
  11871.  
  11872.         WRITE_NETWORK_SUMMARY_BODY_LINE
  11873.            (TO_FILE => THE_SUMMARY_REPORT,
  11874.         A_LINE  => NETWORK_SUMMARY_BODY_LINE);
  11875.  
  11876.     end WRITE_NETWORK_SUMMARY;
  11877.  
  11878.     TEXT_IO.CLOSE (THE_SUMMARY_REPORT);
  11879.  
  11880.  
  11881.     -----------------------------------------------------------
  11882.     -- Do necessary output processing for the manpower report.
  11883.     -----------------------------------------------------------
  11884.     TEXT_IO.CREATE (THE_MANPOWER_REPORT, TEXT_IO.OUT_FILE,
  11885.             THE_MANPOWER_REPORT_NAME);
  11886.  
  11887.     GENERATE_MANPOWER_REPORT:
  11888.     declare
  11889.         MANPOWER_REPORT_BODY_LINE : MANPOWER_REPORT_BODY_LINE_RECORD_TYPE;
  11890.     begin
  11891.         WRITE_HEADER_REPORT
  11892.            (TO_FILE => THE_MANPOWER_REPORT, PAGE_WIDTH => 80);
  11893.  
  11894.         declare
  11895.         WORKING_COLUMN  : TEXT_IO.COUNT := 10;
  11896.         MANPOWER_COLUMN : TEXT_IO.COUNT := 43;
  11897.         begin
  11898.         TEXT_IO.NEW_LINE (THE_MANPOWER_REPORT, 2);
  11899.         TEXT_IO.SET_COL (THE_MANPOWER_REPORT, TO => WORKING_COLUMN);
  11900.         TEXT_IO.PUT (THE_MANPOWER_REPORT,
  11901.                  "Working " & REQUESTED_UNIT_CODE);
  11902.         TEXT_IO.SET_COL (THE_MANPOWER_REPORT, TO => MANPOWER_COLUMN);
  11903.         TEXT_IO.PUT_LINE (THE_MANPOWER_REPORT, "Manpower");
  11904.         TEXT_IO.SET_COL (THE_MANPOWER_REPORT, TO => WORKING_COLUMN);
  11905.         TEXT_IO.PUT (THE_MANPOWER_REPORT, "------------");
  11906.         TEXT_IO.SET_COL (THE_MANPOWER_REPORT, TO => MANPOWER_COLUMN);
  11907.         TEXT_IO.PUT_LINE (THE_MANPOWER_REPORT, "--------");
  11908.         TEXT_IO.NEW_LINE (THE_MANPOWER_REPORT);
  11909.         end;
  11910.  
  11911.         for INDEX in LOAD_PER_TIME_UNIT'RANGE loop
  11912.         MANPOWER_REPORT_BODY_LINE.WORKING_DAYS := INDEX;
  11913.         MANPOWER_REPORT_BODY_LINE.MANPOWER :=
  11914.           LOAD_PER_TIME_UNIT (INDEX);
  11915.         WRITE_MANPOWER_REPORT_BODY_LINE
  11916.            (TO_FILE => THE_MANPOWER_REPORT,
  11917.             A_LINE  => MANPOWER_REPORT_BODY_LINE);
  11918.         end loop;
  11919.  
  11920.         TEXT_IO.CLOSE (THE_MANPOWER_REPORT);
  11921.     end GENERATE_MANPOWER_REPORT;
  11922.  
  11923.  
  11924.     end OUTPUT_RISK_INFORMATION;
  11925.  
  11926. exception
  11927.     when others => 
  11928.     FATAL (UNIT => "Schedule Tool - Unit named " &
  11929.                "[PERT.OUTPUT_VALUES.SUM_MAN]");
  11930.  
  11931. end SUM_MAN;
  11932. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  11933. --outgantt.ada
  11934. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  11935. with TEXT_IO;
  11936. with SCREEN_IO;
  11937. with FILE_OPS;
  11938. with DATE_AND_TIME;
  11939. with FILE_HANDLER;
  11940.  
  11941. separate (SCHEDULE)
  11942. procedure OUT_GANTT is
  11943. -----------------------------------------------------------
  11944. -- Author:     Larry Yelowitz, T. C. Bryan
  11945. -- Source:     Division Software Technology and Support
  11946. --             Western Development Laboratories
  11947. --             Ford Aerospace & Communications Corporation
  11948. --             ATTN:  Ada Tools Group
  11949. -- Date  :     May 25 1985
  11950. -- Summary:    This procedure outputs a Gantt chart based on
  11951. --            data generated during Simpert.
  11952. -----------------------------------------------------------
  11953.  
  11954.     MAX_NUM_ACTIVITIES  : constant INTEGER := 500;
  11955.     MAX_NUM_HOLIDAYS    : constant INTEGER := 100;   -- over lifetime of project
  11956.  
  11957.  
  11958.     CAL_DAYS_PER_PERIOD : constant INTEGER := 91;    --13 weeks per time period
  11959.     WORKDAYS_PER_WEEK   : INTEGER range 5 .. 7;      --read from input file
  11960.     ACTIVITY_COUNTER    : INTEGER range 0 .. 20 := 0; --num activ. per page
  11961.     ACTUAL_NUM_HOLIDAYS : INTEGER range 0 .. MAX_NUM_HOLIDAYS :=
  11962.               MAX_NUM_HOLIDAYS;
  11963.     ------------------------------------------------------------------
  11964.     --later, read in ACTUAL_NUM_HOLIDAYS from input file
  11965.     ------------------------------------------------------------------
  11966.  
  11967.     NUM_CURRENT_HOLIDAYS : INTEGER range 0 .. 50 := 0; --in current period
  11968.     WEEKENDS_PER_PERIOD  : INTEGER range 0 .. 26;
  11969.     START_DAY_INDEX      : INTEGER range 0 .. 6; --day of actual start.
  11970.                          --0 = SUNDAY.
  11971.                          --init from file; then constant
  11972.     NUM_ACTIVITIES       : INTEGER range 1 .. MAX_NUM_ACTIVITIES;
  11973.     NUM_CURRENT_WORKDAYS : INTEGER range 1 .. CAL_DAYS_PER_PERIOD;
  11974.     CAL_DAYS_ELAPSED     : INTEGER := 0;                --update by
  11975.                                   -- CAL_DAYS_PER_PERIOD.
  11976.  
  11977.     PAGE                 : INTEGER := 0; --Number the pages that get printed.
  11978.  
  11979.     subtype PROJECT_DAYS_FOOTER is INTEGER range -5 .. 1090; --footer on each
  11980.                                  -- page
  11981.     subtype PROJECT_DAYS is PROJECT_DAYS_FOOTER range 0 .. 999;
  11982.     ------------------------------------------------------------------
  11983.     --working days into project.
  11984.     ------------------------------------------------------------------
  11985.  
  11986.     type ACTIVITY_INFO is
  11987.     record
  11988.         NAME     : STRING (1 .. 32);
  11989.         START    : PROJECT_DAYS; --start day, based on working days into
  11990.                      -- proj
  11991.         STOP     : PROJECT_DAYS;
  11992.         CRITICAL : BOOLEAN; -- on critical path?
  11993.     end record;
  11994.  
  11995.     type ACTIVITIES_INFO is array (NATURAL range <>) of ACTIVITY_INFO;
  11996.  
  11997.     ------------------------------------------------------------------
  11998.     --  type OUTPUT_SYMBOLS is ('!','H',' ','-', '=', 'T', '^', '*');  
  11999.     --  '*' for potential workdays prior to project start.
  12000.     ------------------------------------------------------------------
  12001.  
  12002.     type WORKDAY_FOOTERS is array (1 .. CAL_DAYS_PER_PERIOD / 7 + 1)
  12003.                    of PROJECT_DAYS_FOOTER;
  12004.  
  12005.     subtype OUTPUT_LINE_INDEX is INTEGER range 0 .. CAL_DAYS_PER_PERIOD;
  12006.     type OUTPUT_LINE is array (OUTPUT_LINE_INDEX) of CHARACTER;
  12007.  
  12008.     type MAPPING is array (1 .. CAL_DAYS_PER_PERIOD) of OUTPUT_LINE_INDEX;
  12009.  
  12010.     subtype JULIAN is DATE_AND_TIME.JULIAN_TYPE; --from date_and_time. 
  12011.     type HOLIDAYS is array (1 .. ACTUAL_NUM_HOLIDAYS) of JULIAN;
  12012.     ------------------------------------------------------------------
  12013.     --TBD  Later, make HOLIDAYS a discr. record based on true value of
  12014.     -- ACTUAL_NUM_HOLIDAYS
  12015.     --only 1..ACTUAL_NUM_HOLIDAYS is valid at any time.
  12016.     ------------------------------------------------------------------
  12017.  
  12018.     SYMBOL     : CHARACTER;
  12019.     ACTIVITIES : ACTIVITIES_INFO (1 .. MAX_NUM_ACTIVITIES);
  12020.     ------------------------------------------------------------------
  12021.     -- make ACTIVITIES a discr. record of 1..NUM_ACTIVITIES
  12022.     ------------------------------------------------------------------
  12023.     WORKDAYS_ELAPSED          : PROJECT_DAYS := 0;
  12024.     PROJ_STOP_DAY             : PROJECT_DAYS; --read from file. Total no.
  12025.                           -- workdays in proj.
  12026.     WORKDAY_FOOTER            : WORKDAY_FOOTERS := (WORKDAY_FOOTERS'RANGE => 0);
  12027.     HOLIDAY_LINE              : OUTPUT_LINE := (others => ' ');
  12028.     ACTIVITY_OUTPUT_LINE      : OUTPUT_LINE; --build up per activity per time
  12029.                          -- period.
  12030.     INITIALIZED_ACTIVITY_LINE : OUTPUT_LINE;
  12031.     ------------------------------------------------------------------
  12032.     --contains weekend and holi symbols per period
  12033.     ------------------------------------------------------------------
  12034.     MAP_VIRTUAL_TO_WORKDAYS : MAPPING;
  12035.     ------------------------------------------------------------------
  12036.     --only 1..NUM_CURRENT_WORKDAYS is valid.
  12037.     -- MVTW(i) denotes index in ACTIVITY_OUTPUT_LINE of ith workday.
  12038.     ------------------------------------------------------------------
  12039.  
  12040.     TENTATIVE_START_INDEX : INTEGER range -999 .. 999;
  12041.     TENTATIVE_STOP_INDEX  : INTEGER range -999 .. 999;
  12042.     ACTIVITY_START_INDEX  : OUTPUT_LINE_INDEX;
  12043.     ACTIVITY_STOP_INDEX   : OUTPUT_LINE_INDEX;
  12044.  
  12045.     DESIRED_CAL_START_DAY : DATE_AND_TIME.CALENDAR_TYPE;
  12046.     HOLI                  : DATE_AND_TIME.CALENDAR_TYPE;
  12047.     DESIRED_START_DAY     : JULIAN;
  12048.     ACTUAL_START_DAY      : JULIAN;
  12049.  
  12050.     JULIAN_HOLIDAYS       : HOLIDAYS; --read from input file and convert to
  12051.                       -- Julian.
  12052.     NORMALIZED_HOLIDAYS   : HOLIDAYS; --relative to actual start day.
  12053.  
  12054.     FILLER_LINE           : OUTPUT_LINE := (others => ' '); --contains symbols
  12055.                                 -- for weekends.
  12056.  
  12057.     type STRING_ACCESS_TYPE is access STRING;
  12058.  
  12059.     ERROR_INDENTATION : TEXT_IO.COUNT := 15;
  12060.  
  12061.     HEADER_TITLE      : constant STRING :=
  12062.             FILE_HANDLER.VERIFY_LABEL
  12063.                (WITH_PROMPT     =>
  12064.                   ASCII.FF & ASCII.LF & ASCII.CR & ASCII.LF &
  12065.                   ASCII.CR & ASCII.LF & ASCII.CR &
  12066.                   "ENTER a Title for the output report." &
  12067.                   "  [60 characters or less]",
  12068.                 STRING_TYPE     => "Title",
  12069.                 LENGTH_OF_LABEL => 60);
  12070.  
  12071.     ------------------------------------------------------------------
  12072.     --header info on each output page
  12073.     ------------------------------------------------------------------
  12074.  
  12075.     DATE_TODAY  : constant STRING := DATE_AND_TIME.CURRENT_DATE;
  12076.  
  12077.     PROB_HEADER : FLOAT;
  12078.  
  12079.     ------------------------------------------------------------------
  12080.     --Declarations for files follow.
  12081.     ------------------------------------------------------------------
  12082.  
  12083.     GANTT_OUTPUT_FILE_NAME : constant STRING :=
  12084.                  FILE_HANDLER.VERIFY_LABEL
  12085.                 (WITH_PROMPT     =>
  12086.                    ASCII.FF & ASCII.LF & ASCII.CR & ASCII.LF &
  12087.                    ASCII.CR & ASCII.LF & ASCII.CR &
  12088.                    "In what file is Gantt output data stored?" &
  12089.                    "  [32 characters or less] -->  ",
  12090.                  STRING_TYPE     => "Title",
  12091.                  LENGTH_OF_LABEL => 32);
  12092.     INPUT_FILE_NAME        : constant STRING :=
  12093.                  FILE_HANDLER.VERIFY_INPUT
  12094.                 (FILE_PROMPT          =>
  12095.                    ASCII.FF & ASCII.LF & ASCII.CR & ASCII.LF &
  12096.                    ASCII.CR & ASCII.LF & ASCII.CR &
  12097.                    "ENTER the name of the file containing " &
  12098.                    "Activity Information" & ASCII.LF &
  12099.                    ASCII.CR & "[32 characters or less].",
  12100.                  MAX_FILE_NAME_LENGTH => 32);
  12101.  
  12102.     HOLIDAY_FILE_NAME      : constant STRING :=
  12103.                  FILE_HANDLER.VERIFY_INPUT
  12104.                 (FILE_PROMPT          =>
  12105.                    ASCII.LF & ASCII.CR & ASCII.LF & ASCII.CR &
  12106.                    ASCII.LF & ASCII.CR &
  12107.                    "ENTER the name of the file containing " &
  12108.                    "Holiday date" & ASCII.LF & ASCII.CR &
  12109.                    "[32 character or less].",
  12110.                  MAX_FILE_NAME_LENGTH => 32);
  12111.  
  12112.     END_VERIFY_OUTPUT, STOP_ON_USER_REQUEST, END_OUT_GANTT : exception;
  12113.  
  12114.     HOLIDAY_FILE : TEXT_IO.FILE_TYPE;
  12115.     INPUT_FILE   : TEXT_IO.FILE_TYPE;
  12116.     OUTPUT_FILE  : TEXT_IO.FILE_TYPE;
  12117.  
  12118.  
  12119.     package INT_IO is new TEXT_IO.INTEGER_IO (INTEGER);
  12120.     package FLT_IO is new TEXT_IO.FLOAT_IO (FLOAT);
  12121.  
  12122.  
  12123.     ------------------------------------------------------------------
  12124.     -- LOCAL SUBPROGRAMS FOLLOW
  12125.     ------------------------------------------------------------------
  12126.  
  12127.     procedure GANTT_INITIALIZE is separate;
  12128.  
  12129.     procedure FILL_HOLIDAY_LINE is separate;
  12130.  
  12131.     procedure INIT_ACTIVITY_LINE is separate;
  12132.  
  12133.     procedure FILL_WORKDAYS_FOOTER is separate;
  12134.  
  12135.     procedure VIRTUAL_MAP is separate;
  12136.  
  12137.     procedure PRINT_HEADER is separate;
  12138.  
  12139.     procedure PRINT_MONTH_DAY_HEADER is separate;
  12140.  
  12141.     procedure PRINT_ACTIVITY (I : INTEGER) is separate;
  12142.  
  12143.     procedure PRINT_FILLER is separate;
  12144.  
  12145.     procedure PRINT_FOOTER is separate;
  12146.  
  12147.     procedure LIMIT_PRINT is separate;
  12148.  
  12149.  
  12150.  
  12151.  
  12152.  
  12153.     procedure VERIFY_OUTPUT_FILE is
  12154.  
  12155.     type YN_TYPE is (Y, YE, YES, N, NO, NONE);
  12156.  
  12157.     function RETURN_YN is new SCREEN_IO.RETURNED_ENUMERATION (YN_TYPE);
  12158.  
  12159.     GO_AHEAD     : BOOLEAN := TRUE;
  12160.  
  12161.     THE_OUT_FILE : TEXT_IO.FILE_TYPE;
  12162.  
  12163.     END_RESET_EXISTING_OUTFILE, STOP_FILES_EXIST : exception;
  12164.  
  12165.  
  12166.     procedure RESET_EXISTING_OUTFILE is
  12167.     begin
  12168.         FILE_OPS.OPEN
  12169.            (THE_FILE         => THE_OUT_FILE,
  12170.         WITH_NAME        => GANTT_OUTPUT_FILE_NAME,
  12171.         TO_MODE          => TEXT_IO.OUT_FILE,
  12172.         CREATION_ENABLED => TRUE);
  12173.  
  12174.         TEXT_IO.DELETE (THE_OUT_FILE);
  12175.     exception
  12176.  
  12177.         when FILE_OPS.SYSTEM_CANNOT_CREATE_FILE => 
  12178.         TEXT_IO.NEW_LINE;
  12179.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  12180.  
  12181.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  12182.         TEXT_IO.PUT_LINE
  12183.            ("Program cannot create [" & GANTT_OUTPUT_FILE_NAME & "]");
  12184.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  12185.         TEXT_IO.PUT_LINE ("due to an access problem.");
  12186.                 PRESS_RETURN_TO_CONTINUE;
  12187.         raise END_RESET_EXISTING_OUTFILE;
  12188.  
  12189.         when FILE_OPS.FILE_ALREADY_OPEN => 
  12190.         TEXT_IO.NEW_LINE;
  12191.         TEXT_IO.PUT_LINE ("INPUT ERROR:");
  12192.  
  12193.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  12194.         TEXT_IO.PUT_LINE
  12195.            ("[" & GANTT_OUTPUT_FILE_NAME & "] is currently in use.");
  12196.  
  12197.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  12198.         TEXT_IO.PUT_LINE ("Program cannot access it");
  12199.                 PRESS_RETURN_TO_CONTINUE;
  12200.         raise END_RESET_EXISTING_OUTFILE;
  12201.  
  12202.     end RESET_EXISTING_OUTFILE;
  12203.  
  12204.  
  12205.     begin
  12206.  
  12207.     if FILE_OPS.FILE_EXISTS (WITH_NAME => GANTT_OUTPUT_FILE_NAME) then
  12208.         TEXT_IO.NEW_LINE (2);
  12209.  
  12210.         if FILE_OPS.FILE_EXISTS (WITH_NAME => GANTT_OUTPUT_FILE_NAME) then
  12211.         TEXT_IO.NEW_LINE;
  12212.         TEXT_IO.PUT ("WARNING !!!  [" & GANTT_OUTPUT_FILE_NAME & "]");
  12213.         TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  12214.         TEXT_IO.PUT_LINE (" will be overwritten.  ");
  12215.         GO_AHEAD := FALSE;
  12216.         end if;
  12217.     end if;
  12218.  
  12219.     if GO_AHEAD then
  12220.         RESET_EXISTING_OUTFILE;
  12221.     else
  12222.         if (RETURN_YN
  12223.            (PROMPT     => ASCII.LF & ASCII.CR &
  12224.                   "Do you wish to CONTINUE?  (y/n) -->  ",
  12225.             DEFAULT    => NONE,
  12226.             FROM_VALUE => Y,
  12227.             TO_VALUE   => NO,
  12228.             ERROR_TEXT => ASCII.LF & ASCII.CR & "INPUT ERROR:  " &
  12229.                   "Answer must be either Y or N." & ASCII.LF &
  12230.                   ASCII.CR) in Y .. YES) then
  12231.         RESET_EXISTING_OUTFILE;
  12232.         else
  12233.         raise STOP_FILES_EXIST;
  12234.  
  12235.         end if;
  12236.     end if;
  12237.  
  12238.     exception
  12239.  
  12240.     when END_RESET_EXISTING_OUTFILE =>
  12241.          raise END_OUT_GANTT;
  12242.  
  12243.     when STOP_FILES_EXIST => 
  12244.         raise STOP_ON_USER_REQUEST;
  12245.  
  12246.     end VERIFY_OUTPUT_FILE;
  12247.  
  12248.     ------------------------------------------------------------------
  12249.     --Begin OUT_GANTT
  12250.     ------------------------------------------------------------------
  12251. begin
  12252.  
  12253.     VERIFY_OUTPUT_FILE;
  12254.  
  12255.     if (INPUT_FILE_NAME = " ") or (HOLIDAY_FILE_NAME = " ") then
  12256.     TEXT_IO.NEW_LINE (2);
  12257.     TEXT_IO.PUT_LINE ("MISSING REQUIRED INPUT-FILE(s) !!!");
  12258.     TEXT_IO.NEW_LINE;
  12259.     TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  12260.     TEXT_IO.PUT_LINE ("Program terminates on user request");
  12261.     TEXT_IO.NEW_LINE (2);
  12262.     raise END_VERIFY_OUTPUT;
  12263.  
  12264.     else
  12265.     GANTT_INITIALIZE;
  12266.     LIMIT_PRINT;
  12267.     FILL_HOLIDAY_LINE;
  12268.     INIT_ACTIVITY_LINE;
  12269.     FILL_WORKDAYS_FOOTER;
  12270.     VIRTUAL_MAP;
  12271.  
  12272.     while WORKDAYS_ELAPSED < PROJ_STOP_DAY loop
  12273.         --main loop, over all time periods
  12274.  
  12275.         ACTIVITY_COUNTER := 0;
  12276.  
  12277.         PRINT_HEADER;
  12278.  
  12279.         PRINT_MONTH_DAY_HEADER;
  12280.  
  12281.         for I in 1 .. NUM_ACTIVITIES loop
  12282.         --20 activities per page for current time period.
  12283.         PRINT_ACTIVITY (I);
  12284.         PRINT_FILLER;
  12285.         ACTIVITY_COUNTER := ACTIVITY_COUNTER + 1;
  12286.  
  12287.         if ACTIVITY_COUNTER = 20 then
  12288.             PRINT_FOOTER;
  12289.             ACTIVITY_COUNTER := 0;
  12290.  
  12291.             if I < NUM_ACTIVITIES then
  12292.             PRINT_HEADER;
  12293.             PRINT_MONTH_DAY_HEADER;
  12294.             end if;
  12295.         end if;
  12296.  
  12297.         end loop;
  12298.  
  12299.  
  12300.         --  All activities have been processed for this time period.
  12301.         --  Now check to see if the final set of activities has to be
  12302.         --  flushed out 
  12303.  
  12304.         if ACTIVITY_COUNTER > 0 then
  12305. --flush out page
  12306.         for I in ACTIVITY_COUNTER + 1 .. 20 loop
  12307.             PRINT_FILLER;
  12308.             PRINT_FILLER; --first one corresponds to printing blank
  12309.                   -- activity.
  12310.         end loop;
  12311.  
  12312.         PRINT_FOOTER;
  12313.         ACTIVITY_COUNTER := 0; --defensive programming
  12314.         end if;
  12315.  
  12316.         --Now reset variables for the next time period.
  12317.  
  12318.         WORKDAYS_ELAPSED := WORKDAYS_ELAPSED + NUM_CURRENT_WORKDAYS;
  12319.         CAL_DAYS_ELAPSED := CAL_DAYS_ELAPSED + CAL_DAYS_PER_PERIOD;
  12320.         FILL_HOLIDAY_LINE;
  12321.         INIT_ACTIVITY_LINE;
  12322.         FILL_WORKDAYS_FOOTER;
  12323.         VIRTUAL_MAP;
  12324.  
  12325.     end loop;
  12326.  
  12327.     FILE_OPS.CLOSE (OUTPUT_FILE);
  12328.     FILE_OPS.CLOSE (INPUT_FILE);
  12329.     FILE_OPS.CLOSE (HOLIDAY_FILE);
  12330.     end if;
  12331.  
  12332. exception
  12333.  
  12334.     when END_VERIFY_OUTPUT | STOP_ON_USER_REQUEST => 
  12335.     null;
  12336.  
  12337.     when END_OUT_GANTT  => 
  12338.     TEXT_IO.NEW_LINE;
  12339.     TEXT_IO.SET_COL (TO => ERROR_INDENTATION);
  12340.     TEXT_IO.PUT_LINE ("A fatal error ocurred.  Program cannot continue.");
  12341.         PRESS_RETURN_TO_CONTINUE;
  12342.  
  12343.     when others => 
  12344.     FATAL (UNIT => "Schedule Tool - Unit named [OUT_GANTT]");
  12345.  
  12346. end OUT_GANTT;
  12347.  
  12348.  
  12349.  
  12350.  
  12351. with SCREEN_IO;
  12352.  
  12353. separate (SCHEDULE.OUT_GANTT)
  12354. procedure GANTT_INITIALIZE is
  12355. -----------------------------------------------------------
  12356. -- Author:     Larry Yelowitz, T. C. Bryan
  12357. -- Source:     Division Software Technology and Support
  12358. --             Western Development Laboratories
  12359. --             Ford Aerospace & Communications Corporation
  12360. --             ATTN:  Ada Tools Group
  12361. -- Date  :     May 25 1985
  12362. -- Summary:    This procedure ...
  12363. -----------------------------------------------------------
  12364.  
  12365.     END_TIME : FLOAT; -- to read in float total project schedule
  12366.     function IS_HOLIDAY (DAY           : JULIAN;
  12367.              PROJ_HOLIDAYS : HOLIDAYS) return BOOLEAN is
  12368.     begin
  12369.     for I in 1 .. ACTUAL_NUM_HOLIDAYS loop
  12370.         if PROJ_HOLIDAYS (I) = DAY then
  12371.         return TRUE;
  12372.  
  12373.         elsif PROJ_HOLIDAYS (I) > DAY then
  12374.         return FALSE;
  12375.         end if;
  12376.     end loop;
  12377.  
  12378.     return FALSE; --DAY is beyond all recorded holidays.
  12379.     end IS_HOLIDAY;
  12380.  
  12381.  
  12382. begin
  12383.     TEXT_IO.OPEN (FILE => INPUT_FILE,
  12384.           NAME => INPUT_FILE_NAME,
  12385.           MODE => TEXT_IO.IN_FILE);
  12386.  
  12387.     TEXT_IO.OPEN (FILE => HOLIDAY_FILE,
  12388.           NAME => HOLIDAY_FILE_NAME,
  12389.           MODE => TEXT_IO.IN_FILE);
  12390.  
  12391.     TEXT_IO.CREATE (FILE => OUTPUT_FILE,
  12392.             NAME => GANTT_OUTPUT_FILE_NAME,
  12393.             MODE => TEXT_IO.OUT_FILE);
  12394.  
  12395.     TEXT_IO.NEW_LINE (2);
  12396.  
  12397.     TEXT_IO.SET_LINE (INPUT_FILE, 23);
  12398.     INT_IO.GET (INPUT_FILE, NUM_ACTIVITIES);
  12399.     TEXT_IO.SET_LINE (INPUT_FILE, 24);
  12400.     FLT_IO.GET (INPUT_FILE, END_TIME);
  12401.     PROJ_STOP_DAY := INTEGER (END_TIME);
  12402.     PROJ_STOP_DAY := PROJ_STOP_DAY + 1;
  12403.     TEXT_IO.SET_LINE (INPUT_FILE, 25);
  12404.     TEXT_IO.SET_COL (INPUT_FILE, 2);
  12405.     INT_IO.GET (INPUT_FILE, WORKDAYS_PER_WEEK);
  12406.     TEXT_IO.SET_LINE (INPUT_FILE, 26);
  12407.     FLT_IO.GET (INPUT_FILE, PROB_HEADER);
  12408.  
  12409.     TEXT_IO.SET_LINE (INPUT_FILE, 27);
  12410.     INT_IO.GET (INPUT_FILE, DESIRED_CAL_START_DAY.DAY);
  12411.     INT_IO.GET (INPUT_FILE, DESIRED_CAL_START_DAY.MONTH);
  12412.     INT_IO.GET (INPUT_FILE, DESIRED_CAL_START_DAY.YEAR);
  12413.  
  12414.     DESIRED_START_DAY := DATE_AND_TIME.JULIAN_DATE (DESIRED_CAL_START_DAY);
  12415.  
  12416.     TEXT_IO.SET_LINE (INPUT_FILE, 36); --start of activities
  12417.  
  12418.     declare
  12419.     C : CHARACTER;
  12420.     begin
  12421.     for I in 1 .. NUM_ACTIVITIES loop
  12422.         TEXT_IO.SET_COL (INPUT_FILE, 12);
  12423.         TEXT_IO.GET (INPUT_FILE, ACTIVITIES (I).NAME);
  12424.         TEXT_IO.SET_COL (INPUT_FILE, 48);
  12425.         TEXT_IO.GET (INPUT_FILE, C);
  12426.  
  12427.         if C = 'C' then
  12428.         ACTIVITIES (I).CRITICAL := TRUE;
  12429.         else
  12430.         ACTIVITIES (I).CRITICAL := FALSE;
  12431.         end if;
  12432.  
  12433.         TEXT_IO.SET_COL (INPUT_FILE, 72);
  12434.         INT_IO.GET (INPUT_FILE, ACTIVITIES (I).START);
  12435.         TEXT_IO.SET_COL (INPUT_FILE, 80);
  12436.         INT_IO.GET (INPUT_FILE, ACTIVITIES (I).STOP);
  12437.  
  12438.         if I < NUM_ACTIVITIES then
  12439.         TEXT_IO.SKIP_LINE (INPUT_FILE);
  12440.         end if;
  12441.     end loop;
  12442.     end;
  12443.     --block
  12444.  
  12445.     --Now read the holiday file
  12446.  
  12447.     ACTUAL_NUM_HOLIDAYS := 0;
  12448.  
  12449.     while not TEXT_IO.END_OF_FILE (HOLIDAY_FILE) loop
  12450.     INT_IO.GET (HOLIDAY_FILE, HOLI.DAY, WIDTH => 2);
  12451.     TEXT_IO.SET_COL (HOLIDAY_FILE, 4);
  12452.     INT_IO.GET (HOLIDAY_FILE, HOLI.MONTH, WIDTH => 2);
  12453.     TEXT_IO.SET_COL (HOLIDAY_FILE, 7);
  12454.     INT_IO.GET (HOLIDAY_FILE, HOLI.YEAR, WIDTH => 2);
  12455.     ACTUAL_NUM_HOLIDAYS := ACTUAL_NUM_HOLIDAYS + 1;
  12456.  
  12457.     if ACTUAL_NUM_HOLIDAYS > MAX_NUM_HOLIDAYS then
  12458.         ACTUAL_NUM_HOLIDAYS := MAX_NUM_HOLIDAYS;
  12459.         exit;
  12460.     end if;
  12461.  
  12462.     JULIAN_HOLIDAYS (ACTUAL_NUM_HOLIDAYS) :=
  12463.       DATE_AND_TIME.JULIAN_DATE (HOLI);
  12464.     TEXT_IO.SKIP_LINE (HOLIDAY_FILE);
  12465.     end loop;
  12466.  
  12467.     --Now compute ACTUAL_START_DAY
  12468.  
  12469.     ACTUAL_START_DAY := DESIRED_START_DAY; --now check for weekend or holiday
  12470.     loop
  12471. --until ACTUAL_START_DAY is past all weekends and holidays
  12472. --first do SAT check
  12473.     if (ACTUAL_START_DAY rem 7) = 6 and WORKDAYS_PER_WEEK = 5 then
  12474.         ACTUAL_START_DAY := ACTUAL_START_DAY + 2; --try Monday
  12475.     elsif (ACTUAL_START_DAY rem 7) = 0 and WORKDAYS_PER_WEEK < 7 then
  12476.         --Sunday
  12477.         ACTUAL_START_DAY := ACTUAL_START_DAY + 1; --try Monday
  12478.     elsif IS_HOLIDAY (ACTUAL_START_DAY, JULIAN_HOLIDAYS) then
  12479.         ACTUAL_START_DAY := ACTUAL_START_DAY + 1; --try next day
  12480.     else
  12481.         exit; --found first available start day
  12482.     end if;
  12483.     end loop;
  12484.  
  12485.     --Now ACTUAL_START_DAY is determined.
  12486.     START_DAY_INDEX := ACTUAL_START_DAY rem 7;
  12487.  
  12488.     --Next, normalize the holidays relative to ACTUAL_START_DAY
  12489.     for I in 1 .. ACTUAL_NUM_HOLIDAYS loop
  12490.     NORMALIZED_HOLIDAYS (I) := JULIAN_HOLIDAYS (I) - ACTUAL_START_DAY;
  12491.     end loop;
  12492.     --some normalized holidays may be negative, but that's OK.
  12493.  
  12494.  
  12495.  
  12496.     --Put the weekend symbol '!' in appropriate places in FILLER_LINE
  12497.  
  12498.     WEEKENDS_PER_PERIOD := 0;
  12499.     FILLER_LINE (CAL_DAYS_PER_PERIOD) := '!'; --right margin
  12500.     if WORKDAYS_PER_WEEK = 5 then
  12501.     for I in 0 .. 12 loop
  12502.         FILLER_LINE (I * 7) := '!'; --Sunday
  12503.         FILLER_LINE (I * 7 + 6) := '!'; --Saturday
  12504.         WEEKENDS_PER_PERIOD := 26;
  12505.     end loop;
  12506.  
  12507.     elsif WORKDAYS_PER_WEEK = 6 then
  12508.     for I in 0 .. 12 loop
  12509.         FILLER_LINE (I * 7) := '!'; --Sundays only
  12510.         WEEKENDS_PER_PERIOD := 13;
  12511.     end loop;
  12512.     end if;
  12513.  
  12514. exception
  12515.     when others => 
  12516.     FATAL (UNIT => "Schedule Tool - Unit named " &
  12517.                "[OUT_GANTT.GANTT_INITIALIZE]");
  12518.  
  12519. end GANTT_INITIALIZE;
  12520.  
  12521.  
  12522.  
  12523.  
  12524. with MENU;
  12525. with SCREEN_IO;
  12526.  
  12527. separate (SCHEDULE.OUT_GANTT)
  12528. procedure LIMIT_PRINT is
  12529. -----------------------------------------------------------------------------
  12530. -- Author:     Larry Yelowitz
  12531. -- Source:     Division Software Technology and Support
  12532. --             Western Development Laboratories
  12533. --             Ford Aerospace & Communications Corporation
  12534. --             ATTN:  Ada Tools Group
  12535. -- Date  :     May 5 1985
  12536. -- Summary:    This procedure allows user to limit the amount of printout 
  12537. --     by specifying print start and stop dates which may be a smaller 
  12538. --     interval than the project start and stop dates read from the 
  12539. --     input file.
  12540. -----------------------------------------------------------------------------
  12541.  
  12542.     NEW_START   : DATE_AND_TIME.CALENDAR_TYPE;
  12543.     NEW_STOP    : DATE_AND_TIME.CALENDAR_TYPE;
  12544.     PRINT_START : DATE_AND_TIME.JULIAN_TYPE;
  12545.     PRINT_STOP  : DATE_AND_TIME.JULIAN_TYPE;
  12546.     USER_CHOICE : POSITIVE;
  12547.  
  12548.     package PRINT_LIMITER is new MENU;
  12549.  
  12550.     TITLE : PRINT_LIMITER.STRING_ACCESS_TYPE;
  12551.  
  12552.     type CHOICES is
  12553.      (HAPPY_WITH_START_STOP_DATES_IN_INPUT_FILE,
  12554.       WANT_TO_INPUT_NEW_PRINT_STARTING_DATE_ONLY,
  12555.       WANT_TO_INPUT_NEW_PRINT_STOPPING_DATE_ONLY,
  12556.       WANT_TO_INPUT_NEW_PRINT_START_STOP_DATES);
  12557.  
  12558.     function PRODUCE_MENU is new PRINT_LIMITER.ENUMERATION_MENU (CHOICES);
  12559.  
  12560.  
  12561.     function GET_NEW_START return DATE_AND_TIME.CALENDAR_TYPE is
  12562.     begin
  12563.     NEW_START.DAY := SCREEN_IO.RETURNED_INTEGER
  12564.                 (PROMPT     => ASCII.LF & ASCII.CR &
  12565.                        "Enter print start day -->  ",
  12566.                  FROM_VALUE => 1,
  12567.                  TO_VALUE   => 31,
  12568.                  CONFIRM    => FALSE);
  12569.  
  12570.     NEW_START.MONTH := SCREEN_IO.RETURNED_INTEGER
  12571.                   (PROMPT     => ASCII.LF & ASCII.CR &
  12572.                          "Enter print start month -->  ",
  12573.                    FROM_VALUE => 1,
  12574.                    TO_VALUE   => 12,
  12575.                    CONFIRM    => FALSE);
  12576.     NEW_START.YEAR := SCREEN_IO.RETURNED_INTEGER
  12577.                  (PROMPT     => ASCII.LF & ASCII.CR &
  12578.                         "Enter print start year -->  ",
  12579.                   FROM_VALUE => 75,
  12580.                   TO_VALUE   => 99,
  12581.                   CONFIRM    => FALSE);
  12582.     return NEW_START;
  12583.     end GET_NEW_START;
  12584.  
  12585.  
  12586.     function GET_NEW_STOP return DATE_AND_TIME.CALENDAR_TYPE is
  12587.     begin
  12588.     NEW_STOP.DAY := SCREEN_IO.RETURNED_INTEGER
  12589.                (PROMPT     => ASCII.LF & ASCII.CR &
  12590.                       "Enter print stop day --> ",
  12591.                 FROM_VALUE => 1,
  12592.                 TO_VALUE   => 31,
  12593.                 CONFIRM    => FALSE);
  12594.  
  12595.     NEW_STOP.MONTH := SCREEN_IO.RETURNED_INTEGER
  12596.                  (PROMPT     => ASCII.LF & ASCII.CR &
  12597.                         "Enter print stop month -->  ",
  12598.                   FROM_VALUE => 1,
  12599.                   TO_VALUE   => 12,
  12600.                   CONFIRM    => FALSE);
  12601.     NEW_STOP.YEAR := SCREEN_IO.RETURNED_INTEGER
  12602.                 (PROMPT     => ASCII.LF & ASCII.CR &
  12603.                        "Enter print stop year -->  ",
  12604.                  FROM_VALUE => 75,
  12605.                  TO_VALUE   => 99,
  12606.                  CONFIRM    => FALSE);
  12607.     return NEW_STOP;
  12608.     end GET_NEW_STOP;
  12609.  
  12610.     function NUMBER_HOLIDAYS (HOLIDAY_LIST : HOLIDAYS;
  12611.                   LOW          : DATE_AND_TIME.JULIAN_TYPE;
  12612.                   HIGH         : DATE_AND_TIME.JULIAN_TYPE)
  12613.                    return INTEGER is
  12614. --return the number of holidays falling between LOW and HIGH inclusive
  12615.     COUNT : INTEGER := 0;
  12616.     begin
  12617.     for I in 1 .. ACTUAL_NUM_HOLIDAYS loop
  12618.         if HOLIDAY_LIST (I) in LOW .. HIGH then
  12619.         COUNT := COUNT + 1;
  12620.         end if;
  12621.     end loop;
  12622.  
  12623.     return COUNT;
  12624.     end NUMBER_HOLIDAYS;
  12625.  
  12626. begin
  12627.     TITLE := new STRING'
  12628.            ("Limit printout by specifying print start or stop date");
  12629.     PRINT_LIMITER.GET_MENU_VALUE (PRODUCE_MENU, TITLE, USER_CHOICE);
  12630.  
  12631.     case USER_CHOICE is
  12632.     when 1 =>  null;
  12633.  
  12634.     when 2 =>  PRINT_START := DATE_AND_TIME.JULIAN_DATE (GET_NEW_START);
  12635.  
  12636.     when 3 =>  PRINT_STOP := DATE_AND_TIME.JULIAN_DATE (GET_NEW_STOP);
  12637.  
  12638.     when 4 => 
  12639.         PRINT_START := DATE_AND_TIME.JULIAN_DATE (GET_NEW_START);
  12640.         PRINT_STOP := DATE_AND_TIME.JULIAN_DATE (GET_NEW_STOP);
  12641.  
  12642.     when others =>  null;
  12643.     end case;
  12644.     --have now received user's choice and inputs.  Next process it.
  12645.  
  12646.     if (USER_CHOICE = 2 or USER_CHOICE = 4) then
  12647. --process new printing starting date
  12648.     if PRINT_START >= ACTUAL_START_DAY then
  12649.         CAL_DAYS_ELAPSED :=
  12650.           DATE_AND_TIME.NEAREST_PRECEDING_MONDAY (PRINT_START);
  12651.         CAL_DAYS_ELAPSED :=
  12652.           CAL_DAYS_ELAPSED -
  12653.           DATE_AND_TIME.NEAREST_PRECEDING_MONDAY (ACTUAL_START_DAY);
  12654.         WORKDAYS_ELAPSED :=
  12655.           CAL_DAYS_ELAPSED -
  12656.           ((CAL_DAYS_ELAPSED / 7) * (7 - WORKDAYS_PER_WEEK));
  12657.         --Workdays_elapsed has now subtracted weekends.
  12658.         WORKDAYS_ELAPSED :=
  12659.           WORKDAYS_ELAPSED -
  12660.           NUMBER_HOLIDAYS (JULIAN_HOLIDAYS, ACTUAL_START_DAY + 1,
  12661.                    DATE_AND_TIME.NEAREST_PRECEDING_MONDAY
  12662.                   (PRINT_START) - 1);
  12663.         --Workdays_elapsed has now subtracted holidays
  12664.         WORKDAYS_ELAPSED := WORKDAYS_ELAPSED - START_DAY_INDEX;
  12665.  
  12666.         if WORKDAYS_PER_WEEK < 7 then
  12667.         WORKDAYS_ELAPSED := WORKDAYS_ELAPSED + 1;
  12668.         --subtracted too much in Start_Day_Index, so add 1 back
  12669.         end if;
  12670.     end if;
  12671.     end if;
  12672.  
  12673.     if (USER_CHOICE = 3) then
  12674.     if PRINT_STOP <
  12675.        DATE_AND_TIME.JULIAN_TYPE (PROJ_STOP_DAY + ACTUAL_START_DAY - 1) then
  12676.         PROJ_STOP_DAY := PRINT_STOP - ACTUAL_START_DAY + 1;
  12677.     end if;
  12678.     end if;
  12679.  
  12680.     if (USER_CHOICE = 4) then
  12681.     if PRINT_STOP >= PRINT_START then
  12682.         PROJ_STOP_DAY := PRINT_STOP - PRINT_START + 1;
  12683.     else
  12684.         PROJ_STOP_DAY := 0;
  12685.     end if;
  12686.     end if;
  12687.  
  12688. exception
  12689.     when others => 
  12690.     FATAL (UNIT => "Schedule Tool - Unit named " &
  12691.                "[OUT_GANTT.LIMIT_PRINT]");
  12692.  
  12693. end LIMIT_PRINT;
  12694.  
  12695.  
  12696.  
  12697.  
  12698.  
  12699. separate (SCHEDULE.OUT_GANTT)
  12700. procedure FILL_HOLIDAY_LINE is
  12701. ----------------------------------------------------------------------------
  12702. -- Author:     Larry Yelowitz
  12703. -- Source:     Division Software Technology and Support
  12704. --             Western Development Laboratories
  12705. --             Ford Aerospace & Communications Corporation
  12706. --             ATTN:  Ada Tools Group
  12707. -- Date  :     May 25 1985
  12708. -- Summary:    This procedure puts 'H' in HOLIDAY_LINE in positions corr.
  12709. --  to holiday in current time period. 
  12710. --  In addition, determine NUM_CURRENT_WORKDAYS and NUM_CURRENT_HOLIDAYS
  12711. ----------------------------------------------------------------------------
  12712.  
  12713. begin
  12714.     NUM_CURRENT_HOLIDAYS := 0;
  12715.     HOLIDAY_LINE := (HOLIDAY_LINE'RANGE => ' ');
  12716.  
  12717.     for I in 1 .. ACTUAL_NUM_HOLIDAYS loop
  12718.     if NORMALIZED_HOLIDAYS (I) in
  12719.        CAL_DAYS_ELAPSED - START_DAY_INDEX ..
  12720.        CAL_DAYS_ELAPSED + 90 - START_DAY_INDEX then
  12721.         HOLIDAY_LINE (NORMALIZED_HOLIDAYS (I) - CAL_DAYS_ELAPSED +
  12722.               START_DAY_INDEX) := 'H';
  12723.  
  12724.         if NORMALIZED_HOLIDAYS (I) > 0 then
  12725.         --only count holidays after proj start
  12726.         NUM_CURRENT_HOLIDAYS := NUM_CURRENT_HOLIDAYS + 1;
  12727.         end if;
  12728.     end if;
  12729.  
  12730.     exit when NORMALIZED_HOLIDAYS (I) >
  12731.           CAL_DAYS_ELAPSED + 90 - START_DAY_INDEX;
  12732.     end loop;
  12733.  
  12734.     --HOLIDAY_LINE is now filled with 'H' as appropriate.
  12735.     --Next determine NUM_CURRENT_WORKDAYS
  12736.  
  12737.     NUM_CURRENT_WORKDAYS := CAL_DAYS_PER_PERIOD - NUM_CURRENT_HOLIDAYS -
  12738.                 WEEKENDS_PER_PERIOD;
  12739.  
  12740.     if CAL_DAYS_ELAPSED = 0 then
  12741.     --for first period only, maybe lose a
  12742.     --few workdays due to midweek project start
  12743.  
  12744.     NUM_CURRENT_WORKDAYS := NUM_CURRENT_WORKDAYS - START_DAY_INDEX;
  12745.  
  12746.     if WORKDAYS_PER_WEEK < 7 then
  12747.         NUM_CURRENT_WORKDAYS := NUM_CURRENT_WORKDAYS + 1;
  12748.         --first Sunday was subtracted twice;  add it back in once.
  12749.     end if;
  12750.     end if;
  12751.  
  12752.     return;
  12753.  
  12754. exception
  12755.     when others => 
  12756.     FATAL (UNIT => "Schedule Tool - Unit named " &
  12757.                "[OUT_GANTT.FILL_HOLIDAY_FILE]");
  12758.  
  12759. end FILL_HOLIDAY_LINE;
  12760.  
  12761.  
  12762.  
  12763.  
  12764.  
  12765. separate (SCHEDULE.OUT_GANTT)
  12766. procedure INIT_ACTIVITY_LINE is
  12767. -----------------------------------------------------------
  12768. -- Author:     Larry Yelowitz
  12769. -- Source:     Division Software Technology and Support
  12770. --             Western Development Laboratories
  12771. --             Ford Aerospace & Communications Corporation
  12772. --             ATTN:  Ada Tools Group
  12773. -- Date  :     May 25 1985
  12774. -- Summary:    This procedure fills INITIALIZED_ACTIVITY_LINE
  12775. --             with weekend and holiday symbols.
  12776. -----------------------------------------------------------
  12777.  
  12778. begin
  12779.     INITIALIZED_ACTIVITY_LINE := FILLER_LINE; --copy weekend markings
  12780.     for I in OUTPUT_LINE_INDEX loop
  12781.     if HOLIDAY_LINE (I) = 'H' then
  12782.         INITIALIZED_ACTIVITY_LINE (I) := 'H'; --copy holiday markings
  12783.     end if;
  12784.     end loop;
  12785.  
  12786.     --Now copy '*' into unused project days during very first week.
  12787.  
  12788.     if WORKDAYS_ELAPSED = 0 then
  12789.     for I in 0 .. START_DAY_INDEX - 1 loop
  12790.         if INITIALIZED_ACTIVITY_LINE (I) = ' ' then
  12791.         INITIALIZED_ACTIVITY_LINE (I) := '*';
  12792.         end if;
  12793.     end loop;
  12794.     end if;
  12795.  
  12796. exception
  12797.     when others => 
  12798.     FATAL (UNIT => "Schedule Tool - Unit named " &
  12799.                "[OUT_GANTT.INIT_ACTIVITY_LINE]");
  12800.  
  12801.  
  12802. end INIT_ACTIVITY_LINE;
  12803.  
  12804.  
  12805.  
  12806.  
  12807.  
  12808. separate (SCHEDULE.OUT_GANTT)
  12809. procedure FILL_WORKDAYS_FOOTER is
  12810. -----------------------------------------------------------------------------
  12811. -- Author:     Larry Yelowitz
  12812. -- Source:     Division Software Technology and Support
  12813. --             Western Development Laboratories
  12814. --             Ford Aerospace & Communications Corporation
  12815. --             ATTN:  Ada Tools Group
  12816. -- Date  :     May 25 1985
  12817. -- Summary:    This procedure computes number of project days into the
  12818. --   effort for each of the 13 weeks -- in the current time period.
  12819. --   And prints the information at the footer on each output page.
  12820. -----------------------------------------------------------------------------
  12821.  
  12822.     function NON_WORKDAYS (I : INTEGER) return INTEGER is
  12823.     COUNT : INTEGER := 0;
  12824.     begin
  12825.     for J in ((I - 2) * 7) .. ((I - 2) * 7 + 6) loop
  12826. --count nonworkdays in previous week
  12827.         if INITIALIZED_ACTIVITY_LINE (J) /= ' ' then
  12828.         COUNT := COUNT + 1;
  12829.         end if;
  12830.     end loop;
  12831.  
  12832.     return COUNT;
  12833.     end NON_WORKDAYS;
  12834.  
  12835.  
  12836. begin
  12837.     WORKDAY_FOOTER (1) := WORKDAYS_ELAPSED + 1;
  12838.  
  12839.     for I in 2 .. 14 loop
  12840.     WORKDAY_FOOTER (I) := WORKDAY_FOOTER (I - 1) + 7 - NON_WORKDAYS (I);
  12841.     end loop;
  12842.     --WORKDAY_FOOTER(14) now = workdays elapsed for next iteration.
  12843.  
  12844. exception
  12845.     when others => 
  12846.     FATAL (UNIT => "Schedule Tool - Unit named " &
  12847.                "[OUT_GANTT.FILL_WORKDAYS_FOOTER]");
  12848.  
  12849.  
  12850. end FILL_WORKDAYS_FOOTER;
  12851.  
  12852.  
  12853.  
  12854.  
  12855.  
  12856. separate (SCHEDULE.OUT_GANTT)
  12857. procedure VIRTUAL_MAP is
  12858. -----------------------------------------------------------------------------
  12859. -- Author:     Larry Yelowitz
  12860. -- Source:     Division Software Technology and Support
  12861. --             Western Development Laboratories
  12862. --             Ford Aerospace & Communications Corporation
  12863. --             ATTN:  Ada Tools Group
  12864. -- Date  :     May 25 1985
  12865. -- Summary:    This procedure fills in the array MAP_VIRTUAL_TO_WORKDAYS.
  12866. --     The ith index of this array will contain the index value corresponding
  12867. --     to the ith available workday in INITIALIZED_ACTIVITY_LINE.
  12868. -----------------------------------------------------------------------------
  12869.  
  12870.     J : INTEGER := 0;
  12871. begin
  12872.     for I in 1 .. NUM_CURRENT_WORKDAYS loop
  12873. --find index of ith workday in INITIALIZED_ACTIVITY_LINE.
  12874.     while INITIALIZED_ACTIVITY_LINE (J) /= ' ' loop
  12875.         J := J + 1;
  12876.         exit when J > 91; --defensive
  12877.     end loop;
  12878.  
  12879.     --should do some defensive checking that j <= 91.  
  12880.  
  12881.     MAP_VIRTUAL_TO_WORKDAYS (I) := J;
  12882.     J := J + 1;
  12883.     end loop;
  12884.  
  12885. exception
  12886.     when others => 
  12887.     FATAL (UNIT => "Schedule Tool - Unit named " &
  12888.                "[OUT_GANTT.VIRTUAL_MAP]");
  12889.  
  12890. end VIRTUAL_MAP;
  12891.  
  12892.  
  12893.  
  12894.  
  12895.  
  12896. separate (SCHEDULE.OUT_GANTT)
  12897. procedure PRINT_HEADER is
  12898. -----------------------------------------------------------
  12899. -- Author:     Larry Yelowitz
  12900. -- Source:     Division Software Technology and Support
  12901. --             Western Development Laboratories
  12902. --             Ford Aerospace & Communications Corporation
  12903. --             ATTN:  Ada Tools Group
  12904. -- Date  :     May 25 1985
  12905. -- Summary:    This procedure prints topmost header at
  12906. --             beginning of each page of output
  12907. -----------------------------------------------------------
  12908.  
  12909.     LEFT_COLON  : TEXT_IO.COUNT := 31;
  12910.     LEFT        : TEXT_IO.COUNT := 35;
  12911.     CENTER      : TEXT_IO.COUNT := 60;
  12912.     RIGHT       : TEXT_IO.COUNT := 82;
  12913.     RIGHT_COLON : TEXT_IO.COUNT := 109;
  12914.     MOST_RIGHT  : TEXT_IO.COUNT := 113;
  12915.  
  12916. begin
  12917.     PAGE := PAGE + 1;
  12918.     TEXT_IO.NEW_LINE (OUTPUT_FILE, 2);
  12919.     TEXT_IO.SET_COL (OUTPUT_FILE, CENTER);
  12920.     TEXT_IO.PUT (OUTPUT_FILE, "GANTT CHART");
  12921.     TEXT_IO.SET_COL (OUTPUT_FILE, RIGHT);
  12922.     TEXT_IO.PUT (OUTPUT_FILE, "Page#");
  12923.     TEXT_IO.SET_COL (OUTPUT_FILE, RIGHT_COLON);
  12924.     TEXT_IO.PUT (OUTPUT_FILE, ":");
  12925.     TEXT_IO.SET_COL (OUTPUT_FILE, MOST_RIGHT);
  12926.     INT_IO.PUT (OUTPUT_FILE, PAGE, WIDTH => 3);
  12927.  
  12928.     TEXT_IO.NEW_LINE (OUTPUT_FILE, 2);
  12929.     TEXT_IO.PUT (OUTPUT_FILE, "Input File");
  12930.     TEXT_IO.SET_COL (OUTPUT_FILE, LEFT_COLON);
  12931.     TEXT_IO.PUT (OUTPUT_FILE, ":");
  12932.     TEXT_IO.SET_COL (OUTPUT_FILE, LEFT);
  12933.     TEXT_IO.PUT (OUTPUT_FILE, INPUT_FILE_NAME);
  12934.     TEXT_IO.SET_COL (OUTPUT_FILE, RIGHT);
  12935.     TEXT_IO.PUT (OUTPUT_FILE, "Date Today");
  12936.     TEXT_IO.SET_COL (OUTPUT_FILE, RIGHT_COLON);
  12937.     TEXT_IO.PUT (OUTPUT_FILE, ":");
  12938.     TEXT_IO.SET_COL (OUTPUT_FILE, MOST_RIGHT);
  12939.     TEXT_IO.PUT (OUTPUT_FILE, DATE_TODAY);
  12940.  
  12941.     TEXT_IO.NEW_LINE (OUTPUT_FILE);
  12942.     TEXT_IO.PUT (OUTPUT_FILE, "Project Start Date (dd/mm/yy)");
  12943.     TEXT_IO.SET_COL (OUTPUT_FILE, LEFT_COLON);
  12944.     TEXT_IO.PUT (OUTPUT_FILE, ":");
  12945.     TEXT_IO.SET_COL (OUTPUT_FILE, LEFT);
  12946.     INT_IO.PUT (OUTPUT_FILE, DESIRED_CAL_START_DAY.DAY, WIDTH => 3);
  12947.     INT_IO.PUT (OUTPUT_FILE, DESIRED_CAL_START_DAY.MONTH, WIDTH => 3);
  12948.     INT_IO.PUT (OUTPUT_FILE, DESIRED_CAL_START_DAY.YEAR, WIDTH => 3);
  12949.     TEXT_IO.SET_COL (OUTPUT_FILE, RIGHT);
  12950.     TEXT_IO.PUT (OUTPUT_FILE, "Probability of Completion:");
  12951.     TEXT_IO.SET_COL (OUTPUT_FILE, RIGHT_COLON);
  12952.     TEXT_IO.PUT (OUTPUT_FILE, ":");
  12953.     TEXT_IO.SET_COL (OUTPUT_FILE, MOST_RIGHT);
  12954.     FLT_IO.PUT (OUTPUT_FILE, PROB_HEADER, EXP => 0, FORE => 2, AFT => 2);
  12955.  
  12956.     TEXT_IO.NEW_LINE (OUTPUT_FILE);
  12957.     TEXT_IO.PUT (OUTPUT_FILE, "Project Title");
  12958.     TEXT_IO.SET_COL (OUTPUT_FILE, LEFT_COLON);
  12959.     TEXT_IO.PUT (OUTPUT_FILE, ":");
  12960.     TEXT_IO.SET_COL (OUTPUT_FILE, LEFT);
  12961.     TEXT_IO.PUT_LINE (OUTPUT_FILE, HEADER_TITLE);
  12962.  
  12963.     TEXT_IO.NEW_LINE (OUTPUT_FILE, 2);
  12964.     TEXT_IO.PUT (OUTPUT_FILE, "Legend");
  12965.     TEXT_IO.SET_COL (OUTPUT_FILE, LEFT_COLON);
  12966.     TEXT_IO.PUT (OUTPUT_FILE, ":");
  12967.  
  12968.     TEXT_IO.SET_COL (OUTPUT_FILE, LEFT);
  12969.     TEXT_IO.PUT (OUTPUT_FILE, "H     -->    holiday");
  12970.     TEXT_IO.SET_COL (OUTPUT_FILE, RIGHT);
  12971.     TEXT_IO.PUT_LINE (OUTPUT_FILE, "-     -->    non-critical activity");
  12972.  
  12973.     TEXT_IO.SET_COL (OUTPUT_FILE, LEFT);
  12974.     TEXT_IO.PUT (OUTPUT_FILE, "=     -->    critical activity");
  12975.     TEXT_IO.SET_COL (OUTPUT_FILE, RIGHT);
  12976.     TEXT_IO.PUT_LINE (OUTPUT_FILE, "^     -->    project start or stop");
  12977.  
  12978.     TEXT_IO.SET_COL (OUTPUT_FILE, LEFT);
  12979.     TEXT_IO.PUT_LINE (OUTPUT_FILE, 
  12980.      "*     -->    day(s) of first week not used");
  12981.     TEXT_IO.NEW_LINE (OUTPUT_FILE, 2);
  12982.  
  12983. exception
  12984.     when others => 
  12985.     FATAL (UNIT => "Schedule Tool - Unit named " &
  12986.                "[OUT_GANTT.PRINT_HEADER]");
  12987.  
  12988. end PRINT_HEADER;
  12989.  
  12990.  
  12991.  
  12992.  
  12993.  
  12994. separate (SCHEDULE.OUT_GANTT)
  12995. procedure PRINT_FILLER is
  12996. -----------------------------------------------------------
  12997. -- Author:     Larry Yelowitz
  12998. -- Source:     Division Software Technology and Support
  12999. --             Western Development Laboratories
  13000. --             Ford Aerospace & Communications Corporation
  13001. --             ATTN:  Ada Tools Group
  13002. -- Date  :     May 25 1985
  13003. -- Summary:    This procedure prints line between activities
  13004. --             containing only weekend and border markings.
  13005. -----------------------------------------------------------
  13006.  
  13007. begin
  13008.     TEXT_IO.PUT (OUTPUT_FILE, '!');
  13009.     TEXT_IO.SET_COL (OUTPUT_FILE, 34); -- Skip over 32 char name field 
  13010.     for I in FILLER_LINE'RANGE loop
  13011.     TEXT_IO.PUT (OUTPUT_FILE, FILLER_LINE (I));
  13012.     end loop;
  13013.  
  13014.     TEXT_IO.NEW_LINE (OUTPUT_FILE);
  13015.  
  13016. exception
  13017.     when others => 
  13018.     FATAL (UNIT => "Schedule Tool - Unit named " &
  13019.                "[OUT_GANTT.PRINT_FILLER]");
  13020.  
  13021. end PRINT_FILLER;
  13022.  
  13023.  
  13024.  
  13025.  
  13026.  
  13027. separate (SCHEDULE.OUT_GANTT)
  13028. procedure PRINT_ACTIVITY (I : INTEGER) is
  13029. -----------------------------------------------------------
  13030. -- Author:     Larry Yelowitz
  13031. -- Source:     Division Software Technology and Support
  13032. --             Western Development Laboratories
  13033. --             Ford Aerospace & Communications Corporation
  13034. --             ATTN:  Ada Tools Group
  13035. -- Date  :     May 25 1985
  13036. -- Summary:    This procedure fills in ACTIVITY_OUTPUT_LINE 
  13037. --             for the current activity, then print it.
  13038. -----------------------------------------------------------
  13039.  
  13040.     procedure FILL_ACT_OUT_LINE (I : INTEGER) is
  13041.  
  13042.     begin
  13043. --check if activity start day overlaps current time period
  13044.     if ACTIVITIES (I).CRITICAL then
  13045.         SYMBOL := '=';
  13046.     else
  13047.         SYMBOL := '-';
  13048.     end if;
  13049.  
  13050.     TENTATIVE_START_INDEX := ACTIVITIES (I).START - WORKDAYS_ELAPSED;
  13051.     TENTATIVE_STOP_INDEX := ACTIVITIES (I).STOP - WORKDAYS_ELAPSED;
  13052.  
  13053.     if TENTATIVE_START_INDEX in 1 .. NUM_CURRENT_WORKDAYS then
  13054.         ACTIVITY_START_INDEX :=
  13055.           MAP_VIRTUAL_TO_WORKDAYS (TENTATIVE_START_INDEX);
  13056.         ACTIVITY_OUTPUT_LINE (ACTIVITY_START_INDEX) := '^';
  13057.         --now check if stop day also overlaps current time period.
  13058.         if TENTATIVE_STOP_INDEX in 1 .. NUM_CURRENT_WORKDAYS then
  13059.         ACTIVITY_STOP_INDEX :=
  13060.           MAP_VIRTUAL_TO_WORKDAYS (TENTATIVE_STOP_INDEX);
  13061.         ACTIVITY_OUTPUT_LINE (ACTIVITY_STOP_INDEX) := '^';
  13062.  
  13063.         for J in TENTATIVE_START_INDEX + 1 ..
  13064.              TENTATIVE_STOP_INDEX - 1 loop
  13065.             ACTIVITY_OUTPUT_LINE (MAP_VIRTUAL_TO_WORKDAYS (J)) :=
  13066.               SYMBOL;
  13067.         end loop;
  13068.         else
  13069. --start overlaps, but stop date extends into future time period.
  13070.         for J in TENTATIVE_START_INDEX + 1 .. NUM_CURRENT_WORKDAYS loop
  13071.             --fill in remainder of this activity with SYMBOL
  13072.             ACTIVITY_OUTPUT_LINE (MAP_VIRTUAL_TO_WORKDAYS (J)) :=
  13073.               SYMBOL;
  13074.         end loop;
  13075.         end if;
  13076.  
  13077.     elsif TENTATIVE_STOP_INDEX in 1 .. NUM_CURRENT_WORKDAYS then
  13078.         --start day does not overlap, but stop day does
  13079.         ACTIVITY_STOP_INDEX :=
  13080.           MAP_VIRTUAL_TO_WORKDAYS (TENTATIVE_STOP_INDEX);
  13081.         ACTIVITY_OUTPUT_LINE (ACTIVITY_STOP_INDEX) := '^';
  13082.  
  13083.         for J in 1 .. TENTATIVE_STOP_INDEX - 1 loop
  13084.         ACTIVITY_OUTPUT_LINE (MAP_VIRTUAL_TO_WORKDAYS (J)) := SYMBOL;
  13085.         end loop;
  13086.  
  13087.     elsif TENTATIVE_START_INDEX < 1 and
  13088.           TENTATIVE_STOP_INDEX > NUM_CURRENT_WORKDAYS then
  13089. --neither start nor stop day overlaps.  See if activity spans
  13090. --entire time period.
  13091.  
  13092.         for J in 1 .. NUM_CURRENT_WORKDAYS loop
  13093.         ACTIVITY_OUTPUT_LINE (MAP_VIRTUAL_TO_WORKDAYS (J)) := SYMBOL;
  13094.  
  13095.         end loop;
  13096.     end if;
  13097.     end FILL_ACT_OUT_LINE;
  13098.  
  13099. begin
  13100.     ACTIVITY_OUTPUT_LINE := INITIALIZED_ACTIVITY_LINE; --copy weekend/holi marks
  13101.     FILL_ACT_OUT_LINE (I);
  13102.     --Now take other actions to print out the activity name, 
  13103.     --plus ACTIVITY_OUTPUT_LINE.  
  13104.  
  13105.     TEXT_IO.PUT (OUTPUT_FILE, '!');
  13106.     TEXT_IO.PUT (OUTPUT_FILE, ACTIVITIES (I).NAME);
  13107.  
  13108.     for I in ACTIVITY_OUTPUT_LINE'RANGE loop
  13109.     TEXT_IO.PUT (OUTPUT_FILE, ACTIVITY_OUTPUT_LINE (I));
  13110.     end loop;
  13111.  
  13112.     TEXT_IO.NEW_LINE (OUTPUT_FILE);
  13113.  
  13114. exception
  13115.     when others => 
  13116.     FATAL (UNIT => "Schedule Tool - Unit named " &
  13117.                "[OUT_GANTT.PRINT_ACTIVITY]");
  13118.  
  13119. end PRINT_ACTIVITY;
  13120.  
  13121.  
  13122.  
  13123.  
  13124. separate (SCHEDULE.OUT_GANTT)
  13125. procedure PRINT_MONTH_DAY_HEADER is
  13126. -----------------------------------------------------------
  13127. -- Author:     Larry Yelowitz
  13128. -- Source:     Division Software Technology and Support
  13129. --             Western Development Laboratories
  13130. --             Ford Aerospace & Communications Corporation
  13131. --             ATTN:  Ada Tools Group
  13132. -- Date  :     May 25 1985
  13133. -- Summary:    This procedure prints calendar data near the
  13134. --             top of each output page.
  13135. -----------------------------------------------------------
  13136.  
  13137.     CAL_DAYS_INTO_PROJECT : JULIAN;
  13138.     HEADER                : array (1 .. CAL_DAYS_PER_PERIOD / 7)
  13139.                    of DATE_AND_TIME.CALENDAR_TYPE;
  13140.  
  13141.     procedure SPACE (I : INTEGER) is
  13142.     begin
  13143.     for J in 1 .. I loop
  13144.         TEXT_IO.PUT (OUTPUT_FILE, ' ');
  13145.     end loop;
  13146.     end SPACE;
  13147.  
  13148.  
  13149. begin
  13150.     CAL_DAYS_INTO_PROJECT := CAL_DAYS_ELAPSED + ACTUAL_START_DAY -
  13151.                  START_DAY_INDEX + 1;
  13152.     -- julian of first monday of the time period.
  13153.  
  13154.     for I in HEADER'RANGE loop
  13155.     HEADER (I) := DATE_AND_TIME.CALENDAR_DATE
  13156.              (CAL_DAYS_INTO_PROJECT + JULIAN ((I - 1) * 7));
  13157.     end loop;
  13158.  
  13159.  
  13160.     TEXT_IO.PUT (OUTPUT_FILE, '+');
  13161.  
  13162.     for I in 1 .. 123 loop
  13163.     TEXT_IO.PUT (OUTPUT_FILE, '-');
  13164.     end loop;
  13165.  
  13166.     TEXT_IO.PUT_LINE (OUTPUT_FILE, "+");
  13167.  
  13168.  
  13169.  
  13170.     TEXT_IO.PUT (OUTPUT_FILE, '!');
  13171.     TEXT_IO.SET_COL (OUTPUT_FILE, 28);
  13172.     TEXT_IO.PUT (OUTPUT_FILE, "MONTH !");
  13173.     INT_IO.PUT (OUTPUT_FILE, HEADER (1).MONTH, WIDTH => 3);
  13174.     INT_IO.PUT (OUTPUT_FILE, HEADER (1).YEAR, WIDTH => 3);
  13175.  
  13176.     for I in 2 .. HEADER'LAST loop
  13177.     if HEADER (I).MONTH = HEADER (I - 1).MONTH then
  13178.         SPACE (7);
  13179.     else
  13180.         TEXT_IO.PUT (OUTPUT_FILE, '!');
  13181.         INT_IO.PUT (OUTPUT_FILE, HEADER (I).MONTH, WIDTH => 3);
  13182.  
  13183.         if HEADER (I).MONTH = 1 then
  13184.         INT_IO.PUT (OUTPUT_FILE, HEADER (I).YEAR, WIDTH => 3);
  13185.         else
  13186.         SPACE (3);
  13187.         end if;
  13188.     end if;
  13189.     end loop;
  13190.  
  13191.     TEXT_IO.PUT_LINE (OUTPUT_FILE, "!");
  13192.     --Month, year line has been printed; now print day line.
  13193.  
  13194.     TEXT_IO.PUT (OUTPUT_FILE, '!');
  13195.     TEXT_IO.SET_COL (OUTPUT_FILE, 29);
  13196.     TEXT_IO.PUT (OUTPUT_FILE, "DATE ");
  13197.  
  13198.     for I in HEADER'RANGE loop
  13199.     TEXT_IO.PUT (OUTPUT_FILE, '!');
  13200.     INT_IO.PUT (OUTPUT_FILE, HEADER (I).DAY, WIDTH => 2);
  13201.     SPACE (4);
  13202.     end loop;
  13203.  
  13204.     TEXT_IO.PUT_LINE (OUTPUT_FILE, "!");
  13205.  
  13206.  
  13207.     --copy text from print footer to print bottom line
  13208.  
  13209.     TEXT_IO.PUT (OUTPUT_FILE, '+');
  13210.  
  13211.     for I in 1 .. 32 loop
  13212.     TEXT_IO.PUT (OUTPUT_FILE, '-');
  13213.     end loop;
  13214.  
  13215.     for I in 1 .. 13 loop
  13216.     TEXT_IO.PUT (OUTPUT_FILE, "!------");
  13217.     end loop;
  13218.  
  13219.     TEXT_IO.PUT_LINE (OUTPUT_FILE, "+");
  13220.  
  13221. exception
  13222.     when others => 
  13223.     FATAL (UNIT => "Schedule Tool - Unit named " &
  13224.                "[OUT_GANTT.PRINT_MONTH_DAY_HEADER]");
  13225.  
  13226. end PRINT_MONTH_DAY_HEADER;
  13227.  
  13228.  
  13229.  
  13230.  
  13231.  
  13232. separate (SCHEDULE.OUT_GANTT)
  13233. procedure PRINT_FOOTER is
  13234. -----------------------------------------------------------
  13235. -- Author:     Larry Yelowitz
  13236. -- Source:     Division Software Technology and Support
  13237. --             Western Development Laboratories
  13238. --             Ford Aerospace & Communications Corporation
  13239. --             ATTN:  Ada Tools Group
  13240. -- Date  :     May 25 1985
  13241. -- Summary:    This procedure prints days-into-project 
  13242. --       (not counting holi and weekends) at bottom of page
  13243. -----------------------------------------------------------
  13244.  
  13245. begin
  13246.     TEXT_IO.PUT (OUTPUT_FILE, '+');
  13247.  
  13248.     for I in 1 .. 32 loop
  13249.     TEXT_IO.PUT (OUTPUT_FILE, '-');
  13250.     end loop;
  13251.  
  13252.     for I in 1 .. 13 loop
  13253.     TEXT_IO.PUT (OUTPUT_FILE, "!------");
  13254.     end loop;
  13255.  
  13256.     TEXT_IO.PUT_LINE (OUTPUT_FILE, "+");
  13257.  
  13258.     --Top line of footer has been printed.  Now print data.
  13259.  
  13260.     TEXT_IO.PUT (OUTPUT_FILE, '!');
  13261.     TEXT_IO.SET_COL (OUTPUT_FILE, 12);
  13262.     TEXT_IO.PUT (OUTPUT_FILE, "WORK DAYS INTO EFFORT");
  13263.     TEXT_IO.SET_COL (OUTPUT_FILE, 34);
  13264.  
  13265.     for I in 1 .. 13 loop
  13266.     TEXT_IO.PUT (OUTPUT_FILE, '!');
  13267.     INT_IO.PUT (OUTPUT_FILE, WORKDAY_FOOTER (I), WIDTH => 3);
  13268.     TEXT_IO.SET_COL (OUTPUT_FILE,
  13269.              TEXT_IO.POSITIVE_COUNT ((41 + (INTEGER (I) - 1) * 7)));
  13270.     end loop;
  13271.  
  13272.     TEXT_IO.PUT_LINE (OUTPUT_FILE, "!");
  13273.  
  13274.     --Data line has now been printed.  Next print bottom line of footer.
  13275.  
  13276.     TEXT_IO.PUT (OUTPUT_FILE, '+');
  13277.  
  13278.     for I in 1 .. 123 loop
  13279.     TEXT_IO.PUT (OUTPUT_FILE, '-');
  13280.     end loop;
  13281.  
  13282.     TEXT_IO.PUT_LINE (OUTPUT_FILE, "+");
  13283.  
  13284.     TEXT_IO.NEW_PAGE (OUTPUT_FILE);
  13285.  
  13286. exception
  13287.     when others => 
  13288.     FATAL (UNIT => "Schedule Tool - Unit named " &
  13289.                "[OUT_GANTT.PRINT_FOOTER]");
  13290.  
  13291. end PRINT_FOOTER;
  13292.  
  13293.