Index: Riskeer/Piping/src/Riskeer.Piping.Forms/Views/PipingFailureMechanismSectionResultRow.cs =================================================================== diff -u -r8cb614f894ad501a91af52dbfa69a71e64d8eb42 -r45e1239316c5f1a40be9d7fee58e906f92f9dc25 --- Riskeer/Piping/src/Riskeer.Piping.Forms/Views/PipingFailureMechanismSectionResultRow.cs (.../PipingFailureMechanismSectionResultRow.cs) (revision 8cb614f894ad501a91af52dbfa69a71e64d8eb42) +++ Riskeer/Piping/src/Riskeer.Piping.Forms/Views/PipingFailureMechanismSectionResultRow.cs (.../PipingFailureMechanismSectionResultRow.cs) (revision 45e1239316c5f1a40be9d7fee58e906f92f9dc25) @@ -21,7 +21,10 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using Riskeer.Common.Data.AssessmentSection; +using Riskeer.Common.Data.FailureMechanism; +using Riskeer.Common.Forms.TypeConverters; using Riskeer.Common.Forms.Views; using Riskeer.Piping.Data; @@ -71,9 +74,118 @@ this.assessmentSection = assessmentSection; } - - public override void Update() + /// + /// Gets or sets whether the section is relevant. + /// + public bool IsRelevant { + get => SectionResult.IsRelevant; + set + { + SectionResult.IsRelevant = value; + UpdateInternalData(); + } } + + /// + /// Gets or sets the initial failure mechanism result. + /// + public InitialFailureMechanismResultType InitialFailureMechanismResult + { + get => SectionResult.InitialFailureMechanismResult; + set + { + SectionResult.InitialFailureMechanismResult = value; + UpdateInternalData(); + } + } + + /// + /// Gets or sets the value of the manual initial failure mechanism result per profile as a probability. + /// + /// Thrown when is not in range [0,1]. + [TypeConverter(typeof(NoProbabilityValueDoubleConverter))] + public double ManualInitialFailureMechanismResultProfileProbability + { + get => SectionResult.ManualInitialFailureMechanismResultProfileProbability; + set + { + SectionResult.ManualInitialFailureMechanismResultProfileProbability = value; + UpdateInternalData(); + } + } + + /// + /// Gets or sets the value of the manual initial failure mechanism result per failure mechanism section as a probability. + /// + /// Thrown when is not in range [0,1]. + [TypeConverter(typeof(NoProbabilityValueDoubleConverter))] + public double ManualInitialFailureMechanismResultSectionProbability + { + get => SectionResult.ManualInitialFailureMechanismResultSectionProbability; + set + { + SectionResult.ManualInitialFailureMechanismResultSectionProbability = value; + UpdateInternalData(); + } + } + + /// + /// Gets or sets whether further analysis is needed. + /// + public bool FurtherAnalysisNeeded + { + get => SectionResult.FurtherAnalysisNeeded; + set + { + SectionResult.FurtherAnalysisNeeded = value; + UpdateInternalData(); + } + } + + /// + /// Gets or sets the probability refinement type. + /// + public ProbabilityRefinementType ProbabilityRefinementType + { + get => SectionResult.ProbabilityRefinementType; + set + { + SectionResult.ProbabilityRefinementType = value; + UpdateInternalData(); + } + } + + /// + /// Gets or sets the value of the refined probability per profile. + /// + /// Thrown when is not in range [0,1]. + [TypeConverter(typeof(NoProbabilityValueDoubleConverter))] + public double RefinedProfileProbability + { + get => SectionResult.RefinedProfileProbability; + set + { + SectionResult.RefinedProfileProbability = value; + UpdateInternalData(); + } + } + + /// + /// Gets or sets the value of the refined probability per failure mechanism section. + /// + /// Thrown when is not in range [0,1].\ + [TypeConverter(typeof(NoProbabilityValueDoubleConverter))] + public double RefinedSectionProbability + { + get => SectionResult.RefinedSectionProbability; + set + { + SectionResult.RefinedSectionProbability = value; + UpdateInternalData(); + } + } + + public override void Update() {} } } \ No newline at end of file Index: Riskeer/Piping/test/Riskeer.Piping.Forms.Test/Views/PipingFailureMechanismSectionResultRowTest.cs =================================================================== diff -u -r8cb614f894ad501a91af52dbfa69a71e64d8eb42 -r45e1239316c5f1a40be9d7fee58e906f92f9dc25 --- Riskeer/Piping/test/Riskeer.Piping.Forms.Test/Views/PipingFailureMechanismSectionResultRowTest.cs (.../PipingFailureMechanismSectionResultRowTest.cs) (revision 8cb614f894ad501a91af52dbfa69a71e64d8eb42) +++ Riskeer/Piping/test/Riskeer.Piping.Forms.Test/Views/PipingFailureMechanismSectionResultRowTest.cs (.../PipingFailureMechanismSectionResultRowTest.cs) (revision 45e1239316c5f1a40be9d7fee58e906f92f9dc25) @@ -20,14 +20,20 @@ // All rights reserved. using System; +using System.Collections.Generic; using System.Linq; +using Core.Common.Base; +using Core.Common.TestUtil; using NUnit.Framework; using Rhino.Mocks; using Riskeer.Common.Data.AssessmentSection; using Riskeer.Common.Data.FailureMechanism; using Riskeer.Common.Data.TestUtil; +using Riskeer.Common.Forms.TypeConverters; +using Riskeer.Common.Forms.Views; using Riskeer.Piping.Data; using Riskeer.Piping.Data.SemiProbabilistic; +using Riskeer.Piping.Data.TestUtil.SemiProbabilistic; using Riskeer.Piping.Forms.Views; namespace Riskeer.Piping.Forms.Test.Views @@ -94,5 +100,235 @@ var exception = Assert.Throws(Call); Assert.AreEqual("assessmentSection", exception.ParamName); } + + [Test] + public void Constructor_ExpectedValues() + { + // Setup + var failureMechanism = new PipingFailureMechanism(); + + var mocks = new MockRepository(); + IAssessmentSection assessmentSection = AssessmentSectionTestHelper.CreateAssessmentSectionStub(failureMechanism, mocks); + mocks.ReplayAll(); + + FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); + var result = new PipingFailureMechanismSectionResult(section); + + SemiProbabilisticPipingCalculationScenario[] calculationScenarios = + { + SemiProbabilisticPipingCalculationTestFactory.CreateCalculation(section) + }; + + // Call + var row = new PipingFailureMechanismSectionResultRow(result, calculationScenarios, failureMechanism, assessmentSection); + + // Assert + Assert.IsInstanceOf>(row); + Assert.AreEqual(result.IsRelevant, row.IsRelevant); + Assert.AreEqual(result.InitialFailureMechanismResult, row.InitialFailureMechanismResult); + Assert.AreEqual(result.ManualInitialFailureMechanismResultProfileProbability, row.ManualInitialFailureMechanismResultProfileProbability); + Assert.AreEqual(result.ManualInitialFailureMechanismResultSectionProbability, row.ManualInitialFailureMechanismResultSectionProbability); + Assert.AreEqual(result.FurtherAnalysisNeeded, row.FurtherAnalysisNeeded); + Assert.AreEqual(result.ProbabilityRefinementType, row.ProbabilityRefinementType); + Assert.AreEqual(result.RefinedProfileProbability, row.RefinedProfileProbability); + Assert.AreEqual(result.RefinedSectionProbability, row.RefinedSectionProbability); + + TestHelper.AssertTypeConverter( + nameof(PipingFailureMechanismSectionResultRow.ManualInitialFailureMechanismResultProfileProbability)); + TestHelper.AssertTypeConverter( + nameof(PipingFailureMechanismSectionResultRow.ManualInitialFailureMechanismResultSectionProbability)); + TestHelper.AssertTypeConverter( + nameof(PipingFailureMechanismSectionResultRow.RefinedProfileProbability)); + TestHelper.AssertTypeConverter( + nameof(PipingFailureMechanismSectionResultRow.RefinedSectionProbability)); + mocks.VerifyAll(); + } + + [Test] + public void IsRelevant_SetNewValue_NotifyObserversAndPropertyChanged() + { + const bool newValue = false; + Property_SetNewValue_NotifyObserversAndPropertyChanged( + row => row.IsRelevant = newValue, + result => result.IsRelevant, + newValue); + } + + [Test] + public void InitialFailureMechanismResult_SetNewValue_NotifyObserversAndPropertyChanged() + { + const InitialFailureMechanismResultType newValue = InitialFailureMechanismResultType.NoFailureProbability; + Property_SetNewValue_NotifyObserversAndPropertyChanged( + row => row.InitialFailureMechanismResult = newValue, + result => result.InitialFailureMechanismResult, + newValue); + } + + [Test] + [TestCaseSource(nameof(GetValidProbabilities))] + public void ManualInitialFailureMechanismResultProfileProbability_SetNewValue_NotifyObserversAndPropertyChanged(double newValue) + { + Property_SetNewValue_NotifyObserversAndPropertyChanged( + row => row.ManualInitialFailureMechanismResultProfileProbability = newValue, + result => result.ManualInitialFailureMechanismResultProfileProbability, + newValue); + } + + [Test] + [SetCulture("nl-NL")] + [TestCaseSource(nameof(GetInvalidProbabilities))] + public void ManualInitialFailureMechanismResultProfileProbability_InvalidValue_ThrowsArgumentOutOfRangeException(double value) + { + ProbabilityProperty_SetInvalidValue_ThrowsArgumentOutOfRangeException(row => row.ManualInitialFailureMechanismResultProfileProbability = value); + } + + [Test] + [TestCaseSource(nameof(GetValidProbabilities))] + public void ManualInitialFailureMechanismResultSectionProbability_SetNewValue_NotifyObserversAndPropertyChanged(double newValue) + { + Property_SetNewValue_NotifyObserversAndPropertyChanged( + row => row.ManualInitialFailureMechanismResultSectionProbability = newValue, + result => result.ManualInitialFailureMechanismResultSectionProbability, + newValue); + } + + [Test] + [SetCulture("nl-NL")] + [TestCaseSource(nameof(GetInvalidProbabilities))] + public void ManualInitialFailureMechanismResultSectionProbability_InvalidValue_ThrowsArgumentOutOfRangeException(double value) + { + ProbabilityProperty_SetInvalidValue_ThrowsArgumentOutOfRangeException(row => row.ManualInitialFailureMechanismResultSectionProbability = value); + } + + [Test] + public void FurtherAnalysisNeeded_SetNewValue_NotifyObserversAndPropertyChanged() + { + const bool newValue = true; + Property_SetNewValue_NotifyObserversAndPropertyChanged( + row => row.FurtherAnalysisNeeded = newValue, + result => result.FurtherAnalysisNeeded, + newValue); + } + + [Test] + public void ProbabilityRefinementType_SetNewValue_NotifyObserversAndPropertyChanged() + { + const ProbabilityRefinementType newValue = ProbabilityRefinementType.Both; + Property_SetNewValue_NotifyObserversAndPropertyChanged( + row => row.ProbabilityRefinementType = newValue, + result => result.ProbabilityRefinementType, + newValue); + } + + [Test] + [TestCaseSource(nameof(GetValidProbabilities))] + public void RefinedProfileProbability_SetNewValue_NotifyObserversAndPropertyChanged(double newValue) + { + Property_SetNewValue_NotifyObserversAndPropertyChanged( + row => row.RefinedProfileProbability = newValue, + result => result.RefinedProfileProbability, + newValue); + } + + [Test] + [SetCulture("nl-NL")] + [TestCaseSource(nameof(GetInvalidProbabilities))] + public void RefinedProfileProbability_InvalidValue_ThrowsArgumentOutOfRangeException(double value) + { + ProbabilityProperty_SetInvalidValue_ThrowsArgumentOutOfRangeException(row => row.RefinedProfileProbability = value); + } + + [Test] + [TestCaseSource(nameof(GetValidProbabilities))] + public void RefinedSectionProbability_SetNewValue_NotifyObserversAndPropertyChanged(double newValue) + { + Property_SetNewValue_NotifyObserversAndPropertyChanged( + row => row.RefinedSectionProbability = newValue, + result => result.RefinedSectionProbability, + newValue); + } + + [Test] + [SetCulture("nl-NL")] + [TestCaseSource(nameof(GetInvalidProbabilities))] + public void RefinedSectionProbability_InvalidValue_ThrowsArgumentOutOfRangeException(double value) + { + ProbabilityProperty_SetInvalidValue_ThrowsArgumentOutOfRangeException(row => row.ManualInitialFailureMechanismResultSectionProbability = value); + } + + private static void Property_SetNewValue_NotifyObserversAndPropertyChanged( + Action setPropertyAction, + Func assertPropertyFunc, + T newValue) + { + // Setup + var failureMechanism = new PipingFailureMechanism(); + + var mocks = new MockRepository(); + IAssessmentSection assessmentSection = AssessmentSectionTestHelper.CreateAssessmentSectionStub(failureMechanism, mocks); + var observer = mocks.StrictMock(); + observer.Expect(o => o.UpdateObserver()); + mocks.ReplayAll(); + + FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); + var result = new PipingFailureMechanismSectionResult(section); + result.Attach(observer); + + SemiProbabilisticPipingCalculationScenario[] calculationScenarios = + { + SemiProbabilisticPipingCalculationTestFactory.CreateCalculation(section) + }; + + var row = new PipingFailureMechanismSectionResultRow(result, calculationScenarios, failureMechanism, assessmentSection); + + // Call + setPropertyAction(row); + + // Assert + Assert.AreEqual(newValue, assertPropertyFunc(result)); + mocks.VerifyAll(); + } + + private static void ProbabilityProperty_SetInvalidValue_ThrowsArgumentOutOfRangeException( + Action setPropertyAction) + { + // Setup + var failureMechanism = new PipingFailureMechanism(); + + var mocks = new MockRepository(); + IAssessmentSection assessmentSection = AssessmentSectionTestHelper.CreateAssessmentSectionStub(failureMechanism, mocks); + mocks.ReplayAll(); + + FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection(); + var result = new PipingFailureMechanismSectionResult(section); + + var row = new PipingFailureMechanismSectionResultRow(result, Enumerable.Empty>(), + failureMechanism, assessmentSection); + + // Call + void Call() => setPropertyAction(row); + + // Assert + const string expectedMessage = "De waarde voor de faalkans moet in het bereik [0,0, 1,0] liggen."; + TestHelper.AssertThrowsArgumentExceptionAndTestMessage(Call, expectedMessage); + mocks.VerifyAll(); + } + + private static IEnumerable GetValidProbabilities() + { + yield return new TestCaseData(0); + yield return new TestCaseData(1); + yield return new TestCaseData(0.5); + yield return new TestCaseData(1e-6); + yield return new TestCaseData(double.NaN); + } + + private static IEnumerable GetInvalidProbabilities() + { + yield return new TestCaseData(-20); + yield return new TestCaseData(-1e-6); + yield return new TestCaseData(1 + 1e-6); + yield return new TestCaseData(12); + } } } \ No newline at end of file