public void StuckNetworkLengthsThrowsError() { var t1 = new PertTask { TimeEstimate = new Estimate(1) }; var t2 = new PertTask { TimeEstimate = new Estimate(1) }; var t3 = new PertTask { TimeEstimate = new Estimate(1) }; var t4 = new PertTask { TimeEstimate = new Estimate(2) }; t1.LinkToDescendant(t2); t2.LinkToDescendant(t3); t2.LinkToDescendant(t4); var tasks = new PertTask[] { t1, t2, t3 }; Assert.Throws <ArgumentException>(() => { PathTools.NetworkPathLengths(tasks, new EstimateModeReader()); }); }
public SimulatedTaskData(PertTask task, IEstimator estimator) { _workLog = new List <Tuple <double, double> >(); this.Task = task; this._estimator = estimator; this.Reset(); }
public void ForkedNetworkLengths() { var t1 = new PertTask { TimeEstimate = new Estimate(1) }; var t2 = new PertTask { TimeEstimate = new Estimate(1) }; var t3 = new PertTask { TimeEstimate = new Estimate(1) }; var t4 = new PertTask { TimeEstimate = new Estimate(2) }; t1.LinkToDescendant(t2); t2.LinkToDescendant(t3); t2.LinkToDescendant(t4); var tasks = new PertTask[] { t1, t2, t3, t4 }; var result = PathTools.NetworkPathLengths(tasks, new EstimateModeReader()); Assert.AreEqual(1.0, result[t3.Id]); Assert.AreEqual(3.0, result[t2.Id]); Assert.AreEqual(4.0, result[t1.Id]); Assert.AreEqual(2.0, result[t4.Id]); }
/// <summary> /// Check to make sure that all of a task's ancestors are ready /// </summary> /// <param name="task"></param> /// <returns></returns> private bool AreTaskAncestorsDone(PertTask task) { foreach (var taskAncestor in task.Ancestors) { if (!_taskDataById[taskAncestor.Id].IsComplete) { return(false); } } return(true); }
public void AddTask() { var tx = new PertTask { Name = "Task x" }; project.AddTask(tx); tx.LinkToAncestor(task10); CollectionAssert.Contains(project.Tasks, tx); }
public TaskViewModel(PertTask taskModel) { this._task = taskModel; this.Resources = new ObservableCollection <IResource>(); foreach (var modelResource in this.Model.Resources) { this.Resources.Add(modelResource); } this.Resources.CollectionChanged += Resources_CollectionChanged; this.TimeEstimate = new EstimateViewModel(this._task.TimeEstimate); this.TimeEstimate.PropertyChanged += TimeEstimate_PropertyChanged; }
public void PrepareProject() { this.project = new Project { Name = "Test Project", Description = "Test project for serialization and deserialization" }; task1 = new PertTask { Name = "Task 1" }; task2 = new PertTask { Name = "Task 2" }; task3 = new PertTask { Name = "Task 3" }; task4 = new PertTask { Name = "Task 4" }; task5 = new PertTask { Name = "Task 5" }; task6 = new PertTask { Name = "Task 6" }; task7 = new PertTask { Name = "Task 7" }; task8 = new PertTask { Name = "Task 8" }; task9 = new PertTask { Name = "Task 9" }; task10 = new PertTask { Name = "Task 10" }; task1.LinkToDescendant(task3); task2.LinkToDescendant(task3); task3.LinkToDescendant(task5); task4.LinkToDescendant(task5); task5.LinkToDescendant(task6); task5.LinkToDescendant(task7); task6.LinkToDescendant(task8); task6.LinkToDescendant(task9); task9.LinkToDescendant(task10); foreach (var pertTask in new PertTask[] { task1, task2, task3, task4, task5, task6, task7, task8, task9, task10 }) { project.AddTask(pertTask); } }
public void LinkDescendant() { var t1 = new PertTask { Name = "Task 1" }; var t2 = new PertTask { Name = "Task 2" }; t1.LinkToDescendant(t2); Assert.IsTrue(t1.Descendants.Contains(t2)); Assert.IsTrue(t2.Ancestors.Contains(t1)); }
public void ComplexNetwork(string node, double expected) { var task1 = new PertTask { Name = "1", TimeEstimate = new Estimate(3) }; var task2 = new PertTask { Name = "2", TimeEstimate = new Estimate(2) }; var task3 = new PertTask { Name = "3", TimeEstimate = new Estimate(5) }; var task4 = new PertTask { Name = "4", TimeEstimate = new Estimate(4) }; var task5 = new PertTask { Name = "5", TimeEstimate = new Estimate(3) }; var task6 = new PertTask { Name = "6", TimeEstimate = new Estimate(2) }; var task7 = new PertTask { Name = "7", TimeEstimate = new Estimate(1) }; var task8 = new PertTask { Name = "8", TimeEstimate = new Estimate(4) }; var task9 = new PertTask { Name = "9", TimeEstimate = new Estimate(3) }; var task10 = new PertTask { Name = "10", TimeEstimate = new Estimate(2) }; task1.LinkToDescendant(task3); task2.LinkToDescendant(task3); task3.LinkToDescendant(task5); task4.LinkToDescendant(task5); task5.LinkToDescendant(task6); task5.LinkToDescendant(task7); task6.LinkToDescendant(task8); task6.LinkToDescendant(task9); task9.LinkToDescendant(task10); var tasks = new PertTask[] { task1, task2, task3, task4, task5, task6, task7, task8, task9, task10 }; var result = PathTools.NetworkPathLengths(tasks, new EstimateModeReader()); var checkTaskId = tasks.First(x => x.Name == node).Id; Assert.AreEqual(expected, result[checkTaskId]); }
public static SerializablePertTask FromPertTask(PertTask item) { return(new SerializablePertTask { Name = item.Name, Id = item.Id, Description = item.Description, TimeEstimate = item.TimeEstimate, Ancestors = item.Ancestors.Select(x => x.Id).ToList(), Descendants = item.Descendants.Select(x => x.Id).ToList(), ResourceNames = item.Resources.Select(x => x.Name).ToList(), Category = item.Category }); }
/// <summary> /// Perform the necessary housekeeping when a task is completed, including removing it from the /// available tasks and adding its descendants to the available list /// </summary> /// <param name="task"></param> private void SimulateTaskCompletion(PertTask task) { var taskData = _taskDataById[task.Id]; if (!taskData.IsComplete) { throw new ArgumentException($"Task '{task.Name}' was passed to completion method but was not actually complete"); } _availableTasks.Remove(task); foreach (var taskDescendant in task.Descendants) { if (AreTaskAncestorsDone(taskDescendant)) { _availableTasks.Add(taskDescendant); } } }
public void CreateNetworks() { task1 = new PertTask { Name = "Task 1" }; task2 = new PertTask { Name = "Task 2" }; task3 = new PertTask { Name = "Task 3" }; task4 = new PertTask { Name = "Task 4" }; task5 = new PertTask { Name = "Task 5" }; task6 = new PertTask { Name = "Task 6" }; task7 = new PertTask { Name = "Task 7" }; task8 = new PertTask { Name = "Task 8" }; task9 = new PertTask { Name = "Task 9" }; task10 = new PertTask { Name = "Task 10" }; task1.LinkToDescendant(task3); task2.LinkToDescendant(task3); task3.LinkToDescendant(task5); task4.LinkToDescendant(task5); task5.LinkToDescendant(task6); task5.LinkToDescendant(task7); task6.LinkToDescendant(task8); task6.LinkToDescendant(task9); task9.LinkToDescendant(task10); }
/// <summary> /// Converts a SerializeablePertTask into a PertTask, but without the resource /// list or any linking /// </summary> /// <param name="item"></param> /// <returns></returns> public static PertTask ToUnlinkedPertTask(SerializablePertTask item) { var working = new PertTask { Name = item.Name, Id = item.Id, Description = item.Description, TimeEstimate = item.TimeEstimate, Resources = new HashSet <IResource>(), Category = item.Category }; if (working.TimeEstimate == null) { working.TimeEstimate = new Estimate(); } return(working); }
public void SetupProjectNetwork() { _org = new Organization(); var engineer = new ResourceGroup { Name = "Engineer", Rate = 100 }; var fabricator = new ResourceGroup { Name = "Fabricator", Rate = 50 }; _org.ResourceGroups.Add(engineer); _org.ResourceGroups.Add(fabricator); pete = new Employee { Name = "Pete", Group = engineer }; joe = new Employee { Name = "Joe", Group = fabricator }; _org.Employees.Add(pete); _org.Employees.Add(joe); t1 = new PertTask { Name = "t1", TimeEstimate = new Estimate(2) }; t2 = new PertTask { Name = "t2", TimeEstimate = new Estimate(3) }; t3 = new PertTask { Name = "t3", TimeEstimate = new Estimate(4) }; t4 = new PertTask { Name = "t4", TimeEstimate = new Estimate(2) }; t5 = new PertTask { Name = "t5", TimeEstimate = new Estimate(3) }; t6 = new PertTask { Name = "t6", TimeEstimate = new Estimate(4) }; t7 = new PertTask { Name = "t7", TimeEstimate = new Estimate(5) }; t8 = new PertTask { Name = "t8", TimeEstimate = new Estimate(2) }; t9 = new PertTask { Name = "t9", TimeEstimate = new Estimate(3) }; _simpleProject = new Project(); _simpleProject.AddTask(t1); _simpleProject.AddTask(t2); _simpleProject.AddTask(t3); _simpleProject.AddTask(t4); _simpleProject.AddTask(t5); _simpleProject.AddTask(t6); _simpleProject.AddTask(t7); _simpleProject.AddTask(t8); _simpleProject.AddTask(t9); t1.LinkToDescendant(t2); t2.LinkToDescendant(t3); t2.LinkToDescendant(t4); t2.LinkToDescendant(t5); t3.LinkToDescendant(t6); t4.LinkToDescendant(t7); t5.LinkToDescendant(t9); t6.LinkToDescendant(t8); t7.LinkToDescendant(t8); }
public static Dictionary <Guid, double> NetworkPathLengths(IEnumerable <PertTask> tasks, IEstimateValueReader valueReader) { var results = new Dictionary <Guid, double>(); var workingTasks = new Queue <PertTask>(); // Prepare the starting (ending) tasks as the ones with no descendants foreach (var pertTask in tasks) { if (!pertTask.Descendants.Any()) { workingTasks.Enqueue(pertTask); } } /* If we go through an entire queue without making any progress, the algorithm * is currently stuck. This object reference is used to detect that condition. * -> If the algorithm finds a node that cannot be resolved because its descendants * don't all exist in the results dictionary, and the firstNoprogressTask reference * is null, then we take the current unresolvable task and store it in the fNT ref * -> If the algorithm finds a node that ~can~ be resolved, it sets the fNT reference * back to null, and the next task that can't be resolved will take its place * -> If the algorithm gets to a node that can't be resolved and it's ~already~ stored * in the fNT reference, then we've managed to go all the way through the queue and * loop back around without resolving a single task. That means we're stuck and we * shoud throw an error. */ PertTask firstNoprogressTask = null; while (workingTasks.Any()) { // For each cycle we check each task to see if it has no unresolved descendants. Each // task located can be assigned a value based on the largest weight of its descendants // added to its own weight, at which time it's stored in the results dictionary var task = workingTasks.Dequeue(); double maxDescendantWeight = 0; bool hasUnresolvedDescendant = false; foreach (var taskDescendant in task.Descendants) { // If we find any descendant that does not have an entry already in the results list, // we abort working on this task put it back at the end of the queue if (!results.ContainsKey(taskDescendant.Id)) { hasUnresolvedDescendant = true; break; } // Otherwise, we check and see if this descendant has a longer weight than the // currently recorded maximum if (results[taskDescendant.Id] > maxDescendantWeight) { maxDescendantWeight = results[taskDescendant.Id]; } } if (hasUnresolvedDescendant) { workingTasks.Enqueue(task); if (firstNoprogressTask == task) { throw new ArgumentException("It seems some descendant activites were not included in the original list and the path length algorithm has stuck"); } if (firstNoprogressTask == null) { firstNoprogressTask = task; } } else { firstNoprogressTask = null; results.Add(task.Id, valueReader.GetValue(task.TimeEstimate) + maxDescendantWeight); foreach (var taskAncestor in task.Ancestors) { if (!workingTasks.Contains(taskAncestor)) { workingTasks.Enqueue(taskAncestor); } } } } return(results); }