private static void ResolveConflictOnMachine( OnlineConflict conflict, ref LinkedListNode <IOnlineChainNode> nodeOnCurrentMachine, ref LinkedListNode <IOnlineChainNode> nodeOnAnotherMachine, bool isFirstDetail, OnlineChain chainOnCurrentMachine, OnlineChain chainOnAnotherMachine, double timeFromMachinesStart, OnlineExecutionContext context) { if (!(chainOnAnotherMachine.First(i => i.Type == OnlineChainType.Conflict && (i as OnlineConflict).Details.Keys.SequenceEqual(conflict.Details.Keys)) is OnlineConflict conflictOnAnotherMachine)) { throw new InvalidOperationException("Not found conflict on another machine"); } var conflictNodeOnAnotherMachine = chainOnAnotherMachine.Find(conflictOnAnotherMachine); var nodeOnCurrentMachineToRemove = nodeOnCurrentMachine; if (!isFirstDetail) { var sumOfPOnCurrent = chainOnCurrentMachine .TakeWhile(i => !Equals(i, nodeOnCurrentMachineToRemove.Value)) .Sum(i => i.Type switch { OnlineChainType.Detail when i is Detail detail => detail.Time.P, OnlineChainType.Downtime when i is Downtime downtime => downtime.Time, _ => throw new InvalidOperationException() });
private static void ProcessDetailOnMachine( OnlineChain chain, ref LinkedListNode <IOnlineChainNode> node, Func <Detail, double> downtimeCalculationFunc, ISet <int> processedDetailNumbersOnAnotherMachine, ref double time, bool isFirstDetail, OnlineExecutionContext context, ConflictResolverDelegate conflictResolver) { var currentDetail = node.Value; if (currentDetail.Type == OnlineChainType.Conflict) { var conflict = currentDetail as OnlineConflict; var start = Stopwatch.GetTimestamp(); conflictResolver(conflict, ref node, context, isFirstDetail); var stop = Stopwatch.GetTimestamp(); context.ExecutionTime = context.ExecutionTime.Add( TimeSpan.FromMilliseconds((stop - start) / (double)Stopwatch.Frequency * 1000)); if (node.Value.Type != OnlineChainType.Detail) { throw new InvalidOperationException("Conflict resolver didn't change current node"); } currentDetail = node.Value; } if (!(currentDetail is Detail detail)) { throw new InvalidCastException( $"Try cast {currentDetail.GetType().FullName} to {typeof(Detail).FullName}"); } if (processedDetailNumbersOnAnotherMachine.Contains(detail.Number)) { time += detail.Time.P; } else { var downTime = downtimeCalculationFunc(detail); if (Math.Abs(downTime) < 0.000000000000001) { node = node.Previous; return; } node = chain.AddBefore(node, new Downtime(downTime)); time += downTime; } }
public void Execute_ShouldBeFinishedWithoutAnyExceptions(string path, OnlineChain onlineChainOnFirst, OnlineChain onlineChainOnSecond, HashSet <int> processedOnFirst, HashSet <int> processedOnSecond) { // Arrange _outputHelper.WriteLine($"Running test with data from '{path}'"); // Act var context = _onlineExecutor.Execute(onlineChainOnFirst, onlineChainOnSecond, processedOnFirst, processedOnSecond); // Assert context.Should().NotBeNull(); }
private static OnlineChain GetOnlineChainOnSecondMachine(ExperimentInfo experimentInfo) { var onlineChain = new OnlineChain(); foreach (var chainNode in experimentInfo.J21Chain) { var element = chainNode.Type switch { ChainType.Detail when chainNode is LaboriousDetail detail => (IOnlineChainNode)detail.OnSecond, ChainType.Conflict when chainNode is Conflict conflict => new OnlineConflict( conflict.Details.Values.Select(d => new KeyValuePair <int, Detail>(d.OnSecond.Number, d.OnSecond))), _ => throw new InvalidOperationException() }; onlineChain.AddLast(element); } foreach (var j2 in experimentInfo.J2) { onlineChain.AddLast(j2); } foreach (var chainNode in experimentInfo.J12Chain) { var element = chainNode.Type switch { ChainType.Detail when chainNode is LaboriousDetail detail => (IOnlineChainNode)detail.OnSecond, ChainType.Conflict when chainNode is Conflict conflict => new OnlineConflict( conflict.Details.Values.Select(d => new KeyValuePair <int, Detail>(d.OnSecond.Number, d.OnSecond))), _ => throw new InvalidOperationException() }; onlineChain.AddLast(element); } return(onlineChain); }
public OnlineExecutionContext Execute(OnlineChain onlineChainOnFirst, OnlineChain onlineChainOnSecond, HashSet <int> processedDetailsOnFirst, HashSet <int> processedDetailsOnSecond) { var context = new OnlineExecutionContext(); IOnlineChainNode currentDetailOnFirst = null; IOnlineChainNode currentDetailOnSecond = null; var timeFromMachinesStart = 0.0; var time1 = 0.0; var time2 = 0.0; var isFirstDetail = true; var nodeOnFirstMachine = onlineChainOnFirst.First; var nodeOnSecondMachine = onlineChainOnSecond.First; var hasDetailOnFirst = nodeOnFirstMachine != null; var hasDetailOnSecond = nodeOnSecondMachine != null; // details are on two machines while (hasDetailOnFirst && hasDetailOnSecond || time1 > time2 && hasDetailOnSecond || time2 > time1 && hasDetailOnFirst) { // time1 equal to time2 if (Math.Abs(time1 - time2) < 0.001) { if (hasDetailOnFirst) { ProcessDetailOnMachine( ref currentDetailOnFirst, processedDetailsOnFirst, processedDetailsOnSecond, ref nodeOnFirstMachine, ref nodeOnSecondMachine, timeFromMachinesStart, onlineChainOnFirst, onlineChainOnSecond, ref time1, out hasDetailOnFirst, isFirstDetail, context); } //if (nodeOnSecondMachine?.List == null) //{ // if (isFirstDetail) // nodeOnSecondMachine = experimentInfo.OnlineChainOnSecondMachine.First; //} if (hasDetailOnSecond) { ProcessDetailOnMachine( ref currentDetailOnSecond, processedDetailsOnSecond, processedDetailsOnFirst, ref nodeOnSecondMachine, ref nodeOnFirstMachine, timeFromMachinesStart, onlineChainOnSecond, onlineChainOnFirst, ref time2, out hasDetailOnSecond, isFirstDetail, context); } } else if (time1 < time2) { ProcessDetailOnMachine( ref currentDetailOnFirst, processedDetailsOnFirst, processedDetailsOnSecond, ref nodeOnFirstMachine, ref nodeOnSecondMachine, timeFromMachinesStart, onlineChainOnFirst, onlineChainOnSecond, ref time1, out hasDetailOnFirst, isFirstDetail, context); } else { ProcessDetailOnMachine( ref currentDetailOnSecond, processedDetailsOnSecond, processedDetailsOnFirst, ref nodeOnSecondMachine, ref nodeOnFirstMachine, timeFromMachinesStart, onlineChainOnSecond, onlineChainOnFirst, ref time2, out hasDetailOnSecond, isFirstDetail, context); } timeFromMachinesStart = Math.Min(time1, time2); isFirstDetail = false; } // details only on first machines if (hasDetailOnFirst) { for (var node = nodeOnFirstMachine; node != null; node = node.Next) { if (node.Value is Detail detail) { time1 += detail.Time.P; } else { throw new InvalidOperationException( "There can be no conflicts and downtimes when one of machine finished work"); } } } else { // details only on second machine for (var node = nodeOnSecondMachine; node != null; node = node.Next) { if (node.Value is Detail detail) { time2 += detail.Time.P; } else { throw new InvalidOperationException( "There can be no conflicts and downtimes when one of machine finished work"); } } } timeFromMachinesStart = Math.Max(time1, time2); context.TimeFromMachinesStart = timeFromMachinesStart; context.Time1 = time1; context.Time2 = time2; return(context); }