Index: Ringtoets/Common/src/Ringtoets.Common.Forms/Properties/Resources.Designer.cs =================================================================== diff -u -r91c77273f4139eb1128c01c6662178796b66a993 -r249a26006e363c5bb4cf26d2f033ee87c30e4bf4 --- Ringtoets/Common/src/Ringtoets.Common.Forms/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision 91c77273f4139eb1128c01c6662178796b66a993) +++ Ringtoets/Common/src/Ringtoets.Common.Forms/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision 249a26006e363c5bb4cf26d2f033ee87c30e4bf4) @@ -2150,6 +2150,15 @@ } /// + /// Looks up a localized string similar to Alle hydraulische randvoorwaarden berekenen.. + /// + public static string HydraulicBoundaryDatabase_Calculate_All_ToolTip { + get { + return ResourceManager.GetString("HydraulicBoundaryDatabase_Calculate_All_ToolTip", resourceCulture); + } + } + + /// /// Looks up a localized string similar to Coördinaten van de hydraulische randvoorwaardenlocatie.. /// public static string HydraulicBoundaryDatabase_Location_Coordinates_Description { Index: Ringtoets/Common/src/Ringtoets.Common.Forms/Properties/Resources.resx =================================================================== diff -u -r91c77273f4139eb1128c01c6662178796b66a993 -r249a26006e363c5bb4cf26d2f033ee87c30e4bf4 --- Ringtoets/Common/src/Ringtoets.Common.Forms/Properties/Resources.resx (.../Resources.resx) (revision 91c77273f4139eb1128c01c6662178796b66a993) +++ Ringtoets/Common/src/Ringtoets.Common.Forms/Properties/Resources.resx (.../Resources.resx) (revision 249a26006e363c5bb4cf26d2f033ee87c30e4bf4) @@ -169,6 +169,9 @@ Alle golfhoogten berekenen. + + Alle hydraulische randvoorwaarden berekenen. + Wis de uitvoer van alle berekeningen binnen dit toetsspoor. Index: Ringtoets/Integration/src/Ringtoets.Integration.Plugin/RingtoetsPlugin.cs =================================================================== diff -u -r8481ca19b1727f44ea251b88146a8621088cf406 -r249a26006e363c5bb4cf26d2f033ee87c30e4bf4 --- Ringtoets/Integration/src/Ringtoets.Integration.Plugin/RingtoetsPlugin.cs (.../RingtoetsPlugin.cs) (revision 8481ca19b1727f44ea251b88146a8621088cf406) +++ Ringtoets/Integration/src/Ringtoets.Integration.Plugin/RingtoetsPlugin.cs (.../RingtoetsPlugin.cs) (revision 249a26006e363c5bb4cf26d2f033ee87c30e4bf4) @@ -1931,10 +1931,31 @@ RingtoetsFormsResources.HydraulicBoundaryDatabase_Connect_ToolTip, RingtoetsCommonFormsResources.DatabaseIcon, (sender, args) => SelectDatabaseFile(nodeData.AssessmentSection)); + var calculateAllItem = new StrictContextMenuItem( + RingtoetsCommonFormsResources.Calculate_All, + RingtoetsCommonFormsResources.HydraulicBoundaryDatabase_Calculate_All_ToolTip, + RingtoetsCommonFormsResources.CalculateAllIcon, + (sender, args) => + { + if (hydraulicBoundaryLocationCalculationGuiService == null) + { + return; + } + + ActivityProgressDialogRunner.Run( + Gui.MainWindow, + AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactory.CreateHydraulicBoundaryLocationCalculationActivities(nodeData.AssessmentSection)); + }); + + SetHydraulicsMenuItemEnabledStateAndTooltip(nodeData.AssessmentSection, + calculateAllItem); + return Gui.Get(nodeData, treeViewControl) .AddCustomItem(connectionItem) .AddExportItem() .AddSeparator() + .AddCustomItem(calculateAllItem) + .AddSeparator() .AddCollapseAllItem() .AddExpandAllItem() .AddSeparator() @@ -2087,7 +2108,7 @@ } ActivityProgressDialogRunner.Run( - Gui.MainWindow, + Gui.MainWindow, AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactory.CreateDesignWaterLevelCalculationActivities(assessmentSection)); }); @@ -2117,7 +2138,7 @@ } ActivityProgressDialogRunner.Run( - Gui.MainWindow, + Gui.MainWindow, AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactory.CreateWaveHeightCalculationActivities(assessmentSection)); }); Index: Ringtoets/Integration/src/Ringtoets.Integration.Service/AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactory.cs =================================================================== diff -u -r5cb386767f4e8fcfee8737bcd44126664d203144 -r249a26006e363c5bb4cf26d2f033ee87c30e4bf4 --- Ringtoets/Integration/src/Ringtoets.Integration.Service/AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactory.cs (.../AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactory.cs) (revision 5cb386767f4e8fcfee8737bcd44126664d203144) +++ Ringtoets/Integration/src/Ringtoets.Integration.Service/AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactory.cs (.../AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactory.cs) (revision 249a26006e363c5bb4cf26d2f033ee87c30e4bf4) @@ -34,6 +34,26 @@ public static class AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactory { /// + /// Creates a collection of for all hydraulic boundary location calculations + /// in the given . + /// + /// The assessment section to create the activities for. + /// A collection of . + /// Thrown when is null. + public static IEnumerable CreateHydraulicBoundaryLocationCalculationActivities(IAssessmentSection assessmentSection) + { + if (assessmentSection == null) + { + throw new ArgumentNullException(nameof(assessmentSection)); + } + + var activities = new List(); + activities.AddRange(CreateDesignWaterLevelCalculationActivities(assessmentSection)); + activities.AddRange(CreateWaveHeightCalculationActivities(assessmentSection)); + return activities; + } + + /// /// Creates a collection of for wave height calculations /// based on the given . /// Index: Ringtoets/Integration/test/Ringtoets.Integration.Plugin.Test/TreeNodeInfos/HydraulicBoundaryDatabaseContextTreeNodeInfoTest.cs =================================================================== diff -u -r53f9e83ff9ccf6ec7f9fcf5e9d01d0bcb97a5af8 -r249a26006e363c5bb4cf26d2f033ee87c30e4bf4 --- Ringtoets/Integration/test/Ringtoets.Integration.Plugin.Test/TreeNodeInfos/HydraulicBoundaryDatabaseContextTreeNodeInfoTest.cs (.../HydraulicBoundaryDatabaseContextTreeNodeInfoTest.cs) (revision 53f9e83ff9ccf6ec7f9fcf5e9d01d0bcb97a5af8) +++ Ringtoets/Integration/test/Ringtoets.Integration.Plugin.Test/TreeNodeInfos/HydraulicBoundaryDatabaseContextTreeNodeInfoTest.cs (.../HydraulicBoundaryDatabaseContextTreeNodeInfoTest.cs) (revision 249a26006e363c5bb4cf26d2f033ee87c30e4bf4) @@ -32,16 +32,22 @@ using Core.Common.Gui.Commands; using Core.Common.Gui.ContextMenu; using Core.Common.Gui.Forms.MainWindow; +using Core.Common.Gui.Forms.ViewHost; using Core.Common.Gui.TestUtil.ContextMenu; using Core.Common.TestUtil; using NUnit.Extensions.Forms; using NUnit.Framework; using Rhino.Mocks; using Ringtoets.Common.Data.AssessmentSection; using Ringtoets.Common.Data.Hydraulics; +using Ringtoets.Common.Data.TestUtil; using Ringtoets.Common.Forms.PresentationObjects; using Ringtoets.Common.IO.FileImporters; +using Ringtoets.Common.Service.TestUtil; using Ringtoets.GrassCoverErosionOutwards.Data; +using Ringtoets.HydraRing.Calculation.Calculator; +using Ringtoets.HydraRing.Calculation.Calculator.Factory; +using Ringtoets.HydraRing.Calculation.TestUtil.Calculator; using Ringtoets.Integration.Data; using Ringtoets.Integration.Forms.PresentationObjects; using Ringtoets.Piping.Data; @@ -54,6 +60,7 @@ public class HydraulicBoundaryDatabaseContextTreeNodeInfoTest : NUnitFormTest { private const int contextMenuImportHydraulicBoundaryDatabaseIndex = 0; + private const int contextMenuRunHydraulicBoundaryLocationCalculationsIndex = 3; private readonly string testDataPath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Integration.Forms, "HydraulicBoundaryDatabase"); private readonly string testDataPathNoHlcd = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Integration.Forms, "HydraulicBoundaryDatabaseNoHLCD"); @@ -142,6 +149,8 @@ menuBuilder.Expect(mb => mb.AddCustomItem(null)).IgnoreArguments().Return(menuBuilder); menuBuilder.Expect(mb => mb.AddExportItem()).Return(menuBuilder); menuBuilder.Expect(mb => mb.AddSeparator()).Return(menuBuilder); + menuBuilder.Expect(mb => mb.AddCustomItem(null)).IgnoreArguments().Return(menuBuilder); + menuBuilder.Expect(mb => mb.AddSeparator()).Return(menuBuilder); menuBuilder.Expect(mb => mb.AddCollapseAllItem()).Return(menuBuilder); menuBuilder.Expect(mb => mb.AddExpandAllItem()).Return(menuBuilder); menuBuilder.Expect(mb => mb.AddSeparator()).Return(menuBuilder); @@ -690,6 +699,100 @@ mocks.VerifyAll(); } + [Test] + [Apartment(ApartmentState.STA)] + public void GivenHydraulicBoundaryLocationThatSucceeds_CalculatingDesignWaterLevelFromContextMenu_ThenLogMessagesAddedOutputSet() + { + // Given + var assessmentSection = new AssessmentSection(AssessmentSectionComposition.Dike) + { + HydraulicBoundaryDatabase = + { + FilePath = Path.Combine(testDataPath, "HRD dutch coast south.sqlite") + } + }; + + var hydraulicBoundaryLocation = new TestHydraulicBoundaryLocation("locationName"); + assessmentSection.SetHydraulicBoundaryLocationCalculations(new[] + { + hydraulicBoundaryLocation + }); + + var context = new HydraulicBoundaryDatabaseContext(assessmentSection.HydraulicBoundaryDatabase, assessmentSection); + + using (var treeViewControl = new TreeViewControl()) + using (var plugin = new RingtoetsPlugin()) + { + var gui = mocks.Stub(); + gui.Stub(g => g.MainWindow).Return(mocks.Stub()); + gui.Stub(g => g.ProjectOpened += null).IgnoreArguments(); + gui.Stub(g => g.ProjectOpened -= null).IgnoreArguments(); + gui.Stub(cmp => cmp.Get(context, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + gui.Stub(g => g.DocumentViewController).Return(mocks.Stub()); + + var calculatorFactory = mocks.Stub(); + var designWaterLevelCalculator = new TestDesignWaterLevelCalculator + { + Converged = false + }; + var waveHeightCalculator = new TestWaveHeightCalculator + { + Converged = false + }; + + calculatorFactory.Expect(cf => cf.CreateDesignWaterLevelCalculator(testDataPath, string.Empty)).Return(designWaterLevelCalculator).Repeat.Times(4); + calculatorFactory.Expect(cf => cf.CreateWaveHeightCalculator(testDataPath, string.Empty)).Return(waveHeightCalculator).Repeat.Times(4); + mocks.ReplayAll(); + + TreeNodeInfo info = GetInfo(plugin); + plugin.Gui = gui; + plugin.Activate(); + + DialogBoxHandler = (name, wnd) => + { + // Expect an activity dialog which is automatically closed + }; + + using (ContextMenuStrip contextMenuAdapter = info.ContextMenuStrip(context, null, treeViewControl)) + using (new HydraRingCalculatorFactoryConfig(calculatorFactory)) + { + // When + Action call = () => contextMenuAdapter.Items[contextMenuRunHydraulicBoundaryLocationCalculationsIndex].PerformClick(); + + // Then + TestHelper.AssertLogMessages(call, messages => + { + string[] msgs = messages.ToArray(); + Assert.AreEqual(64, msgs.Length); + + const string designWaterLevelName = "Waterstand"; + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 0, designWaterLevelName, "A+->A"); + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 8, designWaterLevelName, "A->B"); + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 16, designWaterLevelName, "B->C"); + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 24, designWaterLevelName, "C->D"); + + const string waveHeightName = "Golfhoogte"; + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 32, waveHeightName, "A+->A"); + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 40, waveHeightName, "A->B"); + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 48, waveHeightName, "B->C"); + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 56, waveHeightName, "C->D"); + }); + + AssertDesignWaterLevelCalculationOutput(designWaterLevelCalculator, assessmentSection.WaterLevelCalculationsForFactorizedSignalingNorm.Single().Output); + AssertDesignWaterLevelCalculationOutput(designWaterLevelCalculator, assessmentSection.WaterLevelCalculationsForSignalingNorm.Single().Output); + AssertDesignWaterLevelCalculationOutput(designWaterLevelCalculator, assessmentSection.WaterLevelCalculationsForLowerLimitNorm.Single().Output); + AssertDesignWaterLevelCalculationOutput(designWaterLevelCalculator, assessmentSection.WaterLevelCalculationsForFactorizedLowerLimitNorm.Single().Output); + + AssertWaveHeightCalculationOutput(waveHeightCalculator, assessmentSection.WaveHeightCalculationsForFactorizedSignalingNorm.Single().Output); + AssertWaveHeightCalculationOutput(waveHeightCalculator, assessmentSection.WaveHeightCalculationsForSignalingNorm.Single().Output); + AssertWaveHeightCalculationOutput(waveHeightCalculator, assessmentSection.WaveHeightCalculationsForLowerLimitNorm.Single().Output); + AssertWaveHeightCalculationOutput(waveHeightCalculator, assessmentSection.WaveHeightCalculationsForFactorizedLowerLimitNorm.Single().Output); + } + } + + mocks.VerifyAll(); + } + public override void Setup() { mocks = new MockRepository(); @@ -719,7 +822,7 @@ var waveHeightCalculationsForSignalingNormObserver = mocks.StrictMock(); var waveHeightCalculationsForLowerLimitNormObserver = mocks.StrictMock(); var waveHeightCalculationsForFactorizedLowerLimitNormObserver = mocks.StrictMock(); - + var waterLevelCalculationsForMechanismSpecificFactorizedSignalingNormObserver = mocks.StrictMock(); var waterLevelCalculationsForMechanismSpecificSignalingNormObserver = mocks.StrictMock(); var waterLevelCalculationsForMechanismSpecificLowerLimitNormObserver = mocks.StrictMock(); @@ -789,6 +892,36 @@ } } + private static void AssertHydraulicBoundaryLocationCalculationMessages(HydraulicBoundaryLocation hydraulicBoundaryLocation, + IEnumerable messages, + int startIndex, + string type, + string categoryName) + { + Assert.AreEqual($"{type} berekenen voor locatie '{hydraulicBoundaryLocation.Name}' (Categorie {categoryName}) is gestart.", messages.ElementAt(startIndex)); + CalculationServiceTestHelper.AssertValidationStartMessage(messages.ElementAt(startIndex + 1)); + CalculationServiceTestHelper.AssertValidationEndMessage(messages.ElementAt(startIndex + 2)); + CalculationServiceTestHelper.AssertCalculationStartMessage(messages.ElementAt(startIndex + 3)); + Assert.AreEqual($"{type} berekening voor locatie '{hydraulicBoundaryLocation.Name}' (Categorie {categoryName}) is niet geconvergeerd.", messages.ElementAt(startIndex + 4)); + StringAssert.StartsWith($"{type} berekening is uitgevoerd op de tijdelijke locatie", messages.ElementAt(startIndex + 5)); + CalculationServiceTestHelper.AssertCalculationEndMessage(messages.ElementAt(startIndex + 6)); + Assert.AreEqual($"{type} berekenen voor locatie '{hydraulicBoundaryLocation.Name}' (Categorie {categoryName}) is gelukt.", messages.ElementAt(startIndex + 7)); + } + + private static void AssertDesignWaterLevelCalculationOutput(IDesignWaterLevelCalculator designWaterLevelCalculator, + HydraulicBoundaryLocationCalculationOutput actualOutput) + { + Assert.AreEqual(designWaterLevelCalculator.DesignWaterLevel, actualOutput.Result, actualOutput.Result.GetAccuracy()); + Assert.AreEqual(CalculationConvergence.CalculatedNotConverged, actualOutput.CalculationConvergence); + } + + private static void AssertWaveHeightCalculationOutput(IWaveHeightCalculator waveHeightCalculator, + HydraulicBoundaryLocationCalculationOutput actualOutput) + { + Assert.AreEqual(waveHeightCalculator.WaveHeight, actualOutput.Result, actualOutput.Result.GetAccuracy()); + Assert.AreEqual(CalculationConvergence.CalculatedNotConverged, actualOutput.CalculationConvergence); + } + private static TreeNodeInfo GetInfo(RingtoetsPlugin plugin) { return plugin.GetTreeNodeInfos().First(tni => tni.TagType == typeof(HydraulicBoundaryDatabaseContext)); Index: Ringtoets/Integration/test/Ringtoets.Integration.Service.Test/AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactoryTest.cs =================================================================== diff -u -r5cb386767f4e8fcfee8737bcd44126664d203144 -r249a26006e363c5bb4cf26d2f033ee87c30e4bf4 --- Ringtoets/Integration/test/Ringtoets.Integration.Service.Test/AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactoryTest.cs (.../AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactoryTest.cs) (revision 5cb386767f4e8fcfee8737bcd44126664d203144) +++ Ringtoets/Integration/test/Ringtoets.Integration.Service.Test/AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactoryTest.cs (.../AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactoryTest.cs) (revision 249a26006e363c5bb4cf26d2f033ee87c30e4bf4) @@ -43,6 +43,74 @@ private static readonly string testDataPath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Integration.Service, "HydraRingCalculation"); [Test] + public void CreateHydraulicBoundaryLocationCalculationActivities_AssessmentSectionNull_ThrowsArgumentNullException() + { + // Call + TestDelegate test = () => AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactory.CreateHydraulicBoundaryLocationCalculationActivities(null); + + // Assert + var exception = Assert.Throws(test); + Assert.AreEqual("assessmentSection", exception.ParamName); + } + + [Test] + public void CreateHydraulicBoundaryLocationCalculationActivities_WithValidData_ExpectedInputSetToActivities() + { + // Setup + var assessmentSection = new AssessmentSectionStub + { + HydraulicBoundaryDatabase = + { + FilePath = Path.Combine(testDataPath, "HRD ijsselmeer.sqlite") + } + }; + + var hydraulicBoundaryLocation = new TestHydraulicBoundaryLocation("locationName 1"); + assessmentSection.SetHydraulicBoundaryLocationCalculations(new[] + { + hydraulicBoundaryLocation + }); + + // Call + IEnumerable activities = + AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactory.CreateHydraulicBoundaryLocationCalculationActivities(assessmentSection); + + // Assert + Assert.AreEqual(8, activities.Count()); + + double signalingNorm = assessmentSection.FailureMechanismContribution.SignalingNorm; + double factorizedSignalingNorm = signalingNorm / 30; + double lowerLimitNorm = assessmentSection.FailureMechanismContribution.LowerLimitNorm; + double factorizedLowerLimitNorm = lowerLimitNorm * 30; + + AssertDesignWaterLevelCalculationActivity(activities.First(), + hydraulicBoundaryLocation, + factorizedSignalingNorm); + AssertDesignWaterLevelCalculationActivity(activities.ElementAt(1), + hydraulicBoundaryLocation, + signalingNorm); + AssertDesignWaterLevelCalculationActivity(activities.ElementAt(2), + hydraulicBoundaryLocation, + lowerLimitNorm); + AssertDesignWaterLevelCalculationActivity(activities.ElementAt(3), + hydraulicBoundaryLocation, + factorizedLowerLimitNorm); + + AssertWaveHeightCalculationActivity(activities.ElementAt(4), + hydraulicBoundaryLocation, + factorizedSignalingNorm); + AssertWaveHeightCalculationActivity(activities.ElementAt(5), + hydraulicBoundaryLocation, + signalingNorm); + AssertWaveHeightCalculationActivity(activities.ElementAt(6), + hydraulicBoundaryLocation, + lowerLimitNorm); + AssertWaveHeightCalculationActivity(activities.ElementAt(7), + hydraulicBoundaryLocation, + factorizedLowerLimitNorm); + } + + [Test] public void CreateDesignWaterLevelCalculationActivities_AssessmentSectionNull_ThrowsArgumentNullException() { // Call @@ -78,6 +146,8 @@ AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactory.CreateDesignWaterLevelCalculationActivities(assessmentSection); // Assert + Assert.AreEqual(8, activities.Count()); + double signalingNorm = assessmentSection.FailureMechanismContribution.SignalingNorm; double factorizedSignalingNorm = signalingNorm / 30; AssertDesignWaterLevelCalculationActivity(activities.First(), @@ -147,6 +217,8 @@ AssessmentSectionHydraulicBoundaryLocationCalculationActivityFactory.CreateWaveHeightCalculationActivities(assessmentSection); // Assert + Assert.AreEqual(8, activities.Count()); + double signalingNorm = assessmentSection.FailureMechanismContribution.SignalingNorm; double factorizedSignalingNorm = signalingNorm / 30; AssertWaveHeightCalculationActivity(activities.First(),