public void Execute(object parameter) { var viewModel = parameter as PertPageViewModel; // ノード番号を自動割り付け var input = new CalcNodeNumberInput() { FunctionDependencies = this.appContext.FunctionDependencies, ProcessDependencies = this.appContext.ProcessDependencies, Tasks = viewModel.Edges.Where(x => x.TaskId.HasValue).Select(x => this.appContext.Tasks.FirstOrDefault(y => x.TaskId == y.TaskCd)).ToArray() }; var ret = this.businessLogic.Execute(input); this.appContext.PertEdges.Clear(); this.appContext.PertEdges.AddRange(ret.PertEdges); }
public CalcNodeNumberOutput Execute(CalcNodeNumberInput input) { //変数を設定 var result = new CalcNodeNumberOutput() { PertEdges = Enumerable.Empty <Pert>() }; var funcDependencies = input.FunctionDependencies.Where(x => x.DependencyTypeCd.HasValue && x.DstFunctionCd.HasValue && x.OrgFunctionCd.HasValue).ToArray(); var procDependencies = input.ProcessDependencies.Where(x => x.DependencyType.HasValue && x.DstProcessCd.HasValue && x.OrgProcessCd.HasValue).ToArray(); var tasks = input.Tasks.ToArray(); int cnt = 0; var dependencyMap = new Dictionary <Task, IList <IList <KeyValuePair <Task, DependencyTypes> > > >(); var dependencyList = new Dictionary <Task, IEnumerable <KeyValuePair <Task, DependencyTypes> > >(); foreach (var task in tasks) { var fromTasks = new List <KeyValuePair <Task, DependencyTypes> >(); // 機能依存から依存元タスクを導出 var fromFunctionIds = funcDependencies.Where(x => x.DstFunctionCd == task.FunctionCd) //&& (x.DependencyTypeCd == Entities.Enum.DependencyTypes.FinishStartDependency // || x.DependencyTypeCd == Entities.Enum.DependencyTypes.FinishFinishDependency)) .ToDictionary(x => x.OrgFunctionCd.Value, x => x.DependencyTypeCd.Value); var fromTasksByFunctionDependency = fromFunctionIds.SelectMany(x => tasks.Where(y => y.FunctionCd == x.Key && task.ProcessCd == y.ProcessCd).Select(y => new KeyValuePair <Task, Entities.Enum.DependencyTypes>(y, x.Value))); // 工程依存から依存元タスクを導出 var fromProcessIds = procDependencies.Where(x => x.DstProcessCd == task.ProcessCd) //&& (x.DependencyType == Entities.Enum.DependencyTypes.FinishStartDependency // || x.DependencyType == Entities.Enum.DependencyTypes.FinishFinishDependency)) .ToDictionary(x => x.OrgProcessCd.Value, x => x.DependencyType.Value); var fromTasksByProcessDependency = fromProcessIds.SelectMany(x => tasks.Where(y => y.ProcessCd == x.Key && task.FunctionCd == y.FunctionCd).Select(y => new KeyValuePair <Task, Entities.Enum.DependencyTypes>(y, x.Value))); fromTasks.AddRange(fromTasksByFunctionDependency.Concat(fromTasksByProcessDependency)); dependencyList.Add(task, fromTasks); } // 次のスライスを演算子結果を受理 var nextResult = DoSlicing(tasks, funcDependencies, procDependencies, dependencyList, cnt++); // 結果をマージ foreach (var task in tasks) { dependencyMap[task] = new List <IList <KeyValuePair <Task, DependencyTypes> > >() { dependencyList[task].ToList() }.Concat(nextResult[task].Select(x => x)).ToList(); } // 順番に番号を付けていく var allocationList = new Dictionary <Task, Pert>(); var resultEdges = new List <Pert>(); var createdDstNode = new Dictionary <Task, int>(); var currentNodeNumber = 2; var createNumber = 0; foreach (var taskGraph in dependencyMap) { var task = taskGraph.Key; createNumber = 0; // 一次スライス(直前のタスク)のタスクから順に検索する var beforeNode = null as int?; var mergeEdgeList = new List <Pert>(); var dependencyTasks = new List <KeyValuePair <Task, DependencyTypes> >(); foreach (var dependencyNodes in taskGraph.Value) { var maybeFromTasks = dependencyNodes.Where(x => x.Value == DependencyTypes.FinishStartDependency || x.Value == DependencyTypes.FinishFinishDependency).ToArray(); foreach (var maybeFrom in maybeFromTasks) { // ESまたはEEの場合は該当タスクの終端番号を開始番号とする // 2つ以上EE ESの関係がある場合、次数の低いスライスのタスクに高い次数のタスクがEE ESに含まれていないか調べる。 // 見つかった場合その関係は無視してよい。無視できない場合はマージ用ノードを作成し、依存ノードとマージノードの間に関係を作成する if (beforeNode.HasValue == false) { beforeNode = allocationList[maybeFrom.Key].DstNodeCd; } else { if (dependencyTasks.SelectMany(x => dependencyMap[x.Key].SelectMany(y => y.Select(z => z))) .Where(x => x.Value == DependencyTypes.FinishStartDependency || x.Value == DependencyTypes.FinishFinishDependency) .Select(x => x.Key) .Contains(maybeFrom.Key) == false) { // マージ用ノードを作成 if (mergeEdgeList.Count == 0) { // 最初に検出したエッジの宛先をマージ用ノードにする var firstTaskPert = allocationList[dependencyTasks.First().Key]; mergeEdgeList.Add(new Pert() { Id = this.pertIdGen.CreateNewId(), SrcNodeCd = firstTaskPert.DstNodeCd, DstNodeCd = currentNodeNumber, TaskCd = null, }); } // 依存元タスクとマージ用ノードをつなぐエッジ var maybeFromPert = null as Pert; var dstNodeNumber = 0; if (allocationList.ContainsKey(maybeFrom.Key)) { maybeFromPert = allocationList[maybeFrom.Key]; dstNodeNumber = maybeFromPert.DstNodeCd; } else { if (createdDstNode.ContainsKey(maybeFrom.Key) == false) { createNumber++; createdDstNode.Add(maybeFrom.Key, currentNodeNumber + createNumber); } dstNodeNumber = createdDstNode[maybeFrom.Key]; } mergeEdgeList.Add(new Pert() { Id = this.pertIdGen.CreateNewId(), SrcNodeCd = dstNodeNumber, DstNodeCd = currentNodeNumber, TaskCd = null, }); beforeNode = currentNodeNumber; } } dependencyTasks.Add(maybeFrom); } } if (mergeEdgeList.Count > 0) { currentNodeNumber += createNumber + 1; resultEdges.AddRange(mergeEdgeList); } var pert = new Pert() { Id = this.pertIdGen.CreateNewId(), SrcNodeCd = beforeNode ?? 1, DstNodeCd = createdDstNode.ContainsKey(task) ? createdDstNode[task] : currentNodeNumber, TaskCd = task.TaskCd, }; if (createdDstNode.ContainsKey(task) == false) { currentNodeNumber++; } allocationList.Add(task, pert); resultEdges.Add(pert); } result.PertEdges = resultEdges; return(result); }