Search in sources :

Example 1 with ActualSubtaskData

use of teamdash.wbs.WBSSynchronizer.ActualSubtaskData in project processdash by dtuma.

the class TeamActualTimeColumn method recalculate.

/** Recalculate data for a single node in the WBS.
     * 
     * With a single pass over the WBS, this method calculates actual time
     * for each team member and for the entire team; actual earned value,
     * completion date, percent complete, and percent spent.
     * 
     * @param node the node to recalculate
     * @param actualTime a result array, having one entry for each member of the
     *     team project.  This method should calculate (for each team member)
     *     the total actual time for this node and all children, and store the
     *     resulting value in corresponding field of this array.
     * @param earnedValue a single-entry result array.  This method should
     *     calculate the team earned value (for this node and all children,
     *     in hours), and return the result in the single field of this array.
     * @param completionDate a single-entry result array.  This method should
     *     calculate the actual completion date of this node and all children,
     *     and return the result in the single field of this array.
     */
private void recalculate(WBSNode node, double[] actualTime, TimeCalculator[] timeCalc, double[] earnedValue, long[] completionDate) {
    // get the list of children underneath this node
    WBSNode[] children = wbsModel.getChildren(node);
    boolean isLeaf = (children.length == 0);
    // load the actual node time for each individual into our working array
    for (int i = 0; i < teamSize; i++) actualTime[i] = nanToZero(node.getNumericAttribute(nodeTimeAttrs[i]));
    earnedValue[0] = 0;
    completionDate[0] = COMPL_DATE_NA;
    if (isLeaf) {
        int milestone = MilestoneColumn.getMilestoneID(node);
        // accumulate EV and completion date information for this leaf
        for (int i = 0; i < teamSize; i++) {
            // decide whether data from this team member should be included
            // in team sums
            boolean rollupMember = rollupEveryone || matchesTeamFilter[i];
            // retrieve the planned time for one team member.
            double memberPlanTime = nanToZero(node.getNumericAttribute(planTimeAttrs[i]));
            boolean assignedWithZero = (node.getAttribute(assignedWithZeroAttrs[i]) != null);
            if (memberPlanTime > 0 || assignedWithZero) {
                // if this team member is assigned to this leaf task, get
                // their actual completion date for the task.
                Date memberCompletionDate = (Date) node.getAttribute(completionDateAttrs[i]);
                // keep track of the max completion date so far.
                if (rollupMember)
                    completionDate[0] = mergeCompletionDate(completionDate[0], memberCompletionDate);
                // team has earned the value associated with the task.
                if (memberCompletionDate != null) {
                    if (rollupMember)
                        earnedValue[0] += memberPlanTime;
                    timeCalc[i].addCompletedTask(memberPlanTime, actualTime[i], milestone);
                } else {
                    // See if subtask data is present for this task
                    List<ActualSubtaskData> subtaskData = (List) node.getAttribute(subtaskDataAttrs[i]);
                    if (subtaskData != null && !subtaskData.isEmpty()) {
                        // if subtask data is present, handle it.
                        // if the time estimate in the personal dashboard is
                        // out of sync with the WBS, the subtask times will
                        // add up to a different value than memberPlanTime.
                        // calculate this ratio so we can adjust EV.
                        double subtaskPlanTotal = 0;
                        for (ActualSubtaskData subtask : subtaskData) subtaskPlanTotal += subtask.getPlanTime();
                        double ratio = memberPlanTime / subtaskPlanTotal;
                        if (Double.isInfinite(ratio) || Double.isNaN(ratio))
                            ratio = 0;
                        // record each subtask as an independent task.
                        for (ActualSubtaskData subtask : subtaskData) {
                            if (subtask.getCompletionDate() != null) {
                                // this subtask was completed
                                if (rollupMember)
                                    earnedValue[0] += subtask.getPlanTime() * ratio;
                                timeCalc[i].addCompletedTask(subtask.getPlanTime(), subtask.getActualTime(), milestone);
                            } else {
                                // this subtask is remaining
                                timeCalc[i].addRemainingTask(subtask.getPlanTime(), subtask.getActualTime(), milestone);
                            }
                        }
                    } else {
                        // there is no subtask data for this node. Just
                        // record a plain remaining task.
                        timeCalc[i].addRemainingTask(memberPlanTime, actualTime[i], milestone);
                    }
                }
            }
        }
    } else {
        double[] childTime = new double[teamSize];
        double[] childEarnedValue = new double[1];
        long[] childCompletionDate = new long[1];
        for (int i = 0; i < children.length; i++) {
            // ask our child to compute its time data
            recalculate(children[i], childTime, timeCalc, childEarnedValue, childCompletionDate);
            // if the child isn't hidden, add its values to our totals
            if (!children[i].isHidden()) {
                // accumulate time from that child into our total
                for (int j = 0; j < teamSize; j++) actualTime[j] += childTime[j];
                // accumulate EV related data from our children
                earnedValue[0] += childEarnedValue[0];
                completionDate[0] = Math.max(completionDate[0], childCompletionDate[0]);
            }
        }
    }
    double totalActualTime = 0;
    for (int i = 0; i < teamSize; i++) {
        // add up the actual time for all included team members
        if (rollupEveryone || matchesTeamFilter[i])
            totalActualTime += actualTime[i];
        // also store the total time per individual for this node
        node.setNumericAttribute(actTimeAttrs[i], actualTime[i]);
    }
    // store the actual time for the entire team for this node.
    node.setNumericAttribute(ACT_TIME_ATTR_NAME, totalActualTime);
    // retrieve the total plan time for this node from the TeamTimeColumn.
    double totalPlanTime = nanToZero(NumericDataValue.parse(dataModel.getValueAt(node, teamPlanTimeColumnNum)));
    // calculate and store the percent spent
    double percentSpent = totalActualTime / totalPlanTime;
    node.setNumericAttribute(PercentSpentColumn.RESULT_ATTR, percentSpent);
    // calculate and store the completion date and percent complete
    Date cd = null;
    double percentComplete = earnedValue[0] / totalPlanTime;
    if (completionDate[0] != COMPL_DATE_NA && completionDate[0] != INCOMPLETE) {
        cd = new Date(completionDate[0]);
        percentComplete = 1.0;
    }
    node.setAttribute(TeamCompletionDateColumn.ATTR_NAME, cd);
    node.setNumericAttribute(PercentCompleteColumn.RESULT_ATTR, percentComplete);
}
Also used : ArrayList(java.util.ArrayList) List(java.util.List) TeamMemberList(teamdash.team.TeamMemberList) ActualSubtaskData(teamdash.wbs.WBSSynchronizer.ActualSubtaskData) WBSNode(teamdash.wbs.WBSNode) Date(java.util.Date)

Aggregations

ArrayList (java.util.ArrayList)1 Date (java.util.Date)1 List (java.util.List)1 TeamMemberList (teamdash.team.TeamMemberList)1 WBSNode (teamdash.wbs.WBSNode)1 ActualSubtaskData (teamdash.wbs.WBSSynchronizer.ActualSubtaskData)1