// 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;
}
}