private static ProjectData Finalize(this ProjectData project)
        {
            var calendar = project.Information.Calendar;

            foreach (var taskId in project.Tasks)
            {
                var earlyStart  = project.Get(TaskFields.EarlyStart, taskId);
                var earlyFinish = project.Get(TaskFields.EarlyFinish, taskId);
                var lateStart   = project.Get(TaskFields.LateStart, taskId);
                var lateFinish  = project.Get(TaskFields.LateFinish, taskId);

                // Set start, finish, and duration

                var start    = earlyStart;
                var finish   = earlyFinish;
                var duration = calendar.GetWork(start, finish);

                project = project.SetRaw(TaskFields.Start, taskId, start)
                          .SetRaw(TaskFields.Finish, taskId, finish)
                          .SetRaw(TaskFields.Duration, taskId, duration);

                // Set start slack, finish slack, total slack, and criticality

                var startSlack  = calendar.GetWork(earlyStart, lateStart);
                var finishSlack = calendar.GetWork(earlyFinish, lateFinish);
                var totalSlack  = startSlack <= finishSlack ? startSlack : finishSlack;
                var isCritical  = totalSlack == TimeSpan.Zero;

                project = project.SetRaw(TaskFields.StartSlack, taskId, startSlack)
                          .SetRaw(TaskFields.FinishSlack, taskId, finishSlack)
                          .SetRaw(TaskFields.TotalSlack, taskId, totalSlack)
                          .SetRaw(TaskFields.IsCritical, taskId, isCritical);

                // Set free slack

                var freeSlack = GetFreeSlack(project, taskId);
                project = project.SetRaw(TaskFields.FreeSlack, taskId, freeSlack);
            }

            // Set assignment start and finish

            foreach (var assignmentId in project.Assignments)
            {
                var taskId    = project.Get(AssignmentFields.TaskId, assignmentId);
                var taskStart = project.Get(TaskFields.Start, taskId);

                var assignmentWork  = project.Get(AssignmentFields.Work, assignmentId);
                var assignmentUnits = project.Get(AssignmentFields.Units, assignmentId);
                var assignmentStart = taskStart;

                var duration = TimeSpan.FromHours(assignmentWork.TotalHours / assignmentUnits);
                ComputeFinish(project.Information.Calendar, ref assignmentStart, out var assignmentFinish, duration);

                project = project.SetRaw(AssignmentFields.Start, assignmentId, assignmentStart)
                          .SetRaw(AssignmentFields.Finish, assignmentId, assignmentFinish);
            }

            return(project);
        }
        private static ProjectData ResetTaskResourceNamesOrInitials(ProjectData project, TaskId id, bool isInitials)
        {
            var resourceField = isInitials ? ResourceFields.Initials : ResourceFields.Name;
            var taskField     = isInitials ? TaskFields.ResourceInitials : TaskFields.ResourceNames;

            var sb = new StringBuilder();

            foreach (var a in project.GetAssignments(id)
                     .OrderBy(a => project.Get(resourceField, project.Get(AssignmentFields.ResourceId, a))))
            {
                var resourceId   = project.Get(AssignmentFields.ResourceId, a);
                var resourceName = project.Get(resourceField, resourceId);
                var units        = project.Get(AssignmentFields.Units, a);

                if (sb.Length > 0)
                {
                    sb.Append(", ");
                }

                sb.Append(resourceName);

                if (units != 1.0)
                {
                    sb.Append(" [");
                    sb.Append(Math.Round(units * 100, 2, MidpointRounding.AwayFromZero));
                    sb.Append("%]");
                }
            }

            var resourceNames = sb.ToString();

            return(project.SetRaw(taskField, id, resourceNames));
        }
        private static ProjectData ResetTaskPredecessorsOrSuccessors(ProjectData project, TaskId id, bool isSuccessors)
        {
            TaskId GetPredecessor(TaskLink l) => l.PredecessorId;
            TaskId GetSuccessor(TaskLink l) => l.SuccessorId;

            var getTask   = isSuccessors ? (Func <TaskLink, TaskId>)GetSuccessor : GetPredecessor;
            var field     = isSuccessors ? TaskFields.Successors : TaskFields.Predecessors;
            var linkField = isSuccessors ? TaskFields.SuccessorLinks : TaskFields.PredecessorLinks;

            var sb = new StringBuilder();

            var predecessors = project.Get(linkField, id);

            foreach (var p in predecessors.OrderBy(p => project.Get(TaskFields.Ordinal, getTask(p))))
            {
                if (sb.Length > 0)
                {
                    sb.Append(",");
                }

                var ordinal = project.Get(TaskFields.Ordinal, getTask(p));
                sb.Append(ordinal);

                switch (p.Type)
                {
                case TaskLinkType.FinishToStart:
                    if (p.Lag != TimeSpan.Zero)
                    {
                        sb.Append("FS");
                    }
                    break;

                case TaskLinkType.StartToStart:
                    sb.Append("SS");
                    break;

                case TaskLinkType.FinishToFinish:
                    sb.Append("FF");
                    break;

                case TaskLinkType.StartToFinish:
                    sb.Append("SF");
                    break;
                }

                if (p.Lag != TimeSpan.Zero)
                {
                    if (p.Lag > TimeSpan.Zero)
                    {
                        sb.Append("+");
                    }
                    var lag = project.Information.TimeConversion.FormatDuration(p.Lag);
                    sb.Append(lag);
                }
            }

            var precedessors = sb.ToString();

            return(project.SetRaw(field, id, precedessors));
        }
        private static ProjectData BackwardPass(this ProjectData project)
        {
            var computedTasks = new HashSet <TaskId>();
            var toBeScheduled = new Queue <TaskId>(project.Tasks);

            while (toBeScheduled.Count > 0)
            {
                var taskId                = toBeScheduled.Dequeue();
                var successors            = project.Get(TaskFields.SuccessorLinks, taskId);
                var allSuccessorsComputed = successors.All(l => computedTasks.Contains(l.SuccessorId));
                if (!allSuccessorsComputed)
                {
                    toBeScheduled.Enqueue(taskId);
                }
                else
                {
                    ComputeLateStartAndFinish(project, taskId, successors, out var lateStart, out var lateFinish);

                    project = project.SetRaw(TaskFields.LateStart, taskId, lateStart)
                              .SetRaw(TaskFields.LateFinish, taskId, lateFinish);

                    computedTasks.Add(taskId);
                }
            }

            return(project);
        }
        private static ProjectData ForwardPass(this ProjectData project)
        {
            var computedTasks = new HashSet <TaskId>();
            var toBeScheduled = new Queue <TaskId>(project.Tasks);

            while (toBeScheduled.Count > 0)
            {
                var taskId                  = toBeScheduled.Dequeue();
                var predecessors            = project.Get(TaskFields.PredecessorLinks, taskId);
                var allPredecessorsComputed = predecessors.All(l => computedTasks.Contains(l.PredecessorId));
                if (!allPredecessorsComputed)
                {
                    toBeScheduled.Enqueue(taskId);
                }
                else
                {
                    ComputeEarlyStartAndFinish(project, taskId, predecessors, out var earlyStart, out var earlyFinish);

                    project = project.SetRaw(TaskFields.EarlyStart, taskId, earlyStart)
                              .SetRaw(TaskFields.EarlyFinish, taskId, earlyFinish);

                    computedTasks.Add(taskId);
                }
            }

            var projectFinish = ComputeProjectFinish(project);
            var information   = project.Information.WithFinish(projectFinish);

            return(project.WithInformation(information));
        }
Exemplo n.º 6
0
        private static ProjectData SetAssignmentUnits(ProjectData project, AssignmentId id, double value)
        {
            var taskId = project.Get(AssignmentFields.TaskId, id);

            return(project.SetRaw(AssignmentFields.Units, id, value)
                   .Reset(TaskFields.ResourceNames, taskId)
                   .Reset(TaskFields.ResourceInitials, taskId));
        }
        private static ProjectData SetTaskWork(ProjectData project, TaskId id, TimeSpan value)
        {
            project = project.SetRaw(TaskFields.Work, id, value);

            if (value == TimeSpan.Zero)
            {
                foreach (var assignmentId in project.GetAssignments(id))
                {
                    project = project.SetRaw(AssignmentFields.Work, assignmentId, TimeSpan.Zero);
                }
            }
            else
            {
                var totalExistingWork = TimeSpan.Zero;

                foreach (var assignmentId in project.GetAssignments(id))
                {
                    totalExistingWork += project.Get(AssignmentFields.Work, assignmentId);
                }

                var assignmentCount = project.GetAssignments(id).Count();

                foreach (var assignmentId in project.GetAssignments(id))
                {
                    var assignmentWork = project.Get(AssignmentFields.Work, assignmentId);

                    double newHours;

                    if (totalExistingWork > TimeSpan.Zero)
                    {
                        newHours = assignmentWork.TotalHours / totalExistingWork.TotalHours * value.TotalHours;
                    }
                    else
                    {
                        newHours = value.TotalHours / assignmentCount;
                    }

                    var newWork = TimeSpan.FromHours(newHours);

                    project = project.SetRaw(AssignmentFields.Work, assignmentId, newWork);
                }
            }

            return(project);
        }
        private static ProjectData SetResourceName(ProjectData project, ResourceId id, string value)
        {
            project = project.SetRaw(ResourceFields.Name, id, value);

            // Update Assignment.ResourceName

            foreach (var assignmentId in project.GetAssignments(id))
            {
                project = project.SetRaw(AssignmentFields.ResourceName, assignmentId, value);
            }

            // Update Task.ResourceNames

            foreach (var taskId in project.GetTasks(id))
            {
                project = project.Reset(TaskFields.ResourceNames, taskId);
            }

            return(project);
        }
Exemplo n.º 9
0
        private static ProjectData SetAssignmentWork(ProjectData project, AssignmentId id, TimeSpan value)
        {
            var taskId            = project.Get(AssignmentFields.TaskId, id);
            var oldTaskWork       = project.Get(TaskFields.Work, taskId);
            var oldAssignmentWork = project.Get(AssignmentFields.Work, id);

            var newAssignmentWork = value;
            var newTaskWork       = oldTaskWork + newAssignmentWork - oldAssignmentWork;

            return(project.SetRaw(TaskFields.Work, taskId, newTaskWork)
                   .SetRaw(AssignmentFields.Work, id, newAssignmentWork));
        }
        private static ProjectData SetResourceInitials(ProjectData project, ResourceId id, string value)
        {
            project = project.SetRaw(ResourceFields.Initials, id, value);

            // Update Task.ResourceInitials

            foreach (var taskId in project.GetTasks(id))
            {
                project = project.Reset(TaskFields.ResourceInitials, taskId);
            }

            return(project);
        }
        private static ProjectData SetTaskName(ProjectData project, TaskId id, string value)
        {
            var assignmentIds = project.GetAssignments(id);

            project = project.SetRaw(TaskFields.Name, id, value);

            foreach (var assignmentId in assignmentIds)
            {
                project = project.Set(AssignmentFields.TaskName, assignmentId, value);
            }

            return(project);
        }
        private static ProjectData SetTaskDuration(ProjectData project, TaskId id, TimeSpan value)
        {
            project = project.SetRaw(TaskFields.Duration, id, value);

            var taskFinish = project.Get(TaskFields.Finish, id);

            foreach (var assignmentId in project.GetAssignments(id))
            {
                var assignmentFinish = project.Get(AssignmentFields.Finish, assignmentId);
                var assignmentUnits  = project.Get(AssignmentFields.Units, assignmentId);

                if (assignmentFinish == taskFinish)
                {
                    var assignmentWork = TimeSpan.FromHours(value.TotalHours * assignmentUnits);
                    project = project.Set(AssignmentFields.Work, assignmentId, assignmentWork);
                }
            }

            return(project);
        }
        private static ProjectData SetTaskOrdinal(ProjectData project, TaskId id, int value)
        {
            if (value < 0 || value >= project.TaskMap.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(value));
            }

            var oldOrdinal = project.Get(TaskFields.Ordinal, id);
            var newOrdinal = value;

            var orderedTaskIds = project.Tasks
                                 .OrderBy(t => project.Get(TaskFields.Ordinal, t))
                                 .ToList();

            orderedTaskIds.RemoveAt(oldOrdinal);
            orderedTaskIds.Insert(newOrdinal, id);

            // First we update all ordinals

            for (var i = 0; i < orderedTaskIds.Count; i++)
            {
                var taskId  = orderedTaskIds[i];
                var ordinal = i;

                project = project.SetRaw(TaskFields.Ordinal, taskId, ordinal);
            }

            // Then we can update all predecessors/successors

            foreach (var taskId in orderedTaskIds)
            {
                project = project.Reset(TaskFields.Predecessors, taskId)
                          .Reset(TaskFields.Successors, taskId);
            }

            return(project);
        }