// Copyright (C) Stichting Deltares 2025. All rights reserved. // // This file is part of the application DAM - UI. // // DAM - UI is free software: you can redistribute it and/or modify // it under the terms of the GNU 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 General Public License for more details. // // You should have received a copy of the GNU 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.ComponentModel; using System.Xml.Serialization; using Deltares.Geographic; using Deltares.Standard; using Deltares.Standard.Attributes; using Deltares.Standard.EventPublisher; using Deltares.Standard.Validation; namespace Deltares.Dam.Data; public interface ILocationJob { Location Location { get; } } public class LocationJob : DamJob, ILocationJob, IGeographicPoint, IVisibleEnabled { private TimeSerie waterLevelTimeSerie = new TimeSerie(); private LocationResult locationResult = new LocationResult(); private double designRequiredFactor; public LocationJob() {} public LocationJob(object subject) : base(subject) {} /// /// TODO: what todo when location is null? /// public double XRd { get { return Location == null ? 0 : Location.XRd; } } public double YRd { get { return Location == null ? 0 : Location.YRd; } } public TimeSerie WaterLevelTimeSerie { get { return waterLevelTimeSerie; } set { DataEventPublisher.BeforeChange(this, "WaterLevelTimeSerie"); waterLevelTimeSerie = value; DataEventPublisher.AfterChange(this, "WaterLevelTimeSerie"); } } public virtual LocationResult LocationResult { get { return locationResult; } set { DataEventPublisher.BeforeChange(this, "LocationResult"); locationResult = value; DataEventPublisher.AfterChange(this, "LocationResult"); } } 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())); } } /// /// Gets a value indicating whether this instance has (Design) scenario results. /// /// /// true if this instance has scenario results; otherwise, false. /// public bool HasDesignScenarioResults { get { List scenarios = Location.Scenarios; foreach (Scenario scenario in scenarios) { foreach (CsvExportData calculationResult in scenario.CalculationResults) { bool isUpLiftVanNoUplift = IsUpliftVanNoUplift(calculationResult); if (isUpLiftVanNoUplift || (calculationResult.SafetyFactor != null) || (calculationResult.CalculationResult == CalculationResult.UnexpectedError)) { return true; } } } return false; } } internal static bool IsUpliftVanNoUplift(CsvExportData calculationResult) { if (calculationResult is { DamFailureMechanismeCalculation: not null }) { return calculationResult.DamFailureMechanismeCalculation.FailureMechanismSystemType == FailureMechanismSystemType.StabilityInside && calculationResult.DamFailureMechanismeCalculation.StabilityModelType == StabilityModelType.UpliftVan && calculationResult.IsUplift == false; } return false; } [Data] [Label("Safety factor")] [XmlIgnore] [Format("F3")] public double SafetyFactor { get { if (DamProjectType == DamProjectType.Design) { return GetLowestRealSafetyFactorFromDesignScenarios(); } return DamGlobalConstants.NoRunValue; } } [Data] [Format("F3")] public double RequiredFactorOfSafety { get { if (DamProjectType == DamProjectType.Design) { return designRequiredFactor; } return 1.0; } } [Data] [XmlIgnore] [Label("Result")] public JobResult Result { get { return JobResultInterpreter.GetJobResult(SafetyFactor, RequiredFactorOfSafety, true); } } [XmlIgnore] [Browsable(false)] public static string CurrentProfileName { get; set; } = ""; [XmlIgnore] [Browsable(false)] public static string CurrentScenarioName { get; set; } = ""; [XmlIgnore] [Browsable(false)] public static string CurrentCalculation { get; set; } = ""; [XmlIgnore] [Browsable(false)] public static DamProjectType DamProjectType { get; set; } = DamProjectType.Design; [XmlIgnore] [Browsable(false)] public double X { get { return XRd; } set { if (Location != null) { Location.XRd = value; } } } [XmlIgnore] [Browsable(false)] public double Y { get { return YRd; } set { if (Location != null) { Location.YRd = value; } } } [XmlIgnore] [Validate] public Location Location { get { return Subject as Location; } set { Subject = value; } } public CsvExportData GetFirstDesignResult() { if (HasDesignScenarioResults) { Scenario scenario = Location.Scenarios[0]; if (scenario != null && scenario.CalculationResults.Count > 0) { return scenario.CalculationResults[0]; } } return null; } public CsvExportData GetDesignResultByProfileScenarioAndCalculationName(string profileName, string scenarioName, string calculationName) { if (HasDesignScenarioResults) { foreach (Scenario scenario in Location.Scenarios) { foreach (CsvExportData calculationResult in scenario.CalculationResults) { if (calculationResult.ProfileName == profileName && calculationResult.ScenarioName == scenarioName && calculationResult.StabilityModel.ToString() == calculationName) { return calculationResult; } } } } return null; } public override string ToString() { return Location != null ? Location.ToString() : ""; } public bool IsEnabled(string property) { return true; } public bool IsVisible(string property) { switch (property) { case "SafetyFactor": return Result != JobResult.NoRun && Result != JobResult.Failed; case "RequiredFactorOfSafety": return Result != JobResult.NoRun && Result != JobResult.Failed; case "WaterLevelTimeSerie": return HasLocationResults; default: return true; } } private bool HasUsableStabilityTimeSerieEntries() { var res = false; foreach (TimeSerieEntry timeSerieEntry in locationResult.StabilityTimeSerie.Entries) { if (!double.IsNaN(timeSerieEntry.Value)) { res = true; break; } } return res; } /// /// Get lowest safetyfactor of all scenarios /// /// private double GetLowestRealSafetyFactorFromDesignScenarios() { var res = double.MaxValue; List scenarios = Location.Scenarios; foreach (Scenario scenario in scenarios) { foreach (CsvExportData 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) { designRequiredFactor = calculationResult.RequiredSafetyFactor.Value; } } } } } if (res == double.MaxValue) { res = DamGlobalConstants.NoRunValue; } return res; } }