/// /// Copyright (c) 2013-2015 Sensus Metering Systems /// using System; using System.Collections.Generic; using log4net; using Config.Entities; using TBF.UiBridge; using TBF.BenchControl; using TBF.BenchControl.Operations; using TBF.BenchControl.GenericDevices; using TBF.Boxes; using TBF.Resources; namespace TBF.BenchControl.Sequences { public class MainSeq : SequenceBase { private static readonly ILog log = LogManager.GetLogger(typeof(MainSeq)); public override string ToString() { return "Sequences.MainSeq"; } int simultWithPurgingCount; Generic.IComponentCfg simultWithPurgingCfg; IList simultWithPurgingTests; IList simultWithPurgingParams; int simultWithEvacuationCount; Generic.IComponentCfg simultWithEvacuationCfg; IList simultWithEvacuationTests; IList simultWithEvacuationParams; System.Windows.Forms.Form modelessDlg; /// delegate void iPerlCommFormDlgt(MainSeq myRef, Generic.IComponentCfg cfg, IList tests, IList multiTestParams); /// void OpenIPerlCommForm(MainSeq myRef, Generic.IComponentCfg cfg, IList tests, IList multiTestParams) { try { /// 1nd argument TestMethods.iPerlCommunication.TestMethodCfg iPerlCfg = cfg as TestMethods.iPerlCommunication.TestMethodCfg; /// 2rd argument: as is /// 3th argument IList iPerlCommParams = new List(); foreach (var tp in multiTestParams) iPerlCommParams.Add(tp as TestMethods.iPerlCommunication.iPerlCommunicationParams); myRef.modelessDlg = new TestMethods.iPerlCommunication.iPerlCommunicationForm(iPerlCfg, tests, iPerlCommParams); myRef.modelessDlg.Show(); } catch (Exception e) { log.FatalFormat("---------------( MainSeq : OpenIperlCommForm crashed !!! )---------------"); log.FatalFormat("Message : {0}", e.Message); if (e.InnerException != null) { log.FatalFormat("InnerMessage : {0}", e.InnerException.Message); } log.FatalFormat("StackTrace : {0}{1}", Environment.NewLine, e.StackTrace); log.Fatal("--------------------------------------"); } } void CloseIPerlCommForm() { UiBridge.Bridge.OnCloseModelessForm(this, null); modelessDlg = null; } /// Constructor public MainSeq() { simultWithPurgingTests = new List(); simultWithPurgingParams = new List(); simultWithEvacuationTests = new List(); simultWithEvacuationParams = new List(); } /// /// Main sequence /// /// /// public IList Execute(Test dummyArg) { /// Operations running in more then one state checkUiOp = new CheckUIOp(true); IList e; Selection selection; bool benchFilled = false; simultWithPurgingCount = 0; simultWithPurgingCfg = null; simultWithPurgingTests.Clear(); simultWithPurgingParams.Clear(); simultWithEvacuationCount = 0; simultWithEvacuationCfg = null; simultWithEvacuationTests.Clear(); simultWithEvacuationParams.Clear(); StateMachine.LoadProcedure(true); // TODO: Implement as an operation so that the worker thread is not blocked Bridge.Bench2UI(ButtonsEtc.StopBtnEn); //-------------------------------------------------------------------------------------------- Bridge.OnActivity(this, Strings.Starting_system); State.Create("MainSeq : Setting valves to default positions") .AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (e.Contains(Event.ValvesBusy)); //-------------------------------------------------------------------------------------------- IntBox remainingTime = new IntBox(); State startNew = State.Create("MainSeq : Emptying tanks, Starting cameras") .AddOperation(checkUiOp); foreach (var cmpnt in StateMachine.Components) { Cameras.IdcCamera.IdcCamera camera = cmpnt as Cameras.IdcCamera.IdcCamera; if ((camera != null) && (camera.Cfg.DebugLevel != DebugMode.DetectedOff)) { startNew.AddOperation(camera.StartNewOp()); } } IList allEmptyingValves = new List(); if (StateMachine.EmptyTankValve1 != null) allEmptyingValves.Add(StateMachine.EmptyTankValve1); if (StateMachine.EmptyTankValve2 != null) allEmptyingValves.Add(StateMachine.EmptyTankValve2); if (StateMachine.EmptyTankValve3 != null) allEmptyingValves.Add(StateMachine.EmptyTankValve3); // Determine the tank emptying time (the maximum for all balances) int balanceEmptyTime = 0; if (StateMachine.Balance1 != null && StateMachine.Balance1.EmptyTimeSec > balanceEmptyTime) { balanceEmptyTime = StateMachine.Balance1.EmptyTimeSec; } if (StateMachine.Balance2 != null && StateMachine.Balance2.EmptyTimeSec > balanceEmptyTime) { balanceEmptyTime = StateMachine.Balance2.EmptyTimeSec; } if (StateMachine.Balance3 != null && StateMachine.Balance3.EmptyTimeSec > balanceEmptyTime) { balanceEmptyTime = StateMachine.Balance3.EmptyTimeSec; } if (balanceEmptyTime > 0) { startNew.AddOperation(new TimerOp(balanceEmptyTime, remainingTime)) .AddOperation(StateMachine.ControlBoard.SetValvesOp(allEmptyingValves, null)); } startNew.EnterState(); do { Bridge.OnActivity(this, string.Format("{0} ... {1} {2} {3} {4}", Strings.Emptying_tank, remainingTime.Val / 60, "min", remainingTime.Val % 60, Strings.sec)); e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop) && !e.Contains(Event.ValvesBusy) && !e.Contains(Event.CameraBusy)) { goto stop_emptying; } } while (e.Contains(Event.TimerBusy) || e.Contains(Event.CameraBusy) || e.Contains(Event.ValvesBusy)); if (e.Contains(Event.CameraOpFailed)) goto error; /// TODO: resolve in some other way Bridge.OnActivity(this, Strings.Emptying_tank); stop_emptying: //-------------------------------------------------------------------------------------------- State stopEmptying = State.Create("MainSeq : Stop emptying of water tanks") .AddOperation(checkUiOp) .AddOperation(StateMachine.ControlBoard.SetValvesOp(null, allEmptyingValves)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) goto stop; } while (e.Contains(Event.ValvesBusy)); //-------------------------------------------------------------------------------------------- State taraAll = State.Create("MainSeq : Reset all balances").AddOperation(checkUiOp); DoubleBox tara = new DoubleBox(0); if (StateMachine.Balance1 != null) taraAll.AddOperation(StateMachine.Balance1.TaringOp(ref tara)); if (StateMachine.Balance2 != null) taraAll.AddOperation(StateMachine.Balance2.TaringOp(ref tara)); if (StateMachine.Balance3 != null) taraAll.AddOperation(StateMachine.Balance3.TaringOp(ref tara)); taraAll.EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) goto stop; } while (e.Contains(Event.Busy)); //-------------------------------------------------------------------------------------------- Bridge.OnActivity(this, Strings.Measuring_the_weight); State.Create("MainSeq : Mesuring the weight for the 1st time") .AddOperation(checkUiOp) .AddOperation(new MettlerToledo.ReadMassesOp()) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) goto stop; } while (!e.Contains(Event.BalanceDone)); //-------------------------------------------------------------------------------------------- select_procedure: /// Make sure the CycleBeginForm is closed (after an abnormal procedure/test end, etc.) CloseBeginForm(); selection = MakeSelection(MKSelContext.ProcedureNotSelected); //-------------------------------- Bridge.Bench2UI(ButtonsEtc.StopBtnEn); StateMachine.LoadProcedure(false); if (StateMachine.Procedure == null) goto select_procedure; /// /// Procedure selected at this point, a new batch was started /// StateMachine.LoadProcedureParams(StateMachine.Procedure); /// /// Prepare new water meters /// foreach (var wm in WaterMeters) wm.ClearData(); /// Clean water meter data bool compound = (StateMachine.Procedure.MetersKind == MetersKind.Combined); bool heatMeters = (StateMachine.Procedure.MetersKind == MetersKind.HeatMeter); int waterMetersCount = Math.Min(WaterMeters.Count, heatMeters ? Config.Data.HeatMetersCount : (compound ? Config.Data.CompoundWMsCount : Config.Data.WMsCount)); /// Results.Entities.WaterMeterData[] waterMeterData = new Results.Entities.WaterMeterData[waterMetersCount]; /// int[] waterMeterParts = new int[waterMetersCount]; for (int wmNr = 0; wmNr < waterMetersCount; wmNr++) { int ix = compound ? (2 * wmNr) : wmNr; waterMeterParts[wmNr] = Utils.PartNr(wmNr + 1, compound); waterMeterData[wmNr] = new Results.Entities.WaterMeterData() { ProductName = WaterMeters[ix].ProductName, Producer = WaterMeters[ix].Producer, L = WaterMeters[ix].L, DN = WaterMeters[ix].DN, Mounting = WaterMeters[ix].Mounting, Q4_Qmax = WaterMeters[ix].Q4_Qmax, Q3_Qn = WaterMeters[ix].Q3_Qn, Q2_Qt = WaterMeters[ix].Q2_Qt, Q1_Qmin = WaterMeters[ix].Q1_Qmin, MetrologicalClass = WaterMeters[ix].MetrologicalClass, TemperatureClass = WaterMeters[ix].TemperatureClass, PressureLossClass = WaterMeters[ix].PressureLossClass, MaxAdmissiblePressure = WaterMeters[ix].MaxAdmissiblePressure, FlowProfileSensitivityClass = WaterMeters[ix].FlowProfileSensitivityClass, ApprovalInfo = WaterMeters[ix].ApprovalInfo, Certificate = WaterMeters[ix].Certificate, PulsesPerLtr = WaterMeters[ix].PulsesPerLtr, Text1 = WaterMeters[ix].Text1, Text2 = WaterMeters[ix].Text2, Text3 = WaterMeters[ix].Text3, Text4 = WaterMeters[ix].Text4, Text5 = WaterMeters[ix].Text5, Compound = compound, HeatMeter = heatMeters, }; if (compound) { int auxIx = 2 * wmNr + 1; waterMeterData[wmNr].ProducerAux = WaterMeters[auxIx].Producer; waterMeterData[wmNr].Q3_Qn_Aux = WaterMeters[auxIx].Q3_Qn; waterMeterData[wmNr].MetrologicalClassAux = WaterMeters[auxIx].MetrologicalClass; waterMeterData[wmNr].ApprovalInfoAux = WaterMeters[auxIx].ApprovalInfo; } #if IPERLST || IPERLST_SPECIAL BenchControl.WaterMeters.iPerl.WaterMeter iPerl = WaterMeters[wmNr] as BenchControl.WaterMeters.iPerl.WaterMeter; if (iPerl != null) { waterMeterData[wmNr].WMTypeId = iPerl.WMType_ID; waterMeterData[wmNr].WMTypeRev = iPerl.WMType_Rev; } #endif } /// /// Prepare empty results /// BatchRslts = Results.BatchResults.NewFromProcedure(Program.LocalSettings.BatchNr, (BenchInfo != null) ? BenchInfo.TestBenchId : 1, User.CurrentUser.Name, User.CurrentUser.Number, Program.Version, StateMachine.Procedure, waterMeterData, waterMeterParts); StateMachine.CycleStartTimeStamp = BatchRslts.Batch.StartTime; Bridge.OnProcedureSelected(this, new ProcedureSelectedEventArgs(StateMachine.Procedure)); /// Display 'Cycle Begin Form' if (OpenCycleBeginForm()) goto stop; /// Find purge suquences TransitionSequence purgeBegin = null; TransitionSequence purgeEnd = null; foreach (var transition in StateMachine.TransitionSequences) { if (transition.Name == StateMachine.Procedure.TransitionStart) purgeBegin = transition; if (transition.Name == StateMachine.Procedure.TransitionEnd) purgeEnd = transition; } if (selection == Selection.Q1 || selection == Selection.Q2 || selection == Selection.Q3 || selection == Selection.Test) { goto assume_bench_filled; } else if (selection == Selection.Cycle && benchFilled) { //-------------------------------- State.Create("MainSeq : Answer a question") .AddOperation(new Operations.AskYesNoOp(Strings.Fill_with_water)) .AddOperation(checkUiOp) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.No)) goto assume_bench_filled; if (e.Contains(Event.UiCmdStop)) goto select_procedure; } while (!e.Contains(Event.Yes)); } fill_the_bench: CollectSimultSteps(); /// if (simultWithPurgingCount > 0) { /// Make sure the entry form is closed if (UIFlowControl.Stop == WaitBeginFormClosed()) goto stop; /// Open iPerlCommunicationForm ProcessData.RegisterReaders = StateMachine.GetMetersPath(simultWithPurgingTests[0]).RegisterReaders; Program.MainWnd.Invoke(new iPerlCommFormDlgt(OpenIPerlCommForm), new object[] { this, simultWithPurgingCfg, simultWithPurgingTests, simultWithPurgingParams }); } /// /// Purging @ cycle start /// Event evt = Transition(purgeBegin, TransitionContext.PurgeBegin); /// switch (evt) { case Event.Error: if (simultWithPurgingCount > 0) CloseIPerlCommForm(); goto error; case Event.UiCmdStop: if (simultWithPurgingCount > 0) CloseIPerlCommForm(); goto stop; default: break; } if (simultWithPurgingCount > 0) { /// /// Wait until iPerl communications are completed /// bool completed = !(modelessDlg is GenericDevices.IHasCompleted) || (modelessDlg as GenericDevices.IHasCompleted).Completed; if (!completed) { State.Create("MainSeq : Wait until the entry form is closed") .AddOperation(checkUiOp) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.UiCmdStop)) { CloseIPerlCommForm(); goto stop; } completed = (modelessDlg as GenericDevices.IHasCompleted).Completed; } while (!completed); } modelessDlg = null; } assume_bench_filled: benchFilled = true; Bridge.Bench2UI(ButtonsEtc.ShowBenchFilled); if (selection != Selection.PurgeBegin) { goto cycle_or_test_selected; } select_cycle_or_test: //---------------------------------------------------------- selection = MakeSelection(MKSelContext.InsideProcedure); /// if (selection == Selection.PurgeBegin) goto fill_the_bench; if (selection == Selection.PurgeEnd) goto evacuation; if (selection == Selection.Break) { Bridge.Bench2UI(ButtonsEtc.ShowBenchEmpty); goto select_procedure; } if (selection == Selection.SaveResults) goto save_results; cycle_or_test_selected: UiBridge.Bridge.OnError(this, string.Empty); /// Clear an error message (if any) if (UIFlowControl.Stop == WaitBeginFormClosed()) goto stop_within_cycle; /// Make sure the entry form is closed Bridge.Bench2UI(ButtonsEtc.StopBtnEn); /// Hide buttons if (selection != Selection.Cycle) { //-------------------------------- State.Create("MainSeq : Continue in the cycle?") .AddOperation(new Operations.AskYesNoOp(Strings.Continue_in_the_cycle)) .AddOperation(checkUiOp) .EnterState(); while (true) { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Yes)) { selection = Selection.RestOfCycle; break; } if (e.Contains(Event.No)) break; if (e.Contains(Event.UiCmdStop)) goto select_procedure; } } if (selection == Selection.Cycle) { float TimeEstimateTotal; /// Time estimate of the selected cycle or test TimeEstimateTotal = 0; for (int i = simultWithPurgingCount; i < StateMachine.Tests.Count - simultWithEvacuationCount; i++) { Test test = StateMachine.Tests[i]; TimeEstimateTotal += (test.Repeats * (test.TstTime + 10.0f)); /// Try to fetch all test paths and transitions /// to detect configuration errors as early as possible. string errorMsg; if (!StateMachine.GetPaths(test, (StateMachine.Procedure.MetersKind == MetersKind.HeatMeter), out inPath, out benchPath, out outPath, out sensPath, out heatMetersPath, out transitionBefore, out transitionAfter, out errorMsg)) { UiBridge.Bridge.OnError(this, errorMsg); goto select_cycle_or_test; } } int currentTestIx = simultWithPurgingCount; int outerLoopStartIx = currentTestIx; bool outerLoopMode = false; int outerLoopCounter = 0; do { Test test = StateMachine.Tests[currentTestIx]; /// Fetch the test paths and transitions string errorMsg; if (!StateMachine.GetPaths(test, (StateMachine.Procedure.MetersKind == MetersKind.HeatMeter), out inPath, out benchPath, out outPath, out sensPath, out heatMetersPath, out transitionBefore, out transitionAfter, out errorMsg)) { UiBridge.Bridge.OnError(this, errorMsg); goto select_cycle_or_test; } /// Update format for the water mass Mass.Format = outPath.Balance.Format; StartMass.Format = outPath.Balance.Format; EndMass.Format = outPath.Balance.Format; //-------------------------------------------------------------- ITestMethod testMethodSequence = TbfComponents.FindComponent(test.Method) as ITestMethod; if (testMethodSequence != null && testMethodSequence.CanTest(StateMachine.Procedure.MetersKind)) { StateMachine.LoadTestParams(test); ProcessData.RegisterReaders = sensPath.RegisterReaders; foreach (var rr in sensPath.RegisterReaders) { if ((rr is WaterMeters.iPerl.WaterMeter) && (BenchInfo != null)) { (rr as WaterMeters.iPerl.WaterMeter).BenchName = BenchInfo.TestBenchName; } } e = testMethodSequence.Execute(test, outerLoopMode, outerLoopCounter); if (e.Contains(Event.ConfigurationError)) { outerLoopMode = false; outerLoopCounter = 0; goto select_cycle_or_test; } else if (e.Contains(Event.Error)) { outerLoopMode = false; outerLoopCounter = 0; goto error; } else if (e.Contains(Event.OpArgumentError)) { outerLoopMode = false; outerLoopCounter = 0; goto config_error; } else if (e.Contains(Event.UiCmdStop)) { outerLoopMode = false; outerLoopCounter = 0; goto stop_within_cycle; } else if (e.Contains(Event.OuterLoopStart)) { outerLoopMode = true; outerLoopCounter = 1; outerLoopStartIx = currentTestIx; } else if (e.Contains(Event.OuterLoopNext)) { outerLoopCounter++; currentTestIx = outerLoopStartIx; } else if (e.Contains(Event.OuterLoopEnd)) { outerLoopMode = false; outerLoopCounter = 0; } } else { UiBridge.Bridge.OnError(this, string.Format(Strings.Method_0_cannot_be_used, test.Method)); goto select_cycle_or_test; } currentTestIx++; } while (currentTestIx < StateMachine.Tests.Count - simultWithEvacuationCount); } else if (selection == Selection.RestOfCycle) { Test slctdTest = TBF.BenchControl.StateMachine.GetTest(selection); if (slctdTest == null) { UiBridge.Bridge.OnError(this, string.Format("No test specified")); goto select_cycle_or_test; } int selsctedTestIx = -1; for (int i = simultWithPurgingCount; i < StateMachine.Tests.Count - simultWithEvacuationCount; i++) { if (slctdTest == StateMachine.Tests[i]) { selsctedTestIx = i; break; } } if (selsctedTestIx == -1) goto select_cycle_or_test; float TimeEstimateTotal; /// Time estimate of the selected cycle or test TimeEstimateTotal = 0; for (int i = selsctedTestIx; i < StateMachine.Tests.Count - simultWithEvacuationCount; i++) { Test test = StateMachine.Tests[i]; TimeEstimateTotal += (test.Repeats * (test.TstTime + 10.0f)); /// Try to fetch all test paths and transitions /// to detect configuration errors as early as possible. string errorMsg; if (!StateMachine.GetPaths(test, (StateMachine.Procedure.MetersKind == MetersKind.HeatMeter), out inPath, out benchPath, out outPath, out sensPath, out heatMetersPath, out transitionBefore, out transitionAfter, out errorMsg)) { UiBridge.Bridge.OnError(this, errorMsg); goto select_cycle_or_test; } } int currentTestIx = selsctedTestIx; int outerLoopStartIx = currentTestIx; bool outerLoopMode = false; int outerLoopCounter = 0; do { Test test = StateMachine.Tests[currentTestIx]; /// Fetch the test paths and transitions string errorMsg; if (!StateMachine.GetPaths(test, (StateMachine.Procedure.MetersKind == MetersKind.HeatMeter), out inPath, out benchPath, out outPath, out sensPath, out heatMetersPath, out transitionBefore, out transitionAfter, out errorMsg)) { UiBridge.Bridge.OnError(this, errorMsg); goto select_cycle_or_test; } /// Update format for the water mass Mass.Format = outPath.Balance.Format; StartMass.Format = outPath.Balance.Format; EndMass.Format = outPath.Balance.Format; //-------------------------------------------------------------- ITestMethod testMethodSequence = TbfComponents.FindComponent(test.Method) as ITestMethod; if (testMethodSequence != null && testMethodSequence.CanTest(StateMachine.Procedure.MetersKind)) { StateMachine.LoadTestParams(test); ProcessData.RegisterReaders = sensPath.RegisterReaders; foreach (var rr in sensPath.RegisterReaders) { if ((rr is WaterMeters.iPerl.WaterMeter) && (BenchInfo != null)) { (rr as WaterMeters.iPerl.WaterMeter).BenchName = BenchInfo.TestBenchName; } } e = testMethodSequence.Execute(test, outerLoopMode, outerLoopCounter); if (e.Contains(Event.ConfigurationError)) { outerLoopMode = false; outerLoopCounter = 0; goto select_cycle_or_test; } else if (e.Contains(Event.Error)) { outerLoopMode = false; outerLoopCounter = 0; goto error; } else if (e.Contains(Event.OpArgumentError)) { outerLoopMode = false; outerLoopCounter = 0; goto config_error; } else if (e.Contains(Event.UiCmdStop)) { outerLoopMode = false; outerLoopCounter = 0; goto stop_within_cycle; } else if (e.Contains(Event.OuterLoopStart)) { outerLoopMode = true; outerLoopCounter = 1; outerLoopStartIx = currentTestIx; } else if (e.Contains(Event.OuterLoopNext)) { outerLoopCounter++; currentTestIx = outerLoopStartIx; } else if (e.Contains(Event.OuterLoopEnd)) { outerLoopMode = false; outerLoopCounter = 0; } } else { UiBridge.Bridge.OnError(this, string.Format("{0} cannot be used", test.Method)); goto select_cycle_or_test; } currentTestIx++; } while (currentTestIx < StateMachine.Tests.Count - simultWithEvacuationCount); } else /// if (selection == Selection.Test) { Test test = TBF.BenchControl.StateMachine.GetTest(selection); if (test == null) { UiBridge.Bridge.OnError(this, string.Format("No test specified")); goto select_cycle_or_test; } /// Fetch the test paths and transitions string errorMsg; if (!StateMachine.GetPaths(test, (StateMachine.Procedure.MetersKind == MetersKind.HeatMeter), out inPath, out benchPath, out outPath, out sensPath, out heatMetersPath, out transitionBefore, out transitionAfter, out errorMsg)) { UiBridge.Bridge.OnError(this, errorMsg); goto select_cycle_or_test; } /// Update format for the water mass Mass.Format = outPath.Balance.Format; StartMass.Format = outPath.Balance.Format; EndMass.Format = outPath.Balance.Format; ITestMethod testMethodSequence = TbfComponents.FindComponent(test.Method) as ITestMethod; if (testMethodSequence != null && testMethodSequence.CanTest(StateMachine.Procedure.MetersKind)) { StateMachine.LoadTestParams(test); ProcessData.RegisterReaders = sensPath.RegisterReaders; foreach (var rr in sensPath.RegisterReaders) { if ((rr is WaterMeters.iPerl.WaterMeter) && (BenchInfo != null)) { (rr as WaterMeters.iPerl.WaterMeter).BenchName = BenchInfo.TestBenchName; } } e = testMethodSequence.Execute(test, false, 0); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.OpArgumentError)) goto config_error; if (e.Contains(Event.UiCmdStop)) goto stop_within_cycle; } else { UiBridge.Bridge.OnError(this, string.Format("{0} cannot be used", test.Method)); goto select_cycle_or_test; } } if (BatchRslts.AllTestsDone()) { Bridge.Bench2UI(ButtonsEtc.AcceptResultsBtnEn | ButtonsEtc.ResetResultsBtnEn); } else { Bridge.Bench2UI(ButtonsEtc.ResetResultsBtnEn); } goto select_cycle_or_test; evacuation: save_results: UiBridge.Bridge.OnError(this, string.Empty); /// Clear an error message (if any) Bridge.Bench2UI(ButtonsEtc.StopBtnEn); /// Hide the most of buttons if (State.LastEvents.Contains(Event.ModelessFormIsOpen)) { if (UIFlowControl.Stop == WaitBeginFormClosed()) goto stop; } else if (State.LastEvents.Contains(Event.ModelessFormClosed)) { CloseBeginForm(); } Bridge.OnActivity(this, Strings.Enter_protocol_data); //-------------------------------- GenericDevices.IDataEntry dataEntryCmpnt = TbfComponents.FindComponent(StateMachine.Procedure.DataEntry) as GenericDevices.IDataEntry; if (dataEntryCmpnt != null) { if (dataEntryCmpnt is IHasCycleEndForm) { /// Open the modeless form for the end of the cycle State.Create("MainSeq : Enter end data") .AddOperation((dataEntryCmpnt as GenericDevices.IHasCycleEndForm).ShowCycleEndFormOp()) .AddOperation(checkUiOp) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.UiCmdStop)) goto stop; } while (!e.Contains(Event.ModelessFormClosed)); } dataEntryCmpnt.UpdateTestResults(BatchRslts); } ProcessData.BatchRslts.Batch.EndTime = DateTime.Now; ProcessData.BatchRslts.AddWaterMetersToBatch(); //------------------------------------------------------ Bridge.OnActivity(this, Strings.Saving_and_printing_results); State savingAndPrintingRslts = State.Create("MainSeq : Saving and printing results"); string[] writers = StateMachine.Procedure.ResultsWriter.Split(new char[] { '~' }); foreach (var writerName in writers) { IResultsWriter writer = TbfComponents.FindComponent(writerName) as IResultsWriter; if (writer != null) { try { savingAndPrintingRslts.AddOperation(writer.WriteResultsOp(ProcessData.BatchRslts.Batch)); } catch (Exception exc) { Bridge.OnError(this, string.Format(Strings.Component_0_crashed_Results_not_saved, writerName)); log.FatalFormat("FileWriter {0} crashed: {1}", writerName, exc.Message); } } } string[] printers = StateMachine.Procedure.ResultsPrinter.Split(new char[] { '~' }); foreach (var printerName in printers) { IResultsPrinter printer = TbfComponents.FindComponent(printerName) as IResultsPrinter; if (printer != null && !printer.SupressPrinting) { try { savingAndPrintingRslts.AddOperation(printer.PrintResultsOp(ProcessData.BatchRslts.Batch)); } catch (Exception exc) { Bridge.OnError(this, string.Format(Strings.Component_0_crashed_Results_not_printed, printerName)); log.FatalFormat("Printer {0} crashed: {1}", printerName, exc.Message); } } } savingAndPrintingRslts.AddOperation(checkUiOp).EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) goto stop; } while (e.Contains(Event.Busy)); bool resultsSent = !e.Contains(Event.ResultsNotWritten); ProcessData.BatchRslts.Batch.RsltsSent = resultsSent; /// /// Save results to the built in 'Results' database /// Results.DB.SaveNewBatch(ProcessData.BatchRslts.Batch); /// /// Save results to 'summary results' logger /// foreach (var tr in ProcessData.BatchRslts.Batch.TestRslts) { summaryResults.Info(TestResult2CsvLine(tr)); } Program.LocalSettings.BatchNr++; Program.LocalSettings.Save(); log.FatalFormat("BatchNr = {0} (incremented)", Program.LocalSettings.BatchNr); if (simultWithEvacuationCount > 0) { /// Open iPerlCommunicationForm ProcessData.RegisterReaders = StateMachine.GetMetersPath(simultWithEvacuationTests[0]).RegisterReaders; Program.MainWnd.Invoke(new iPerlCommFormDlgt(OpenIPerlCommForm), new object[] { this, simultWithEvacuationCfg, simultWithEvacuationTests, simultWithEvacuationParams }); } //-------------------------------------------------------- switch (Transition(purgeEnd, TransitionContext.PurgeEnd)) { case Event.Error: if (simultWithEvacuationCount > 0) CloseIPerlCommForm(); goto error; case Event.UiCmdStop: if (simultWithEvacuationCount > 0) CloseIPerlCommForm(); goto stop; default: break; } if (simultWithEvacuationCount > 0) { /// /// Wait until iPerl communications are completed /// bool completed = !(modelessDlg is GenericDevices.IHasCompleted) || (modelessDlg as GenericDevices.IHasCompleted).Completed; if (!completed) { State.Create("MainSeq : Wait until the entry form is closed") .AddOperation(checkUiOp) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.UiCmdStop)) { CloseIPerlCommForm(); goto stop; } completed = (modelessDlg as GenericDevices.IHasCompleted).Completed; } while (!completed); } modelessDlg = null; } benchFilled = false; Bridge.Bench2UI(ButtonsEtc.ShowBenchEmpty); goto select_procedure; stop_within_cycle: //-------------------------------- State.Create("MainSeq : Turning IDLE -> Closing the valves") .AddOperation(checkUiOp) .AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; } while (!e.Contains(Event.ValvesSet)); goto select_cycle_or_test; stop: //-------------------------------- State.Create("MainSeq : Turning IDLE -> Closing the valves") .AddOperation(checkUiOp) .AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; } while (!e.Contains(Event.ValvesSet)); goto select_procedure; config_error: //-------------------------------- State.Create("MainSeq : Procedure configuration error") .AddOperation(checkUiOp) .AddOperation(new Operations.MessageBoxOp("Test configration error")) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.OK)); goto select_cycle_or_test; error: //-------------------------------- State.Create("MainSeq : ERROR -> Closing the valves") .AddOperation(checkUiOp) .AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet) && !e.Contains(Event.Error)); //-------------------------------- State.Create("MainSeq : ERROR state") .EnterState(); while (true) StateMachine.WaitRunDevsRunOps(); } /// /// MakeSelection() call context /// enum MKSelContext { ProcedureNotSelected, InsideProcedure, } /// /// Selection done in MakeSelection() /// public enum Selection { /// Handled inside MakeSelection() None, EmptyTank1, EmptyTank2, EmptyTank3, CloseTank1, CloseTank2, CloseTank3, CameraTest, /// Used as return values Cycle, RestOfCycle, Test, Q1, Q2, Q3, Stop, PurgeBegin, PurgeEnd, Break, SaveResults, } /// /// Idle loop to make a procedure or test selection. /// Handles tank emptying, camera test. /// /// Context where MakeSelection() is called /// /// Selection.Cycle /// Selection.Test /// Selection.Q1 /// Selection.Q2 /// Selection.Q3 /// Selection.Stop /// Selection.PurgeBegin /// Selection.PurgeEnd /// private Selection MakeSelection(MKSelContext context) { /// Tank emptying valves states bool emptying1 = false; bool emptying2 = false; bool emptying3 = false; /// Measured masses to control emptying DoubleBox mass1 = new DoubleBox(); DoubleBox mass2 = new DoubleBox(); DoubleBox mass3 = new DoubleBox(); IList e; Selection selection; while (true) { /// Display an appropriate activity message if (emptying1 || emptying2 || emptying3) { Bridge.OnActivity(this, Strings.Emptying_tank); } else if (context == MKSelContext.ProcedureNotSelected) { Bridge.OnActivity(this, Strings.Please_select_a_procedure); } else if (context == MKSelContext.InsideProcedure) { Bridge.OnActivity(this, Strings.Please_select_a_cycle_a_test_or_empty); } /// Enable appropriate UI controls and buttons Bridge.Bench2UI(((context == MKSelContext.ProcedureNotSelected) ? ButtonsEtc.ProcedureCmbBoxEn : 0) | ButtonsEtc.TestCmbBoxEn | ButtonsEtc.StopBtnEn | ((emptying1 || emptying2 || emptying3) ? 0 : (ButtonsEtc.StartCycleBtnEn | ButtonsEtc.StartTestBtnsEn | ButtonsEtc.PurgeBeginBtnEn | ((context == MKSelContext.InsideProcedure) ? ButtonsEtc.PurgeEndBtnEn : 0) | ButtonsEtc.SensitivityTestBtnEn | ((Cameras.Count > 0) ? ButtonsEtc.CalibrationBtnEn : 0) | ButtonsEtc.Break)) | (((StateMachine.Balance1 != null) && (StateMachine.EmptyTankValve1 != null) && !emptying1) ? ButtonsEtc.EmptyTankBtn1En : 0) | (((StateMachine.Balance2 != null) && (StateMachine.EmptyTankValve2 != null) && !emptying2) ? ButtonsEtc.EmptyTankBtn2En : 0) | (((StateMachine.Balance3 != null) && (StateMachine.EmptyTankValve3 != null) && !emptying3) ? ButtonsEtc.EmptyTankBtn3En : 0)); selection = Selection.None; State.Create("MainSeq : Select an activity") .AddOperation(checkUiOp) .AddOperation((StateMachine.Balance1 != null) ? StateMachine.Balance1.ReadMassOp(ref mass1) : null) .AddOperation((StateMachine.Balance2 != null) ? StateMachine.Balance2.ReadMassOp(ref mass2) : null) .AddOperation((StateMachine.Balance3 != null) ? StateMachine.Balance3.ReadMassOp(ref mass3) : null) .AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp()) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; else if (e.Contains(Event.UiCmdStop)) selection = Selection.Stop; else if (e.Contains(Event.UiCmdCameraTest)) selection = Selection.CameraTest; else if (e.Contains(Event.UiCmdEmptyTank1)) selection = Selection.EmptyTank1; else if (e.Contains(Event.UiCmdEmptyTank2)) selection = Selection.EmptyTank2; else if (e.Contains(Event.UiCmdEmptyTank3)) selection = Selection.EmptyTank3; else if (emptying1 && StateMachine.Balance1.IsEmpty(mass1.Val)) selection = Selection.CloseTank1; else if (emptying2 && StateMachine.Balance2.IsEmpty(mass2.Val)) selection = Selection.CloseTank2; else if (emptying3 && StateMachine.Balance3.IsEmpty(mass3.Val)) selection = Selection.CloseTank3; else if (e.Contains(Event.UiCmdPurgeBegin)) return Selection.PurgeBegin; /// Value used to branch the code later on else if (e.Contains(Event.UiCmdPurgeEnd)) return Selection.PurgeEnd; else if (e.Contains(Event.UiCmdBreak) && context == MKSelContext.InsideProcedure) return Selection.Break; else if (e.Contains(Event.UiCmdStartTest)) return Selection.Test; else if (e.Contains(Event.UiCmdStartQ1)) return Selection.Q1; else if (e.Contains(Event.UiCmdStartQ2)) return Selection.Q2; else if (e.Contains(Event.UiCmdStartQ3)) return Selection.Q3; else if (e.Contains(Event.UiCmdStartCycle)) return Selection.Cycle; else if (e.Contains(Event.UiCmdAcceptResults)) return Selection.SaveResults; } while (selection == Selection.None); if (selection == Selection.CameraTest) { CameraTest(); } else if (selection == Selection.Stop) { if (emptying1 || emptying2 || emptying3) { IList valvesClose = new List(); if (emptying1) valvesClose.Add(StateMachine.EmptyTankValve1); if (emptying2) valvesClose.Add(StateMachine.EmptyTankValve2); if (emptying3) valvesClose.Add(StateMachine.EmptyTankValve3); State.Create("MainSeq : Close emptying valve(s)") .AddOperation(StateMachine.ControlBoard.SetValvesOp(null, valvesClose)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet)); emptying1 = emptying2 = emptying3 = false; } selection = Selection.None; } else if ((selection == Selection.EmptyTank1) && !emptying1) { emptying1 = true; Bridge.OnActivity(this, Strings.Emptying_tank); Bridge.Bench2UI(((context == MKSelContext.ProcedureNotSelected) ? ButtonsEtc.ProcedureCmbBoxEn : 0) | ButtonsEtc.TestCmbBoxEn | ButtonsEtc.StopBtnEn | (emptying2 ? 0 : ButtonsEtc.EmptyTankBtn2En) | (emptying3 ? 0 : ButtonsEtc.EmptyTankBtn3En)); State.Create("MainSeq : Open tank 1") .AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.EmptyTankValve1, null)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet)); } else if ((selection == Selection.EmptyTank2) && !emptying2) { emptying2 = true; Bridge.OnActivity(this, Strings.Emptying_tank); Bridge.Bench2UI(((context == MKSelContext.ProcedureNotSelected) ? ButtonsEtc.ProcedureCmbBoxEn : 0) | ButtonsEtc.TestCmbBoxEn | ButtonsEtc.StopBtnEn | (emptying1 ? 0 : ButtonsEtc.EmptyTankBtn1En) | (emptying3 ? 0 : ButtonsEtc.EmptyTankBtn3En)); State.Create("MainSeq : Open tank 2") .AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.EmptyTankValve2, null)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet)); } else if ((selection == Selection.EmptyTank3) && !emptying3) { emptying3 = true; Bridge.OnActivity(this, Strings.Emptying_tank); Bridge.Bench2UI(((context == MKSelContext.ProcedureNotSelected) ? ButtonsEtc.ProcedureCmbBoxEn : 0) | ButtonsEtc.TestCmbBoxEn | ButtonsEtc.StopBtnEn | (emptying1 ? 0 : ButtonsEtc.EmptyTankBtn1En) | (emptying2 ? 0 : ButtonsEtc.EmptyTankBtn2En)); State.Create("MainSeq : Open tank 3") .AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.EmptyTankValve3, null)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet)); } else if (selection == Selection.CloseTank1) { State.Create("MainSeq : Close tank 1") .AddOperation(StateMachine.ControlBoard.SetValvesOp(null, StateMachine.EmptyTankValve1)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet)); emptying1 = false; } else if (selection == Selection.CloseTank2) { State.Create("MainSeq : Close tank 2") .AddOperation(StateMachine.ControlBoard.SetValvesOp(null, StateMachine.EmptyTankValve2)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet)); emptying2 = false; } else if (selection == Selection.CloseTank3) { State.Create("MainSeq : Close tank 3") .AddOperation(StateMachine.ControlBoard.SetValvesOp(null, StateMachine.EmptyTankValve3)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet)); emptying3 = false; } } error: Bridge.OnActivity(this, Strings.Error); State.Create("MainSeq : ERROR state") .EnterState(); while (true) StateMachine.WaitRunDevsRunOps(); } /// /// Perform a camera test /// void CameraTest() { IList e; camera_test: Bridge.OnActivity(this, "Camera test"); //--------------------------------------------------------- Bridge.Bench2UI(ButtonsEtc.StartTestBtnsEn | ButtonsEtc.StopBtnEn); State.Create("MainSeq : 1 = Grab, 2 = Live, 3 = Focus, Stop = Quit camera test") .AddOperation(checkUiOp) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) return; if (e.Contains(Event.UiCmdStartQ1)) goto grab; if (e.Contains(Event.UiCmdStartQ2)) goto live; if (e.Contains(Event.UiCmdStartQ3)) goto focus; } while (true); grab: Bridge.Bench2UI(ButtonsEtc.StopBtnEn); State.Create("MainSeq : Press 'Stop' to continue") .AddOperation(checkUiOp) .AddOperation((Cameras.Count > 0 && Cameras[0] != null && (Cameras[0].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[0].GrabOp() : null) .AddOperation((Cameras.Count > 1 && Cameras[1] != null && (Cameras[1].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[1].GrabOp() : null) .AddOperation((Cameras.Count > 2 && Cameras[2] != null && (Cameras[2].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[2].GrabOp() : null) .AddOperation((Cameras.Count > 3 && Cameras[3] != null && (Cameras[3].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[3].GrabOp() : null) .AddOperation((Cameras.Count > 4 && Cameras[4] != null && (Cameras[4].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[4].GrabOp() : null) .AddOperation((Cameras.Count > 5 && Cameras[5] != null && (Cameras[5].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[5].GrabOp() : null) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) goto camera_test; } while (true); live: Bridge.Bench2UI(ButtonsEtc.StopBtnEn); State.Create("MainSeq : Press 'Stop' to stop.") .AddOperation(checkUiOp) .AddOperation((Cameras.Count > 0 && Cameras[0] != null && (Cameras[0].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[0].LiveOp() : null) .AddOperation((Cameras.Count > 1 && Cameras[1] != null && (Cameras[1].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[1].LiveOp() : null) .AddOperation((Cameras.Count > 2 && Cameras[2] != null && (Cameras[2].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[2].LiveOp() : null) .AddOperation((Cameras.Count > 3 && Cameras[3] != null && (Cameras[3].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[3].LiveOp() : null) .AddOperation((Cameras.Count > 4 && Cameras[4] != null && (Cameras[4].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[4].LiveOp() : null) .AddOperation((Cameras.Count > 5 && Cameras[5] != null && (Cameras[5].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[5].LiveOp() : null) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) goto camera_test; } while (true); focus: Bridge.Bench2UI(ButtonsEtc.StopBtnEn); State.Create("MainSeq : Press 'Stop' to stop.") .AddOperation(checkUiOp) .AddOperation((Cameras.Count > 0 && Cameras[0] != null && (Cameras[0].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[0].FocusOp() : null) .AddOperation((Cameras.Count > 1 && Cameras[1] != null && (Cameras[1].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[1].FocusOp() : null) .AddOperation((Cameras.Count > 2 && Cameras[2] != null && (Cameras[2].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[2].FocusOp() : null) .AddOperation((Cameras.Count > 3 && Cameras[3] != null && (Cameras[3].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[3].FocusOp() : null) .AddOperation((Cameras.Count > 4 && Cameras[4] != null && (Cameras[4].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[4].FocusOp() : null) .AddOperation((Cameras.Count > 5 && Cameras[5] != null && (Cameras[5].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[5].FocusOp() : null) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) goto camera_test; } while (true); error: Bridge.OnActivity(this, Strings.Error); State.Create("MainSeq : ERROR state") .EnterState(); while (true) StateMachine.WaitRunDevsRunOps(); } void CollectSimultSteps() { /// /// Collect steps (e.g. iPerl communication) to be done simultaneously with purging /// simultWithPurgingCount = 0; simultWithPurgingCfg = null; simultWithPurgingTests.Clear(); simultWithPurgingParams.Clear(); /// foreach (var test in StateMachine.Tests) { Generic.IComponent testMethodComp = TbfComponents.FindComponent(test.Method); if (testMethodComp == null) break; testMethodComp.Cfg.UpdateTestParams(test); ISimultTestMethod simultTest = testMethodComp as ISimultTestMethod; MetersPath sensPath = StateMachine.GetMetersPath(test); if (simultTest == null || !simultTest.SimultWithPrevious || sensPath == null) break; if (simultWithPurgingCount == 0) { simultWithPurgingCfg = simultTest.Cfg; } else if (simultTest.Cfg != simultWithPurgingCfg) { break; } simultWithPurgingTests.Add(test); simultWithPurgingParams.Add(testMethodComp.Cfg.GetTestParams().Clone() as Generic.ITestParams); simultWithPurgingCount++; } /// /// Collect steps (e.g. iPerl communication) to be done simultaneously with evacuation /// simultWithEvacuationCount = 0; simultWithEvacuationCfg = null; simultWithEvacuationTests.Clear(); simultWithEvacuationParams.Clear(); /// for (int i = StateMachine.Tests.Count - 1; i >= simultWithPurgingCount; i--) { var test = StateMachine.Tests[i]; Generic.IComponent testMethodComp = TbfComponents.FindComponent(test.Method); if (testMethodComp == null) break; testMethodComp.Cfg.UpdateTestParams(test); ISimultTestMethod simultTest = testMethodComp as ISimultTestMethod; MetersPath sensPath = StateMachine.GetMetersPath(test); if (simultTest == null || !simultTest.SimultWithNext || sensPath == null) break; if (simultWithEvacuationCount == 0) { simultWithEvacuationCfg = simultTest.Cfg; } else if (simultTest.Cfg != simultWithEvacuationCfg) { break; } simultWithEvacuationTests.Insert(0, test); simultWithEvacuationParams.Insert(0, testMethodComp.Cfg.GetTestParams().Clone() as Generic.ITestParams); simultWithEvacuationCount++; } } } }