public void Delete_Random_Consistency() { var random = new Random(); var testEnd = DateTime.Now.AddSeconds(30); while (DateTime.Now < testEnd) { var tasks = new List <KAction>(); var rootTasksCount = random.Next(10); var currentWbsParts = new Stack <int>(); currentWbsParts.Push(0); PopulateRandom(random, tasks, currentWbsParts, 5, false); WriteTasksWBS(tasks); ActionsTimingsMoveManagement.DebugCheckAllWBS(tasks); if (CheckWBS(tasks) != null) { throw new InvalidOperationException("Wrong generation"); } while (tasks.Count > 0) { var index = random.Next(tasks.Count); var countToDelete = Math.Min(random.Next(1, 10), tasks.Count); var toDelete = tasks[index]; var currentStatus = Clone(tasks).ToArray(); ActionsTimingsMoveManagement.DeleteUpdateWBS(tasks.ToArray(), toDelete); tasks.Remove(toDelete); TestContext.WriteLine("Deleted: {0} {1}.", toDelete.WBS, toDelete.Label); var wrongWbs = CheckWBS(tasks); if (wrongWbs != null) { // Rappeler l'état d'origine et l'élément supprimé TestContext.WriteLine("Fail!"); TestContext.WriteLine("--- Before deletion, indented format:"); WriteTasksWBS(currentStatus); TestContext.WriteLine("--- Before deletion, appended format: {0}", string.Join(" ", currentStatus.Select(t => t.WBS))); TestContext.WriteLine("--- Deleted element {0} {1}", toDelete.WBS, toDelete.Label); TestContext.WriteLine("--- After deletion, indented format:"); WriteTasksWBS(tasks); Assert.Fail("The WBS {0} is invalid", wrongWbs); } ActionsTimingsMoveManagement.DebugCheckAllWBS(tasks); } } }
/// <summary> /// Met à jour les actions récursivement sur les scénarios dérivés de celui spécifié. /// </summary> /// <param name="context">Le contexte EF.</param> /// <param name="sourceScenario">Le scénario source.</param> /// <param name="allScenarios">Tous les scénarios qui peuvent être impactés.</param> /// <param name="actionsToRemove">Les actions à supprimer manuellement.</param> internal static void UpdateActions(KsmedEntities context, Scenario sourceScenario, Scenario[] allScenarios, out KAction[] actionsToRemove, out IList <KAction> actionsWithOriginal) { var derivedScenarios = ScenarioActionHierarchyHelper.GetDerivedScenarios(sourceScenario, allScenarios); var actions = GetActionsSortedWBS(sourceScenario); actionsWithOriginal = new List <KAction>(); foreach (var scenario in derivedScenarios) { // Mettre à jour IsGroup foreach (var action in scenario.Actions) { action.IsGroup = WBSHelper.HasChildren(action, scenario.Actions); } } foreach (var originalAction in actions) { // J'enlève le IsMArkedAsModified car les 2 références sont la sauvegarde des actions depuis la construction et depuis l'optimisation // Or depuis la construction, en modification, le bout de code cidessous est déjà appelé // Et depuis l'optimisation, il n'y a pas de changement de temps video if (originalAction.IsMarkedAsAdded /*|| originalAction.IsMarkedAsModified*/) { var originalValues = originalAction.ChangeTracker.OriginalValues; var modifiedValues = originalAction.ChangeTracker.ModifiedValues; if (originalAction.IsMarkedAsAdded || modifiedValues.ContainsKey(ActionsTimingsMoveManagement.KActionStartPropertyName) || modifiedValues.ContainsKey(ActionsTimingsMoveManagement.KActionFinishPropertyName)) { // Vérifier si le temps vidéo a changé ActionsTimingsMoveManagement.GetOrignalModifiedVideoDurations(originalAction, out long originalDuration, out long modifiedDuration); bool hasVideoDurationChanged = originalDuration != modifiedDuration; // Si c'est une tâche créée et non dupliquée, le buildDuration est à 0, donc on doit le mettre à jour //Sinon, si c'est une tâche dupliquée, on le laisse tel quel. if (originalAction.BuildDuration == 0) { var paceRating = originalAction.Resource != null ? originalAction.Resource.PaceRating : 1d; originalAction.BuildDuration = Convert.ToInt64(modifiedDuration * paceRating); } } } if (originalAction.IsMarkedAsAdded) { // Si l'action est une action nouvelle dans un scénario cible, définir automatiquement la partie réduite if (sourceScenario.NatureCode == KnownScenarioNatures.Target && originalAction.Reduced == null) { SharedScenarioActionsOperations.ApplyNewReduced(originalAction); } var originalActionKey = context.CreateEntityKey(KsmedEntities.KActionsEntitySetName, originalAction); var parentOriginalAction = WBSHelper.GetParent(originalAction, actions); foreach (var derivedScenario in derivedScenarios) { var derivedActions = GetActionsSortedWBS(derivedScenario); // Rechercher le parent dans le scénario dérivé var parentDerivedAction = ScenarioActionHierarchyHelper.GetDerivedAction(parentOriginalAction, derivedScenario); // Cloner l'action originale var newAction = ScenarioCloneManager.CloneAction(originalAction, ActionCloneBehavior.Cascade); // Assigner l'original var originalActionForCurrentDerivedScenario = derivedScenario.Original == sourceScenario ? originalAction : ScenarioActionHierarchyHelper.GetDerivedAction(originalAction, derivedScenario.Original); newAction.Original = originalActionForCurrentDerivedScenario; actionsWithOriginal.Add(newAction); // Insérer l'action clonée dans le scénario dérivé ActionsTimingsMoveManagement.InsertUpdateWBS( derivedActions, newAction, parentDerivedAction, WBSHelper.GetParts(originalAction.WBS).Last(), (a, wbs) => EnsureTracking(a)); // Rafraichir les actions derivedScenario.Actions.Add(newAction); derivedActions = GetActionsSortedWBS(derivedScenario); // Ajouter les mêmes prédécesseurs et successeurs foreach (var originalPredecessor in originalAction.Predecessors) { var derivedPredecessor = ScenarioActionHierarchyHelper.GetDerivedAction(originalPredecessor, derivedScenario); if (derivedPredecessor != null) { EnsureTracking(derivedPredecessor); ActionsTimingsMoveManagement.AddPredecessor(derivedActions, newAction, derivedPredecessor); } } foreach (var originalSuccessor in originalAction.Successors) { var derivedSuccessor = ScenarioActionHierarchyHelper.GetDerivedAction(originalSuccessor, derivedScenario); if (derivedSuccessor != null) { EnsureTracking(derivedSuccessor); ActionsTimingsMoveManagement.AddPredecessor(derivedActions, derivedSuccessor, newAction); } } EnsureTracking(derivedScenario); SharedScenarioActionsOperations.EnsureEmptySolutionExists(derivedScenario); SharedScenarioActionsOperations.UdpateSolutionsApprovedState(derivedScenario); ActionsTimingsMoveManagement.DebugCheckAllWBS(derivedActions); } } else if (originalAction.IsMarkedAsModified) { var originalValues = originalAction.ChangeTracker.OriginalValues; var modifiedValues = originalAction.ChangeTracker.ModifiedValues; var propertiesToCopyValues = new Dictionary <string, object>(); foreach (var propertyName in _kActionPropertyNamesToCopy) { if (modifiedValues.ContainsKey(propertyName)) { propertiesToCopyValues[propertyName] = modifiedValues[propertyName]; } } // Vérifier si les reduced doit être impactés également ActionsTimingsMoveManagement.GetOrignalModifiedBuildDurations(originalAction, out long originalDuration, out long modifiedDuration); bool hasBuildDurationChanged = originalDuration != modifiedDuration; foreach (var derivedScenario in derivedScenarios) { var derivedAction = ScenarioActionHierarchyHelper.GetDerivedAction(originalAction, derivedScenario); if (derivedAction != null) { EnsureTracking(derivedAction); foreach (var kvp in propertiesToCopyValues) { derivedAction.SetPropertyValue(kvp.Key, kvp.Value); } if (hasBuildDurationChanged) { if (derivedAction.IsReduced) { // Modifier l'original duration et recalculer le temps final en fonction du gain EnsureTracking(derivedAction.Reduced); derivedAction.Reduced.OriginalBuildDuration = modifiedDuration; ActionsTimingsMoveManagement.UpdateTimingsFromReducedReduction(derivedAction); } else { // Simplement recopier la durée derivedAction.BuildDuration = modifiedDuration; } } } } } } var toRemove = new List <KAction>(); // Gérer les actions supprimées // EF gérant mal l'ordre des suppressions, ça créer une ConstraintException sur la FK OriginalActionId // Malheureusement un CascadeDelete est impossible puisque la FK est sur un même table if (sourceScenario.ChangeTracker.ObjectsRemovedFromCollectionProperties.ContainsKey("Actions")) { var removedActions = sourceScenario.ChangeTracker.ObjectsRemovedFromCollectionProperties["Actions"].ToArray(); foreach (KAction originalAction in removedActions) { EnsureTracking(originalAction); toRemove.Add(originalAction); originalAction.MarkAsUnchanged(); foreach (var derivedScenario in derivedScenarios) { var derivedAction = ScenarioActionHierarchyHelper.GetDerivedAction(originalAction, derivedScenario); if (derivedAction != null) { var derivedActions = GetActionsSortedWBS(derivedScenario); // Mettre à jour les WBS des autres actions ActionsTimingsMoveManagement.DeleteUpdateWBS(derivedActions, derivedAction, (a, wbs) => EnsureTracking(a)); EnsureTracking(derivedAction); toRemove.Add(derivedAction); } } } // Il faut maintenant trier les actions à supprimer pour que la suppression se fasse dans le bon ordre toRemove.Reverse(); actionsToRemove = toRemove.ToArray(); } else { actionsToRemove = new KAction[] { } }; sourceScenario.CriticalPathIDuration = ActionsTimingsMoveManagement.GetInternalCriticalPathDuration(sourceScenario); foreach (var scenario in derivedScenarios) { EnsureTracking(scenario); ActionsTimingsMoveManagement.FixPredecessorsSuccessorsTimings(scenario.Actions.ToArray(), false); ActionsTimingsMoveManagement.UpdateVideoGroupsTiming(scenario.Actions.ToArray()); ActionsTimingsMoveManagement.UpdateBuildGroupsTiming(scenario.Actions.ToArray()); scenario.CriticalPathIDuration = ActionsTimingsMoveManagement.GetInternalCriticalPathDuration(scenario); } }
public void Delete_From_Input_TestCases() { var jsonObject = JObject.Parse(File.ReadAllText("ActionsTimingsMoveManagement_DeleteTestCases.json")); JArray cases = (JArray)jsonObject["delete"]; var testCases = JsonConvert.DeserializeObject <DeleteTestCase[]>(cases.ToString()); foreach (var tc in testCases) { TestContext.WriteLine("---------------------------------"); TestContext.WriteLine("Analyzing Test Case {0}", tc.Label); var inputTasks = new List <KAction>(); var wbses = tc.Input.Split(' '); foreach (var wbs in wbses) { var task = new KAction { Label = "T" + wbs, WBS = wbs, }; inputTasks.Add(task); } TestContext.WriteLine("Input :", tc.Label); WriteTasksWBS(inputTasks); TestContext.WriteLine("Delete : {0}", tc.Delete); var tasksToDelete = inputTasks.Where(t => tc.Delete.Any(wbs => wbs == t.WBS)).ToArray(); var outputTasks = inputTasks.ToList(); foreach (var task in tasksToDelete) { TestContext.WriteLine("Deleting : {0}", tc.Delete); ActionsTimingsMoveManagement.DeleteUpdateWBS(outputTasks.ToArray(), task); outputTasks.Remove(task); WriteTasksWBS(outputTasks); ActionsTimingsMoveManagement.DebugCheckAllWBS(outputTasks); } TestContext.WriteLine("Output :", tc.Label); WriteTasksWBS(outputTasks); TestContext.WriteLine("Expected :", tc.Label); WriteTasksWBS(tc.Expected); int i = 0; foreach (var expectedWbs in tc.Expected.Keys) { var expectedLabel = tc.Expected[expectedWbs]; if (outputTasks.Count - 1 < i) { Assert.Fail("The actual has less tasks than expected"); } var task = outputTasks[i]; var actualWbs = task.WBS; var actuallabel = task.Label; Assert.AreEqual(expectedWbs, task.WBS, string.Format("Expected {0}: {1}, Found {2}: {3}", expectedWbs, expectedLabel, actualWbs, actuallabel)); Assert.AreEqual(expectedLabel, actuallabel, string.Format("Expected {0}: {1}, Found {2}: {3}", expectedWbs, expectedLabel, actualWbs, actuallabel)); i++; } if (i != outputTasks.Count) { Assert.Fail("The actual has more tasks than expected"); } } }