using System; using Core.Common.Base; using Core.Common.Base.Data; using Core.Common.Base.Properties; using log4net; using Ringtoets.Piping.Data; using Resources = Ringtoets.Piping.Service.Properties.Resources; namespace Ringtoets.Piping.Service { public class PipingInputSynchronizer : IObserver { private static readonly ILog log = LogManager.GetLogger(typeof(PipingInputSynchronizer)); private const double seepageLengthStandardDeviationFraction = 0.1; private readonly PipingInput input; private PipingInputSynchronizer(PipingInput input) { if (input == null) { throw new ArgumentNullException("input", "Cannot create PipingInputSynchronizer without PipingInput."); } input.Attach(this); this.input = input; SynchronizeDerivedProperties(); } /// /// Starts the synchronization of the given . /// /// The input to synchronize the values for. public static void Synchronize(PipingInput input) { new PipingInputSynchronizer(input); } public void UpdateObserver() { SynchronizeDerivedProperties(); } private void SynchronizeDerivedProperties() { UpdateAssessmentLevel(); UpdateSeepageLength(); UpdateThicknessCoverageLayer(); UpdateThicknessAquiferLayer(); UpdatePiezometricHeadExit(); } private void UpdateThicknessAquiferLayer() { PipingSoilProfile soilProfile = input.SoilProfile; RingtoetsPipingSurfaceLine surfaceLine = input.SurfaceLine; double exitPointL = input.ExitPointL; if (soilProfile != null && surfaceLine != null && !double.IsNaN(exitPointL)) { double thicknessTopAquiferLayer = GetThicknessTopAquiferLayer(soilProfile, surfaceLine, exitPointL); TrySetThicknessAquiferLayerMean(input, thicknessTopAquiferLayer); if (double.IsNaN(input.ThicknessAquiferLayer.Mean)) { log.Warn(Resources.PipingInputSynchronizer_UpdateThicknessAquiferLayer_Cannot_determine_thickness_aquifer_layer); } } else { input.ThicknessAquiferLayer.Mean = (RoundedDouble) double.NaN; } } private static void TrySetThicknessAquiferLayerMean(PipingInput input, double thicknessTopAquiferLayer) { try { input.ThicknessAquiferLayer.Mean = (RoundedDouble) thicknessTopAquiferLayer; } catch (ArgumentOutOfRangeException) { input.ThicknessAquiferLayer.Mean = (RoundedDouble) double.NaN; } } private static double GetThicknessTopAquiferLayer(PipingSoilProfile soilProfile, RingtoetsPipingSurfaceLine surfaceLine, double exitPointL) { try { var zAtL = surfaceLine.GetZAtL(exitPointL); return soilProfile.GetTopAquiferLayerThicknessBelowLevel(zAtL); } catch (ArgumentOutOfRangeException) { return double.NaN; } } private void UpdateThicknessCoverageLayer() { if (input.SurfaceLine != null && input.SoilProfile != null & !double.IsNaN(input.ExitPointL)) { TrySetThicknessCoverageLayer(); if (double.IsNaN(input.ThicknessCoverageLayer.Mean)) { log.Warn(Resources.PipingInputSynchronizer_UpdateThicknessCoverageLayer_Cannot_determine_thickness_coverage_layer); } } else { input.ThicknessCoverageLayer.Mean = (RoundedDouble)double.NaN; } } private void TrySetThicknessCoverageLayer() { try { input.ThicknessCoverageLayer.Mean = (RoundedDouble)PipingCalculationService.CalculateThicknessCoverageLayer(input); } catch (ArgumentOutOfRangeException) { input.ThicknessCoverageLayer.Mean = (RoundedDouble)double.NaN; } } private void UpdatePiezometricHeadExit() { try { input.PiezometricHeadExit = (RoundedDouble) PipingCalculationService.CalculatePiezometricHeadAtExit(input); } catch (ArgumentOutOfRangeException) { input.PiezometricHeadExit = (RoundedDouble) double.NaN; } } private void UpdateAssessmentLevel() { input.AssessmentLevel = input.HydraulicBoundaryLocation == null ? (RoundedDouble) double.NaN : (RoundedDouble) input.HydraulicBoundaryLocation.DesignWaterLevel; } private void UpdateSeepageLength() { try { input.SeepageLength.Mean = input.ExitPointL - input.EntryPointL; } catch (ArgumentOutOfRangeException) { input.SeepageLength.Mean = (RoundedDouble) double.NaN; } input.SeepageLength.StandardDeviation = input.SeepageLength.Mean*seepageLengthStandardDeviationFraction; } } }