separate (Tracker.Manipulate_Data.Calc_Time_Done)

procedure Get_El_Time is
    --------------------------------------------------------------------------------
    --|
    --|  NAME:  GET_EL_TIME
    --|
    --|  OVERVIEW:
    --|    This procedure computes the total amount of time needed to complete
    --|    the activities with TEST_PRIORITY of each element assigned to the
    --|    current programmer, PR_PTR.  It then adds this time to the total
    --|    time the programmer works and to the total number of hours needed
    --|    to complete the element, ELE_PTR.hours_to_complete. It also calculates
    --|    the date this amount of work will be completed.  The completion date
    --|    is stored in the element field, DATE_DONE.
    --|
    --|  EXCEPTIONS HANDLED:
    --|    others   an error message is printed and execution continues
    --|
    --|  HISTORY:
    --|    written by   Bonnie Burkhardt   March 1985
    --------------------------------------------------------------------------------

    use Data_Pkg;

    Biased_Total_Time : Float := 0.0;
    Date_Done : Date_Type := Null_Date;
    Date_Calculated : Boolean := False;
    Ele_Ptr : Element_Pointer;
    Ele_Size : Integer range 0 .. 999_000;
    End_List : Boolean := False;
    Projected_Date_Done : Date_Type := Null_Date;
    Time_Span_Used : Integer range 1 .. 3 := Begin_Date_Used;
    Starting_Date : Date_Type := Begin_Date;
    Standard_Workweek : Boolean := False;
    Time_For_1_Ac : Float := 0.0;
    Time_For_Ele : Float := 0.0;

begin
    Standard_Workweek := Float (Pr_Ptr.Hours_Per_Week) =
                            Hours_In_Work_Day * Float (Days_In_Work_Week);
    Start_Walk (Pr_Ptr.Element_List);

    loop
        Walk (Pr_Ptr.Element_List, Ele_Ptr, End_List);
        exit when End_List;

        Ele_Size := Ele_Ptr.Current_Size - Ele_Ptr.Size_Done_At_Start;
        Time_For_Ele := 0.0;

        -- calculate the amount of time needed to complete this element's activities
        for Ac_Index in 1 .. Num_Of_Activities loop
            if Ac_Priorities (Ac_Index) = Test_Priority then

                if not Ele_Ptr.More_Than_One_Person then
                    Time_For_1_Ac :=
                       Ele_Ptr.Complexity * Float (Ele_Size) *
                          (Pct_Tot_Proj (Ac_Index) / 100.0) *
                          ((100.0 -
                            Ac_Pct_Value
                               (Ele_Ptr.Activity_Completeness (Ac_Index))) /
                           100.0) / Pr_Ptr.Production_Rate;

                elsif Ele_Ptr.People_Initials (Ac_Index) = Pr_Ptr.Initials then
                    Time_For_1_Ac :=
                       Ele_Ptr.Complexity * Float (Ele_Size) *
                          (Pct_Tot_Proj (Ac_Index) / 100.0) *
                          ((100.0 -
                            Ac_Pct_Value
                               (Ele_Ptr.Activity_Completeness (Ac_Index))) /
                           100.0) / Pr_Ptr.Production_Rate;
                    Ele_Ptr.Hours_Left (Ac_Index) := Time_For_1_Ac;
                end if;

                Time_For_Ele := Time_For_Ele + Time_For_1_Ac;
            end if;
        end loop;

        Total_Time := Total_Time + Time_For_Ele;
        Ele_Ptr.Hours_To_Complete := Ele_Ptr.Hours_To_Complete + Time_For_Ele;

        -- calculate the date this element is completed
        if Standard_Workweek then
            Biased_Total_Time := Total_Time;
        else
            Biased_Total_Time :=
               Total_Time * Float (Days_In_Work_Week) *
                  Hours_In_Work_Day / Float (Pr_Ptr.Hours_Per_Week);
        end if;

        Projected_Date_Done := Starting_Date + Biased_Total_Time;

        Starting_Date := Begin_Date;
        Time_Span_Used := Begin_Date_Used;
        Date_Calculated := False;

        while not Date_Calculated loop
            case Time_Span_Used is
                when 1 | 2 =>
                    -- it fits in the time span
                    if (Pr_Ptr.Stop_Dates (Time_Span_Used) = Null_Date) or
                       (Pr_Ptr.Stop_Dates (Time_Span_Used) >=
                        Projected_Date_Done) then
                        Date_Done := Projected_Date_Done;
                        Date_Calculated := True;
                        -- another set of start/stop dates doesn't exits
                    elsif Pr_Ptr.Start_Dates (Time_Span_Used + 1) =
                          Null_Date then
                        Date_Done := Underflow_Date;
                        Date_Calculated := True;
                    else
                        -- move on to next set of completion dates
                        -- add in the total amount of work missed to the biased total time
                        -- (the vacation is from this stop date to the next start date)
                        Biased_Total_Time :=
                           Biased_Total_Time +
                              (Pr_Ptr.Start_Dates (Time_Span_Used + 1) -
                               Pr_Ptr.Stop_Dates (Time_Span_Used));
                        Time_Span_Used := Time_Span_Used + 1;
                        Projected_Date_Done :=
                           Starting_Date + Biased_Total_Time;
                    end if;
                when 3 =>
                    -- it fits in the time span
                    if (Pr_Ptr.Stop_Dates (Time_Span_Used) = Null_Date) or
                       (Pr_Ptr.Stop_Dates (Time_Span_Used) >=
                        Projected_Date_Done) then
                        Date_Done := Projected_Date_Done;
                        Date_Calculated := True;
                    else
                        -- no time to finish the work
                        Date_Done := Underflow_Date;
                        Date_Calculated := True;
                    end if;
            end case;
        end loop;

        -- assign the newly completed completion date to the fields in the element
        if (Ele_Ptr.Date_Done = Null_Date) or
           (Ele_Ptr.Date_Done < Date_Done) or (Date_Done = Underflow_Date) then
            Ele_Ptr.Date_Done := Date_Done;
        end if;

        if Ele_Ptr.More_Than_One_Person then
            for Ac_Index in 1 .. Num_Of_Activities loop
                if (Ac_Priorities (Ac_Index) = Test_Priority) and
                   (Ele_Ptr.People_Initials (Ac_Index) = Pr_Ptr.Initials) then
                    Ele_Ptr.Dates_Done (Ac_Index) := Date_Done;
                end if;
            end loop;
        end if;
    end loop;

exception
    when others =>
        Put_Line ("exception raised in GET_EL_TIME.");
end Get_El_Time;