diff --git a/StructureHelperLogics/NdmCalculations/Cracking/CheckCrackCalculatorInputDataLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/CheckCrackCalculatorInputDataLogic.cs index 60a20f3..8bb3572 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/CheckCrackCalculatorInputDataLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/CheckCrackCalculatorInputDataLogic.cs @@ -89,7 +89,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { result = false; string message = $"Host {rebar.Name} ({rebar.HostPrimitive.Name}) is not included in primitives\n"; - checkResult += message; + CheckResult += message; TraceLogger?.AddMessage(message, TraceLogStatuses.Error); } } @@ -97,7 +97,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { result = false; string message = $"Material of host of {rebar.Name} ({rebar.HostPrimitive.HeadMaterial.Name}) does not support cracking\n"; - checkResult += message; + CheckResult += message; TraceLogger?.AddMessage(message, TraceLogStatuses.Error); } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/IRebarCalulatorsFactory.cs b/StructureHelperLogics/NdmCalculations/Cracking/IRebarCalulatorsFactory.cs new file mode 100644 index 0000000..737e14c --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/IRebarCalulatorsFactory.cs @@ -0,0 +1,15 @@ +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperLogics.NdmCalculations.Primitives; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + public interface IRebarCalulatorsFactory : ILogic + { + TupleCrackInputData InputData { get; set; } + double LongLength { get; set; } + IEnumerable Rebars { get; set; } + double ShortLength { get; set; } + + List GetCalculators(); + } +} \ No newline at end of file diff --git a/StructureHelperLogics/NdmCalculations/Cracking/IRebarCrackCalculator.cs b/StructureHelperLogics/NdmCalculations/Cracking/IRebarCrackCalculator.cs new file mode 100644 index 0000000..70412f2 --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/IRebarCrackCalculator.cs @@ -0,0 +1,12 @@ +using StructureHelperCommon.Models; +using StructureHelperCommon.Models.Calculators; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + public interface IRebarCrackCalculator : ICalculator + { + Action ActionToOutputResults { get; set; } + RebarCrackCalculatorInputData InputData { get; set; } + IShiftTraceLogger? TraceLogger { get; set; } + } +} \ No newline at end of file diff --git a/StructureHelperLogics/NdmCalculations/Cracking/IRebarCrackInputDataFactory.cs b/StructureHelperLogics/NdmCalculations/Cracking/IRebarCrackInputDataFactory.cs new file mode 100644 index 0000000..5e9de6a --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/IRebarCrackInputDataFactory.cs @@ -0,0 +1,14 @@ +using StructureHelperLogics.NdmCalculations.Primitives; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + public interface IRebarCrackInputDataFactory + { + RebarPrimitive Rebar { get; set; } + TupleCrackInputData InputData { get; set; } + double LongLength { get; set; } + double ShortLength { get; set; } + + RebarCrackCalculatorInputData GetInputData(); + } +} \ No newline at end of file diff --git a/StructureHelperLogics/NdmCalculations/Cracking/ITupleRebarsCrackSolver.cs b/StructureHelperLogics/NdmCalculations/Cracking/ITupleRebarsCrackSolver.cs new file mode 100644 index 0000000..6399d60 --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/ITupleRebarsCrackSolver.cs @@ -0,0 +1,18 @@ +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperLogics.NdmCalculations.Primitives; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + public interface ITupleRebarsCrackSolver : ILogic + { + string Description { get; } + TupleCrackInputData InputData { get; set; } + bool IsResultValid { get; } + double LongLength { get; set; } + IEnumerable Rebars { get; set; } + List Result { get; } + double ShortLength { get; set; } + + void Run(); + } +} \ No newline at end of file diff --git a/StructureHelperLogics/NdmCalculations/Cracking/RebarCalulatorsFactory.cs b/StructureHelperLogics/NdmCalculations/Cracking/RebarCalulatorsFactory.cs new file mode 100644 index 0000000..c91438b --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/RebarCalulatorsFactory.cs @@ -0,0 +1,47 @@ +using StructureHelperCommon.Models; +using StructureHelperLogics.NdmCalculations.Primitives; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + public class RebarCalulatorsFactory : IRebarCalulatorsFactory + { + private IRebarCrackInputDataFactory inputFactory; + + public IEnumerable Rebars { get; set; } + public TupleCrackInputData InputData { get; set; } + public double LongLength { get; set; } + public double ShortLength { get; set; } + public IShiftTraceLogger? TraceLogger { get; set; } + + public RebarCalulatorsFactory(IRebarCrackInputDataFactory inputFactory) + { + this.inputFactory = inputFactory; + } + + public RebarCalulatorsFactory() : this(new RebarCrackInputDataFactory()) { } + + public List GetCalculators() + { + List calculators = new List(); + foreach (var rebar in Rebars) + { + inputFactory.Rebar = rebar; + inputFactory.InputData = InputData; + inputFactory.LongLength = LongLength; + inputFactory.ShortLength = ShortLength; + var calculator = new RebarCrackCalculator + { + InputData = inputFactory.GetInputData() + }; + calculators.Add(calculator); + } + return calculators; + } + + } +} diff --git a/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackCalculator.cs b/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackCalculator.cs index 2bc5ee5..c2f40f2 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackCalculator.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackCalculator.cs @@ -8,7 +8,7 @@ using StructureHelperLogics.NdmCalculations.Primitives; namespace StructureHelperLogics.NdmCalculations.Cracking { - public class RebarCrackCalculator : ICalculator + public class RebarCrackCalculator : IRebarCrackCalculator { private ICrackSofteningLogic crackSofteningLogic; private ICrackWidthLogic crackWidthLogic = new CrackWidthLogicSP63(); @@ -120,7 +120,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking private ICrackWidthLogicInputData GetCrackWidthInputData(RebarCrackInputData inputData, CalcTerms calcTerm) { - + var factoryInputData = new CrackWidthLogicInputDataFactory(crackSofteningLogic) { CalcTerm = calcTerm, diff --git a/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackInputDataFactory.cs b/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackInputDataFactory.cs new file mode 100644 index 0000000..8118c60 --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackInputDataFactory.cs @@ -0,0 +1,76 @@ +using LoaderCalculator.Data.Ndms; +using StructureHelper.Models.Materials; +using StructureHelperCommon.Models.Calculators; +using StructureHelperCommon.Models.Forces; +using StructureHelperLogics.NdmCalculations.Primitives; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static System.Windows.Forms.VisualStyles.VisualStyleElement; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + public class RebarCrackInputDataFactory : IRebarCrackInputDataFactory + { + private ICrackedSectionTriangulationLogic triangulationLogicLoc; + + public RebarCrackInputDataFactory(ICrackedSectionTriangulationLogic triangulationLogicLoc) + { + this.triangulationLogicLoc = triangulationLogicLoc; + } + + public RebarCrackInputDataFactory(TupleCrackInputData inputData) : this (new CrackedSectionTriangulationLogic(inputData.Primitives)) + { + + } + + public RebarCrackInputDataFactory() + { + + } + + public RebarPrimitive Rebar { get; set; } + public TupleCrackInputData InputData { get; set; } + public double LongLength { get; set; } + public double ShortLength { get; set; } + + public RebarCrackCalculatorInputData GetInputData() + { + IEnumerable crackableNdmsLoc = null; + IEnumerable crackedNdmsLoc = null; + INdm concreteNdmUnderRebar; + RebarPrimitive rebarCopy = null; + + rebarCopy = Rebar.Clone() as RebarPrimitive; + rebarCopy.HeadMaterial = rebarCopy.HeadMaterial.Clone() as IHeadMaterial; + triangulationLogicLoc = new CrackedSectionTriangulationLogic(InputData.Primitives); + crackableNdmsLoc = triangulationLogicLoc.GetNdmCollection(); + crackedNdmsLoc = triangulationLogicLoc.GetCrackedNdmCollection(); + + var longRebarData = new RebarCrackInputData() + { + CrackableNdmCollection = crackableNdmsLoc, + CrackedNdmCollection = crackedNdmsLoc, + ForceTuple = InputData.LongTermTuple.Clone() as ForceTuple, + Length = LongLength + }; + var shortRebarData = new RebarCrackInputData() + { + CrackableNdmCollection = crackableNdmsLoc, + CrackedNdmCollection = crackedNdmsLoc, + ForceTuple = InputData.ShortTermTuple.Clone() as ForceTuple, + Length = ShortLength + }; + var rebarCalculatorData = new RebarCrackCalculatorInputData() + { + RebarPrimitive = rebarCopy, + LongRebarData = longRebarData, + ShortRebarData = shortRebarData, + UserCrackInputData = InputData.UserCrackInputData + }; + return rebarCalculatorData; + } + } +} diff --git a/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackCalculator.cs b/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackCalculator.cs index afa4607..ad01557 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackCalculator.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackCalculator.cs @@ -33,7 +33,6 @@ namespace StructureHelperLogics.NdmCalculations.Cracking private StrainTuple shortDefaultStrainTuple; private double longLength; private double shortLength; - private object locker = new(); public string Name { get; set; } public TupleCrackInputData InputData { get; set; } @@ -43,8 +42,8 @@ namespace StructureHelperLogics.NdmCalculations.Cracking public void Run() { - PrepareNewResult(); TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); + PrepareNewResult(); try { @@ -79,13 +78,20 @@ namespace StructureHelperLogics.NdmCalculations.Cracking longDefaultStrainTuple = CalcStrainMatrix(InputData.LongTermTuple as ForceTuple, crackableNdms); shortDefaultStrainTuple = CalcStrainMatrix(InputData.LongTermTuple as ForceTuple, crackableNdms); + GetLengthBeetwenCracks(); + SolveRebarResult(); + GetMinMaxCrackWidth(); + } + + private void GetLengthBeetwenCracks() + { var longElasticStrainTuple = CalcStrainMatrix(InputData.LongTermTuple as ForceTuple, elasticNdms); var shortElasticStrainTuple = CalcStrainMatrix(InputData.ShortTermTuple as ForceTuple, elasticNdms); if (result.IsValid == false) { return; } if (InputData.UserCrackInputData.SetLengthBetweenCracks == true) { longLength = InputData.UserCrackInputData.LengthBetweenCracks; - shortLength = InputData.UserCrackInputData.LengthBetweenCracks; + shortLength = InputData.UserCrackInputData.LengthBetweenCracks; TraceLogger?.AddMessage($"User value of length between cracks Lcrc = {longLength}"); } else @@ -93,30 +99,11 @@ namespace StructureHelperLogics.NdmCalculations.Cracking longLength = GetLengthBetweenCracks(longElasticStrainTuple); shortLength = GetLengthBetweenCracks(shortElasticStrainTuple); } - //CalcCrackForce(); - //for (int j = 0; j < 100000; j++) - //{ - result.RebarResults.Clear(); - int rebarCount = rebarPrimitives.Count; - Task[] tasks = new Task[rebarCount]; - for (int i = 0; i < rebarCount; i++) - { - var rebar = rebarPrimitives[i]; - tasks[i] = new Task(() => ProcessRebar(rebar)); - tasks[i].Start(); - } - Task.WaitAll(tasks); - for (int i = 0; i < rebarCount; i++) - { - result.RebarResults.Add(tasks[i].Result); - } - //} - - if (result.RebarResults.Any(x => x.IsValid == false)) - { - result.IsValid = false; - return; - } + } + + private void GetMinMaxCrackWidth() + { + if (result.IsValid == false || result.RebarResults.Count == 0) { return; } result.LongTermResult = new() { CrackWidth = result.RebarResults.Max(x => x.LongTermResult.CrackWidth), @@ -129,61 +116,23 @@ namespace StructureHelperLogics.NdmCalculations.Cracking }; } - private RebarCrackResult ProcessRebar(RebarPrimitive rebar) + private void SolveRebarResult() { - RebarCrackCalculatorInputData rebarCalculatorData = GetRebarCalculatorInputData(rebar); - var calculator = new RebarCrackCalculator + result.RebarResults.Clear(); + ITupleRebarsCrackSolver solver = new TupleRebarsCrackSolver(); + solver.Rebars = rebarPrimitives; + solver.InputData = InputData; + solver.LongLength = longLength; + solver.ShortLength = shortLength; + solver.TraceLogger = TraceLogger?.GetSimilarTraceLogger(0); + solver.Run(); + if (solver.IsResultValid == false) { - InputData = rebarCalculatorData, - TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) - }; - calculator.Run(); - var rebarResult = calculator.Result as RebarCrackResult; - return rebarResult; - } - - private RebarCrackCalculatorInputData GetRebarCalculatorInputData(RebarPrimitive rebar) - { - IEnumerable crackableNdmsLoc = null; - IEnumerable crackedNdmsLoc = null; - INdm concreteNdmUnderRebar; - RebarPrimitive rebarCopy = null; - lock (locker) - { - rebarCopy = rebar.Clone() as RebarPrimitive; - rebarCopy.HeadMaterial = rebarCopy.HeadMaterial.Clone() as IHeadMaterial; - var triangulationLogicLoc = new CrackedSectionTriangulationLogic(InputData.Primitives); - crackableNdmsLoc = triangulationLogicLoc.GetNdmCollection(); - crackedNdmsLoc = triangulationLogicLoc.GetCrackedNdmCollection(); - //concreteNdmUnderRebar = rebarCopy.GetConcreteNdm(new TriangulationOptions() - //{ CalcTerm = crackingTerm, - // LimiteState = crackingLimitState }); - //concreteNdmUnderRebar.StressScale = 1d; - //crackableNdmsLoc = new List() { concreteNdmUnderRebar}; + result.IsValid = false; + result.Description += solver.Description; + return; } - - var longRebarData = new RebarCrackInputData() - { - CrackableNdmCollection = crackableNdmsLoc, - CrackedNdmCollection = crackedNdmsLoc, - ForceTuple = InputData.LongTermTuple.Clone() as ForceTuple, - Length = longLength - }; - var shortRebarData = new RebarCrackInputData() - { - CrackableNdmCollection = crackableNdmsLoc, - CrackedNdmCollection = crackedNdms, - ForceTuple = InputData.ShortTermTuple.Clone() as ForceTuple, - Length = shortLength - }; - var rebarCalculatorData = new RebarCrackCalculatorInputData() - { - RebarPrimitive = rebarCopy, - LongRebarData = longRebarData, - ShortRebarData = shortRebarData, - UserCrackInputData = InputData.UserCrackInputData - }; - return rebarCalculatorData; + result.RebarResults.AddRange(solver.Result); } private StrainTuple CalcStrainMatrix(ForceTuple forceTuple, IEnumerable ndms) @@ -234,15 +183,6 @@ namespace StructureHelperLogics.NdmCalculations.Cracking elasticNdms = triangulationLogic.GetElasticNdmCollection(); } - private void CalcCrackForce() - { - var calculator = new CrackForceCalculator(); - calculator.EndTuple = InputData.LongTermTuple; - calculator.NdmCollection = crackableNdms; - calculator.Run(); - crackForceResult = calculator.Result as CrackForceResult; - } - private void CheckInputData() { if (InputData.Primitives is null || InputData.Primitives.Count == 0) diff --git a/StructureHelperLogics/NdmCalculations/Cracking/TupleRebarsCrackSolver.cs b/StructureHelperLogics/NdmCalculations/Cracking/TupleRebarsCrackSolver.cs new file mode 100644 index 0000000..aaba861 --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/TupleRebarsCrackSolver.cs @@ -0,0 +1,96 @@ +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperCommon.Models; +using StructureHelperCommon.Models.Calculators; +using StructureHelperLogics.NdmCalculations.Primitives; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + public class TupleRebarsCrackSolver : ITupleRebarsCrackSolver + { + private IRebarCalulatorsFactory calculatorsFactory; + + public IEnumerable Rebars { get; set; } + public TupleCrackInputData InputData { get; set; } + public double LongLength { get; set; } + public double ShortLength { get; set; } + public IShiftTraceLogger? TraceLogger { get; set; } + + public List Result { get; private set; } + public bool IsResultValid { get; private set; } + public string Description { get; private set; } + + public TupleRebarsCrackSolver(IRebarCalulatorsFactory calulatorsFactory) + { + this.calculatorsFactory = calulatorsFactory; + } + + public TupleRebarsCrackSolver() : this(new RebarCalulatorsFactory()) { } + + public void Run() + { + Result = new List(); + Description = string.Empty; + var rebarCalculators = GetRebarCalculators(); + List> tasks = new(); + foreach (var calculator in rebarCalculators) + { + if (TraceLogger != null) + { + calculator.TraceLogger = new ShiftTraceLogger(); + } + tasks.Add(new Task(() => ProcessCalculator(calculator))); + } + + var taskArray = tasks.ToArray(); + foreach (var task in taskArray) + { + task.Start(); + } + Task.WaitAll(taskArray); + + if (TraceLogger != null) + { + for (int i = 0; i < rebarCalculators.Count(); i++) + { + TraceLogger.TraceLoggerEntries.AddRange(rebarCalculators[i].TraceLogger.TraceLoggerEntries); + } + } + + for (int i = 0; i < taskArray.Length; i++) + { + Result.Add(taskArray[i].Result); + } + + if (Result.Any(x => x.IsValid == false)) + { + IsResultValid = false; + Description += "\n There not valid results for rebar"; + return; + } + IsResultValid = true; + } + + + private RebarCrackResult ProcessCalculator(IRebarCrackCalculator calculator) + { + calculator.Run(); + var rebarResult = calculator.Result as RebarCrackResult; + return rebarResult; + } + + private List GetRebarCalculators() + { + calculatorsFactory.Rebars = Rebars; + calculatorsFactory.InputData = InputData; + calculatorsFactory.LongLength = LongLength; + calculatorsFactory.ShortLength = ShortLength; + calculatorsFactory.TraceLogger = TraceLogger?.GetSimilarTraceLogger(0); + return calculatorsFactory.GetCalculators(); + } + } +} diff --git a/StructureHelperTests/UnitTests/Ndms/Cracks/RebarCalulatorsFactoryTests.cs b/StructureHelperTests/UnitTests/Ndms/Cracks/RebarCalulatorsFactoryTests.cs new file mode 100644 index 0000000..d09169d --- /dev/null +++ b/StructureHelperTests/UnitTests/Ndms/Cracks/RebarCalulatorsFactoryTests.cs @@ -0,0 +1,85 @@ +using System.Collections.Generic; +using Moq; +using NUnit.Framework; +using StructureHelperCommon.Models; +using StructureHelperLogics.NdmCalculations.Cracking; +using StructureHelperLogics.NdmCalculations.Primitives; + +namespace StructureHelperTests.UnitTests.Ndms.Cracks +{ + public class RebarCalulatorsFactoryTests + { + [Test] + public void GetCalculators_ShouldReturnListOfCalculators() + { + // Arrange + var mockInputFactory = new Mock(); + var rebar = new RebarPrimitive(); + var inputData = new TupleCrackInputData(); + var rebarCrackInputData = new RebarCrackCalculatorInputData(); + + mockInputFactory.SetupProperty(f => f.Rebar, rebar); + mockInputFactory.SetupProperty(f => f.InputData, inputData); + mockInputFactory.SetupProperty(f => f.LongLength, 10.0); + mockInputFactory.SetupProperty(f => f.ShortLength, 5.0); + mockInputFactory.Setup(f => f.GetInputData()).Returns(rebarCrackInputData); + + var factory = new RebarCalulatorsFactory(mockInputFactory.Object) + { + Rebars = new List { rebar }, + InputData = inputData, + LongLength = 10.0, + ShortLength = 5.0, + TraceLogger = null + }; + + // Act + var calculators = factory.GetCalculators(); + + // Assert + var calculator = calculators[0]; + Assert.NotNull(calculator); + Assert.AreEqual(rebarCrackInputData, calculator.InputData); + Assert.Null(calculator.TraceLogger); + } + + [Test] + public void GetCalculators_ShouldInitializeCalculatorsWithCorrectData() + { + // Arrange + var mockInputFactory = new Mock(); + var rebar1 = new RebarPrimitive(); + var rebar2 = new RebarPrimitive(); + var inputData = new TupleCrackInputData(); + var rebarInputData1 = new RebarCrackCalculatorInputData(); + var rebarInputData2 = new RebarCrackCalculatorInputData(); + var mockLogger = new Mock(); + + mockInputFactory.SetupSequence(f => f.GetInputData()) + .Returns(rebarInputData1) + .Returns(rebarInputData2); + mockInputFactory.Setup(f => f.GetInputData()).Returns(rebarInputData1); + + mockLogger.Setup(l => l.GetSimilarTraceLogger(50)).Returns(mockLogger.Object); + + var factory = new RebarCalulatorsFactory(mockInputFactory.Object) + { + Rebars = new List { rebar1, rebar2 }, + InputData = inputData, + LongLength = 20.0, + ShortLength = 10.0, + TraceLogger = mockLogger.Object + }; + + // Act + var calculators = factory.GetCalculators(); + + // Assert + Assert.AreEqual(2, calculators.Count); + Assert.AreEqual(rebarInputData1, calculators[0].InputData); + //Assert.AreEqual(rebarInputData2, calculators[1].InputData); + Assert.AreEqual(mockLogger.Object, calculators[0].TraceLogger); + Assert.AreEqual(mockLogger.Object, calculators[1].TraceLogger); + } + } +} \ No newline at end of file diff --git a/StructureHelperTests/UnitTests/Ndms/Cracks/TupleRebarCrackSolverTest.cs b/StructureHelperTests/UnitTests/Ndms/Cracks/TupleRebarCrackSolverTest.cs new file mode 100644 index 0000000..e0c8a81 --- /dev/null +++ b/StructureHelperTests/UnitTests/Ndms/Cracks/TupleRebarCrackSolverTest.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using StructureHelperLogics.NdmCalculations.Cracking; +using StructureHelperLogics.NdmCalculations.Primitives; + +namespace StructureHelperTests.UnitTests.Ndms.Cracks +{ + public class TupleRebarsCrackSolverTest + { + [Test] + public void Run_ShouldProcessAllCalculatorsAndSetValidResults() + { + // Arrange + var mockCalculatorFactory = new Mock(); + var mockCalculator = new Mock(); + mockCalculator.Setup(c => c.Run()); + mockCalculator.Setup(c => c.Result).Returns(new RebarCrackResult { IsValid = true }); + + var calculators = new List { mockCalculator.Object }; + mockCalculatorFactory.Setup(f => f.GetCalculators()).Returns(calculators); + + var solver = new TupleRebarsCrackSolver(mockCalculatorFactory.Object) + { + Rebars = new List(), + InputData = new TupleCrackInputData(), + LongLength = 10.0, + ShortLength = 5.0, + TraceLogger = null + }; + + // Act + solver.Run(); + + // Assert + mockCalculator.Verify(c => c.Run(), Times.Once); + Assert.True(solver.IsResultValid); + Assert.NotNull(solver.Result); + Assert.True(solver.Result.All(r => r.IsValid)); + } + + [Test] + public void Run_ShouldSetInvalidResultWhenAnyCalculatorResultIsInvalid() + { + // Arrange + var mockCalculatorFactory = new Mock(); + var mockCalculator1 = new Mock(); + mockCalculator1.Setup(c => c.Run()); + mockCalculator1.Setup(c => c.Result).Returns(new RebarCrackResult { IsValid = true }); + + var mockCalculator2 = new Mock(); + mockCalculator2.Setup(c => c.Run()); + mockCalculator2.Setup(c => c.Result).Returns(new RebarCrackResult { IsValid = false }); + + var calculators = new List { mockCalculator1.Object, mockCalculator2.Object }; + mockCalculatorFactory.Setup(f => f.GetCalculators()).Returns(calculators); + + var solver = new TupleRebarsCrackSolver(mockCalculatorFactory.Object) + { + Rebars = new List(), + InputData = new TupleCrackInputData(), + LongLength = 10.0, + ShortLength = 5.0, + TraceLogger = null + }; + + // Act + solver.Run(); + + // Assert + mockCalculator1.Verify(c => c.Run(), Times.Once); + mockCalculator2.Verify(c => c.Run(), Times.Once); + Assert.False(solver.IsResultValid); + } + } +} \ No newline at end of file