// 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() : "";
}
}
}