separate (Manpower)
procedure Graph_It (Title : in String) is
    ----------------------------------------------------------------------
    --| NAME : GRAPH_IT
    --|
    --| OVERVIEW:
    --|   This procedure plots the monthly work distribution on a page of
    --|   output.  The graph is scaled vertically with no limitation placed
    --|   on staffing requirement values, and horizontally, with the maximum
    --|   amount of time being 100 months.
    --|
    --| HISTORY:
    --|   written by   Bonnie Burkhardt   March 1985
    --|
    --| EXCEPTIONS:
    --|   others   An error message is printed and processing continues
    --|
    ----------------------------------------------------------------------

    Dashes : constant String (Month_Type) := (others => '-');
    Max_Lines : constant Integer := 30;
    Stars : constant String (1 .. 20) := (others => '*');

    A_Month : Month_Type := Month_Type'First;
    Big_At : Month_Type := Month_Type'First;
    Biggest : Float digits 15 := 0.0;
    Graph_Line : String (Month_Type);
    Horiz_Scale : Integer := 3;
    Month_Width : Integer := 3;
    Month_Count : Integer := 1;
    Num_Lines : Integer := Max_Lines;
    Staff : array (Month_Type) of Integer range 0 .. Max_Lines;
    Vert_Scale : Float digits 15 := 1.0;
    Vert_Index : Integer := 1;

begin
    -- print header for page
    New_Page (Report);
    Set_Col (Report, 56);
    Put_Line (Report, Title);
    Set_Col (Report, 56);
    Put_Line (Report, Dashes (1 .. 20));

    New_Line (Report, 2);
    Put (Report, ' ');
    Put (Report, Stars (1 .. 10));
    Put (Report, "     Acceleration rate = ");
    Put (Report, Accel_Rate, 3, 3, 0);
    Set_Col (Report, 60);
    Put (Report, Stars (1 .. 5));
    Set_Col (Report, 70);
    Put (Report, "Peak staffing occurs around month ");
    Put (Report, Tdev, 3, 1, 0);
    Put (Report, "     ");
    Put_Line (Report, Stars (1 .. 10));

    -- print header for graph
    New_Line (Report, 2);
    Put (Report, " Staffing Estimate:");
    Set_Col (Report, 110);
    Put_Line (Report, "Month      Est. Staff");
    Set_Col (Report, 110);
    Put (Report, Dashes (1 .. 5));
    Set_Col (Report, 121);
    Put_Line (Report, Dashes (1 .. 10));

    -- find the largest staffing requirement
    for I in Staffing'First .. Month loop
        if Biggest < Staffing (I) then
            Big_At := I;
            Biggest := Staffing (I);
        end if;
    end loop;

    -- compute vertical height of '*' on the graph for each horizontal point
    if Biggest > Float (Max_Lines) then
        Vert_Scale := Float (Max_Lines) / Biggest;
    else
        Num_Lines := Integer (Biggest);
    end if;

    for I in 1 .. Month loop
        Staff (I) := Integer (Staffing (I) * Vert_Scale);
    end loop;

    -- compute horizontal scaling and MONTH-COUNT field width
    if Month > 50 then
        Horiz_Scale := 1;
    elsif Month > 33 then
        Horiz_Scale := 2;
        Month_Width := 4;
    end if;

    -- print out graph
    for I in reverse 1 .. Num_Lines loop

        -- create graph line
        Graph_Line := (others => ' ');

        for J in 1 .. Month loop
            if Staff (J) = I then
                Graph_Line (J * Horiz_Scale) := '*';
            end if;
        end loop;

        -- print graph lines
        Vert_Index := Integer (Float (I) / Vert_Scale);
        Set_Col (Report, 3);
        Put (Report, Vert_Index, 5);
        Put (Report, " |");
        Put (Report, Graph_Line);

        if Month_Count <= Month then
            Set_Col (Report, 111);
            Put (Report, Month_Count, 3);
            Set_Col (Report, 121);
            Put (Report, Staffing (Month_Count), 3, 5, 0);
            Month_Count := Month_Count + 1;
        end if;

        New_Line (Report);
    end loop;

    -- print bottom lines of graph
    Set_Col (Report, 9);
    Put (Report, "+");
    Graph_Line (1 .. Month * Horiz_Scale) := Dashes (1 .. Month * Horiz_Scale);

    for J in 1 .. Month loop
        if Staff (J) = 0 then
            Graph_Line (J * Horiz_Scale) := '*';
        end if;
    end loop;

    Put (Report, Graph_Line);

    if Month_Count <= Month then
        Set_Col (Report, 111);
        Put (Report, Month_Count, 3);
        Set_Col (Report, 121);
        Put (Report, Staffing (Month_Count), 3, 5, 0);
        Month_Count := Month_Count + 1;
    end if;

    New_Line (Report);

    -- print out month numbers
    Set_Col (Report, 9);
    Put (Report, '0');
    A_Month := 4 - Horiz_Scale;

    while A_Month <= Month loop
        Put (Report, A_Month, Month_Width);
        A_Month := A_Month + (4 - Horiz_Scale);
    end loop;

    if Month_Count <= Month then
        Set_Col (Report, 111);
        Put (Report, Month_Count, 3);
        Set_Col (Report, 121);
        Put (Report, Staffing (Month_Count), 3, 5, 0);
        Month_Count := Month_Count + 1;
    end if;

    New_Line (Report);

    -- print out month label
    Set_Col (Report, 40);
    Put (Report, "Duration (months)");

    if Month_Count <= Month then
        Set_Col (Report, 111);
        Put (Report, Month_Count, 3);
        Set_Col (Report, 121);
        Put (Report, Staffing (Month_Count), 3, 5, 0);
        Month_Count := Month_Count + 1;
    end if;

    New_Line (Report);

    -- print out remainder of month/staffing requirement table
    for I in Month_Count .. Month loop
        Set_Col (Report, 111);
        Put (Report, I, 3);
        Set_Col (Report, 121);
        Put (Report, Staffing (I), 3, 5, 0);
        New_Line (Report);
    end loop;
exception
    when others =>
        Put_Line ("exception raised in GRAPH_IT");
end Graph_It;