Beispiel #1
0
        private static Chain TryToOptimizeJ21(ExperimentInfo experimentInfo)
        {
            var(firstBox, secondBox, asteriskBox) = SplitToBoxes(
                experimentInfo.J21,
                detail => detail.OnSecond.Time.B <= detail.OnFirst.Time.A,
                detail => detail.OnFirst.Time.B <= detail.OnSecond.Time.A);

            var sortedFirstBox = firstBox
                                 .OrderBy(detail => detail.OnSecond.Time.A)
                                 .ToList();

            var sortedSecondBox = secondBox
                                  .OrderBy(detail => detail.OnFirst.Time.A)
                                  .Reverse()
                                  .ToList();

            var firstChain = GetChainFromBox(
                sortedFirstBox,
                (previousDetail, currentDetail) => previousDetail.OnSecond.Time.B > currentDetail.OnSecond.Time.A);

            var secondChain = GetChainFromBox(
                sortedSecondBox,
                (previousDetail, currentDetail) => previousDetail.OnFirst.Time.A < currentDetail.OnFirst.Time.B);

            if (!asteriskBox.Any())
            {
                return(new Chain(firstChain.Concat(secondChain)));
            }

            if (asteriskBox.Count() == 1)
            {
                return(new Chain(firstChain.Append(asteriskBox.First()).Concat(secondChain)));
            }

            //find conflict borders
            var minAOnFirst  = asteriskBox.Min(detail => detail.OnFirst.Time.A);
            var minAOnSecond = asteriskBox.Min(detail => detail.OnSecond.Time.A);

            var resultChain = new Chain();
            var jConflict   = new Conflict();

            foreach (var chainElement in firstChain)
            {
                if (chainElement.Type == ChainType.Conflict)
                {
                    var conflict = chainElement as Conflict;
                    if (conflict.Details.Values.Max(detail => detail.OnSecond.Time.B) > minAOnSecond)
                    {
                        //we find a border of conflict
                        var chainNode = firstChain.Find(chainElement);

                        while (chainNode != null)
                        {
                            var nodeValue = chainNode.Value;
                            jConflict.AddDetails(nodeValue);
                            chainNode = chainNode.Next;
                        }

                        break;
                    }

                    resultChain.AddLast(chainElement);
                }
                else
                {
                    var detail = chainElement as LaboriousDetail;
                    if (detail.OnSecond.Time.B > minAOnSecond)
                    {
                        //we find a border of conflict
                        var chainNode = firstChain.Find(chainElement);

                        while (chainNode != null)
                        {
                            jConflict.AddDetails(chainNode.Value);
                            chainNode = chainNode.Next;
                        }

                        break;
                    }

                    resultChain.AddLast(chainElement);
                }
            }

            jConflict.Details.AddRange(asteriskBox.Select(x =>
                                                          new KeyValuePair <int, LaboriousDetail>(x.Number, x)));

            foreach (var chainElement in secondChain)
            {
                if (chainElement.Type == ChainType.Conflict)
                {
                    var conflict = chainElement as Conflict;
                    if (conflict.Details.Values.Max(detail => detail.OnFirst.Time.B) > minAOnFirst)
                    {
                        jConflict.Details.AddRange(conflict.Details);
                    }
                    else
                    {
                        resultChain.AddLast(jConflict);
                        jConflict = null;
                        var chainNode = secondChain.Find(chainElement);

                        while (chainNode != null)
                        {
                            resultChain.AddLast(chainNode.Value);
                            chainNode = chainNode.Next;
                        }

                        break;
                    }
                }
                else
                {
                    var detail = chainElement as LaboriousDetail;
                    if (detail.OnFirst.Time.B > minAOnFirst)
                    {
                        jConflict.Details.Add(detail.Number, detail);
                    }
                    else
                    {
                        resultChain.AddLast(jConflict);
                        jConflict = null;
                        var chainNode = secondChain.Find(chainElement);

                        while (chainNode != null)
                        {
                            resultChain.AddLast(chainNode.Value);
                            chainNode = chainNode.Next;
                        }

                        break;
                    }
                }
            }

            if (jConflict != null)
            {
                resultChain.AddLast(jConflict);
            }

            return(resultChain);
        }