// Copyright (C) Stichting Deltares 2018. All rights reserved. // // This file is part of the Dam Engine. // // The Dam Engine is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . // // All names, logos, and references to "Deltares" are registered trademarks of // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. using System; using System.Collections.Generic; using System.Linq; using Deltares.DamEngine.Data.Design; using Deltares.DamEngine.Data.General.Results; using Deltares.DamEngine.Data.General.TimeSeries; using Deltares.DamEngine.Data.RWScenarios; using Deltares.DamEngine.Data.Standard.Calculation; using Deltares.DamEngine.Data.Standard.Validation; namespace Deltares.DamEngine.Data.General { public interface ILocationJob { Location Location { get; } IEnumerable RWScenarioResults { get; } bool HasRWScenarioResults { get; } } public class LocationJob : DamJob, ILocationJob { private TimeSerie waterLevelTimeSerie = new TimeSerie(); private LocationResult locationResult = new LocationResult(); private static ScenarioType currentScenarioType = ScenarioType.Scenario01; private static DateTime currentTime = DateTime.Today; private static DamProjectType damProjectType = DamProjectType.Operational; private double designRequiredFactor = 0.0; public LocationJob(object subject) : base(subject) { } /// /// TODO: what todo when location is null? /// public double XRd { get { return this.Location == null ? 0 : this.Location.XRd; } } public double YRd { get { return this.Location == null ? 0 : this.Location.YRd; } } [Validate] public Location Location { get { return this.Subject as Location; } set { this.Subject = value; } } public TimeSerie WaterLevelTimeSerie { get { return waterLevelTimeSerie; } set { waterLevelTimeSerie = value; } } public virtual IEnumerable RWScenarioResults { get { return !this.HasRWScenarioResults ? new List() : this.locationResult.RWScenariosResult.RWScenarioResults; } } public virtual IEnumerable SchematizationFactorResults { get { return !this.HasSchematizationFactorResults ? new List() : this.locationResult.SchematizationFactorsResult.SchematizationFactorResults; } } public bool HasRWScenarioResults { get { return this.locationResult != null && this.locationResult.RWScenariosResult != null && this.locationResult.RWScenariosResult.RWScenarioResults.Any(); } } public bool HasSchematizationFactorResults { get { return this.locationResult != null && this.locationResult.SchematizationFactorsResult != null; } } public virtual LocationResult LocationResult { get { return locationResult; } set { locationResult = value; } } private bool HasUsableStabilityTimeSerieEntries() { var res = false; foreach (var timeSerieEntry in locationResult.StabilityTimeSerie.Entries) { if (timeSerieEntry.Value != Double.NaN) { res = true; break; } } return res; } public bool HasLocationResults { get { if (locationResult == null) return false; return ((locationResult.PipingTimeSerie != null && locationResult.PipingTimeSerie.Entries.Count > 0) || (locationResult.StabilityTimeSerie != null && locationResult.StabilityTimeSerie.Entries.Count > 0 && HasUsableStabilityTimeSerieEntries())); } } /// /// Return the result of the profile with highest probability of occurrence /// /// /// /// /// Return result with the lowest safetyfactor /// /// /// public RWScenarioProfileResult GetRWScenarioResultWithLowestSafetyFactor(ScenarioType scenarioType) { if (this.HasRWScenarioResults) { RWScenarioResult scenarioResult = this.LocationResult.RWScenariosResult.GetScenarioResult(scenarioType); if (scenarioResult != null && scenarioResult.RWScenarioProfileResults.Count > 0) { RWScenarioProfileResult rwScenarioProfileResult = scenarioResult.RWScenarioProfileResults[0]; for (int i = 1; i < scenarioResult.RWScenarioProfileResults.Count; i++) { if (scenarioResult.RWScenarioProfileResults[i].SafetyFactor < rwScenarioProfileResult.SafetyFactor) { rwScenarioProfileResult = scenarioResult.RWScenarioProfileResults[i]; } } return rwScenarioProfileResult; } } return null; } public bool HasScenarioResults { get { List scenarios = Location.Scenarios; foreach (var scenario in scenarios) { foreach (var calculationResult in scenario.CalculationResults) { if ((calculationResult.SafetyFactor != null) || (calculationResult.CalculationResult == CalculationResult.UnexpectedError) ) { return true; } } } return false; } } /// /// Get lowest safetyfactor of all scenarios /// /// private double GetLowestRealSafetyFactorFromScenarios() { var res = double.MaxValue; List scenarios = Location.Scenarios; foreach (var scenario in scenarios) { foreach (var calculationResult in scenario.CalculationResults) { if (calculationResult.CalculationResult == CalculationResult.UnexpectedError) { res = -1; } if (calculationResult.SafetyFactor != null) { if (calculationResult.SafetyFactor.Value < res) { res = calculationResult.SafetyFactor.Value; // if (calculationResult.RequiredSafetyFactor != null) #Bka should come from input, not results // { // designRequiredFactor = calculationResult.RequiredSafetyFactor.Value; // } } } } } if (res == double.MaxValue) res = DamGlobalConstants.NoRunValue; return res; } public double SafetyFactor { get { if (DamProjectType == DamProjectType.Operational) { if (this.HasLocationResults) { TimeSerie timeSerie = this.LocationResult.StabilityTimeSerie; return timeSerie.GetValue(CurrentTime); } else { return DamGlobalConstants.NoRunValue; } } else if (DamProjectType == DamProjectType.Assessment) { if (this.HasRWScenarioResults && GetRWScenarioResultWithLowestSafetyFactor(currentScenarioType) != null) { return GetRWScenarioResultWithLowestSafetyFactor(currentScenarioType).SafetyFactor; } else { if (this.locationResult.RWScenariosResult != null && this.locationResult.RWScenariosResult.CalculationResult == CalculationResult.RunFailed) { // DamGlobalConstants.NoRunValue is the default result resulting in NoRun whereas the // status must be failed. So when failed set to -1. return -1; } else { return DamGlobalConstants.NoRunValue; } } } else if (DamProjectType == DamProjectType.Design) { return GetLowestRealSafetyFactorFromScenarios(); } else { return DamGlobalConstants.NoRunValue; } } } public double DetrimentFactor { get { if (DamProjectType == DamProjectType.Design) { return designRequiredFactor; } else { // For Piping in Assesment projects, ignore the given detriment factor and use the required safety for Piping if (DamProjectType == DamProjectType.Assessment && (currentScenarioType == ScenarioType.Scenario10 || currentScenarioType == ScenarioType.Scenario11)) { return DamGlobalConstants.RequiredSafetyPipingForAssessment; } return this.Location.DetrimentFactor; } } } public bool AreRWScenarioResultsMixed(ScenarioType scenarioType) { if (this.HasRWScenarioResults) { RWScenarioResult scenarioResult = this.LocationResult.RWScenariosResult.GetScenarioResult(scenarioType); if (scenarioResult != null && scenarioResult.RWScenarioProfileResults.Count > 0) { var aboveRequiredSafety = false; var belowRequiredSafety = false; for (int i = 0; i < scenarioResult.RWScenarioProfileResults.Count; i++) { if (!aboveRequiredSafety) { aboveRequiredSafety = scenarioResult.RWScenarioProfileResults[i].SafetyFactor >= DetrimentFactor; } if (!belowRequiredSafety) { belowRequiredSafety = scenarioResult.RWScenarioProfileResults[i].SafetyFactor < DetrimentFactor; } } return aboveRequiredSafety && belowRequiredSafety; } } return false; } public JobResult Result { get { if (DamProjectType == DamProjectType.Assessment && AreRWScenarioResultsMixed(currentScenarioType)) { return JobResult.Mixed; } return JobResultInterpreter.GetJobResult(SafetyFactor, DetrimentFactor, true); } } public static DateTime CurrentTime { get { return currentTime; } set { currentTime = value; } } public static DamProjectType DamProjectType { get { return damProjectType; } set { damProjectType = value; } } public override string ToString() { return this.Location != null ? this.Location.ToString() : ""; } } }