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)); }