//-----------------------------------------------------------------------
//
// Copyright (c) 2009 Deltares. All rights reserved.
//
// Rob Brinkman
// rob.brinkman@deltares.nl
// 16-2-2011
// n.a.
//-----------------------------------------------------------------------
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using Deltares.Geographic;
using Deltares.Standard.Attributes;
using Deltares.Standard.EventPublisher;
using Deltares.Standard.Validation;
namespace Deltares.Dam.Data
{
using System;
using System.Xml.Serialization;
using Deltares.Standard;
public interface ILocationJob
{
Location Location { get; }
IEnumerable RWScenarioResults { get; }
bool HasRWScenarioResults { get; }
}
public class LocationJob : DamJob, ILocationJob, IGeographicPoint, IVisibleEnabled
{
private TimeSerie waterLevelTimeSerie = new TimeSerie();
private LocationResult locationResult = new LocationResult();
private static ScenarioType currentScenarioType = ScenarioType.Scenario01;
private static string currentProfileName = "";
private static string currentScenarioName = "";
private static string currentCalculation = "";
private static DateTime currentTime = DateTime.Today;
private static DamProjectType damProjectType = DamProjectType.Calamity;
private static ProbabilisticType probabilisticType = ProbabilisticType.Deterministic;
private double designRequiredFactor = 0.0;
public LocationJob()
{
}
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; } }
[XmlIgnore]
[Validate]
public Location Location
{
get
{
return this.Subject as Location;
}
set
{
this.Subject = value;
}
}
public TimeSerie WaterLevelTimeSerie
{
get { return waterLevelTimeSerie; }
set
{
DataEventPublisher.BeforeChange(this, "WaterLevelTimeSerie");
waterLevelTimeSerie = value;
DataEventPublisher.AfterChange(this, "WaterLevelTimeSerie");
}
}
[XmlOldName("ScenarioResults")]
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
{
DataEventPublisher.BeforeChange(this, "LocationResult");
locationResult = value;
DataEventPublisher.AfterChange(this, "LocationResult");
}
}
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()));
}
}
public LocationResult GetLocationResultWithStabilityTimeSerie(string locationName)
{
LocationResult result = null;
if (locationResult != null && locationResult.StabilityTimeSerie != null &&
locationResult.StabilityTimeSerie.LocationId == locationName &&
locationResult.StabilityTimeSerie.Entries != null && locationResult.StabilityTimeSerie.Entries.Count > 1)
{
result = locationResult;
}
return result;
}
public LocationResult GetFirstLocationResultWithStabilityTimeSerie()
{
LocationResult result = null;
if (locationResult != null && locationResult.StabilityTimeSerie != null &&
locationResult.StabilityTimeSerie.Entries != null && locationResult.StabilityTimeSerie.Entries.Count > 1)
{
result = locationResult;
}
return result;
}
public RWScenarioProfileResult GetAssesmentResultByProfile(ScenarioType scenarioType, string profileName)
{
if (this.HasRWScenarioResults)
{
RWScenarioResult scenarioResult = this.LocationResult.RWScenariosResult.GetScenarioResult(scenarioType);
if (scenarioResult != null)
{
foreach (var res in scenarioResult.RWScenarioProfileResults)
{
if (res.SoilProfileName == profileName)
return res;
}
}
}
return null;
}
public CsvExportData GetFirstDesignResult()
{
if (this.HasScenarioResults)
{
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 (this.HasScenarioResults)
{
foreach (var scenario in Location.Scenarios)
{
foreach (var calculationResult in scenario.CalculationResults)
{
if (calculationResult.ProfileName == profileName &&
calculationResult.ScenarioName == scenarioName &&
calculationResult.Calculation == calculationName)
return calculationResult;
}
}
}
return null;
}
///
/// Return the result of the profile with highest probability of occurrence
///
///
///
public RWScenarioProfileResult GetRWScenarioResultOfProfileWithHighestProbablilityOfOccurrence(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].SoilProfileProbability > rwScenarioProfileResult.SoilProfileProbability)
{
rwScenarioProfileResult = scenarioResult.RWScenarioProfileResults[i];
}
}
return rwScenarioProfileResult;
}
}
return null;
}
///
/// 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 (ProbabilisticType == ProbabilisticType.Deterministic)
{
if ((calculationResult.SafetyFactor != null) || (calculationResult.CalculationResult == CalculationResult.UnexpectedError) )
{
return true;
}
}
else
{
if (calculationResult.FailureProbability != null)
{
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)
{
designRequiredFactor = calculationResult.RequiredSafetyFactor.Value;
}
}
}
}
}
if (res == double.MaxValue) res = DamGlobalConstants.NoRunValue;
return res;
}
///
/// Get highest porbability of failure of all scenarios
///
///
private double GetHighestRealPropbabilityFromScenarios()
{
var res = double.MinValue;
List scenarios = Location.Scenarios;
foreach (var scenario in scenarios)
{
foreach (var calculationResult in scenario.CalculationResults)
{
if (calculationResult.Calculation.Equals("FlowSlide"))
{
designRequiredFactor = 1.0; // This is a hack to make FlowSlide color display correct;
// TODO: make a good generic method to display colored results
}
else
{
if (calculationResult.PipingFailureProbability != null)
{
if (calculationResult.PipingFailureProbability.Value > res &&
calculationResult.PipingFailureProbability.Value < DamGlobalConstants.NoRunValue)
{
res = calculationResult.PipingFailureProbability.Value;
if (calculationResult.RequiredFailureProbability != null)
{
designRequiredFactor = calculationResult.RequiredFailureProbability.Value;
}
}
}
}
}
}
if (res == double.MinValue) res = DamGlobalConstants.NoRunValue;
return res;
}
[Data]
[Label("Safety factor")]
[XmlIgnore]
[Format("F3")]
public double SafetyFactor
{
get
{
if (DamProjectType == DamProjectType.Calamity)
{
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;
}
}
}
[Data]
[Label("Detriment factor")]
[Format("F3")]
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;
}
}
}
[Data]
[Label("Failure probability")]
[XmlIgnore]
[Format("F3")]
public double FailureProbability
{
get
{
if (DamProjectType == DamProjectType.Calamity)
{
return DamGlobalConstants.NoRunValue;
}
else if (DamProjectType == DamProjectType.Assessment)
{
return DamGlobalConstants.NoRunValue;
}
else if (DamProjectType == DamProjectType.Design)
{
return GetHighestRealPropbabilityFromScenarios();
}
else
{
return DamGlobalConstants.NoRunValue;
}
}
}
[Data]
[Label("Required probability")]
[Format("F3")]
[XmlIgnore]
public double RequiredProbability
{
get
{
if (DamProjectType == DamProjectType.Design)
{
return designRequiredFactor; // only for piping at the moment
}
else
{
return 1; //#Bka: for now return 1 if not piping probabilistic.
}
}
}
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;
}
[Data]
[XmlIgnore]
[Label("Result")]
public JobResult Result
{
get
{
if (ProbabilisticType == ProbabilisticType.Deterministic)
{
if (DamProjectType == DamProjectType.Assessment && AreRWScenarioResultsMixed(currentScenarioType))
{
return JobResult.Mixed;
}
return JobResultInterpreter.GetJobResult(SafetyFactor, DetrimentFactor, true);
}
else
{
return JobResultInterpreter.GetJobResult(FailureProbability, RequiredProbability, false);
}
}
}
[XmlIgnore]
[Browsable(false)]
public double X
{
get { return this.Location.XRd; }
set { this.Location.XRd = value; }
}
[XmlIgnore]
[Browsable(false)]
public double Y
{
get { return this.Location.YRd; }
set { this.Location.YRd = value; }
}
[XmlIgnore]
[Browsable(false)]
public static ScenarioType CurrentScenarioType
{
get { return currentScenarioType; }
set { currentScenarioType = value; }
}
[XmlIgnore]
[Browsable(false)]
public static string CurrentProfileName
{
get { return currentProfileName; }
set { currentProfileName = value; }
}
[XmlIgnore]
[Browsable(false)]
public static string CurrentScenarioName
{
get { return currentScenarioName; }
set { currentScenarioName = value; }
}
[XmlIgnore]
[Browsable(false)]
public static string CurrentCalculation
{
get { return currentCalculation; }
set { currentCalculation = value; }
}
[XmlIgnore]
[Browsable(false)]
public static DateTime CurrentTime
{
get { return currentTime; }
set { currentTime = value; }
}
[XmlIgnore]
[Browsable(false)]
public static DamProjectType DamProjectType
{
get { return damProjectType; }
set { damProjectType = value; }
}
[XmlIgnore]
[Browsable(false)]
public static ProbabilisticType ProbabilisticType
{
get { return probabilisticType; }
set { probabilisticType = value; }
}
public bool IsEnabled(string property)
{
return true;
}
public bool IsVisible(string property)
{
switch (property)
{
case "SafetyFactor": return this.Result != JobResult.NoRun && this.Result != JobResult.Failed &&
ProbabilisticType == ProbabilisticType.Deterministic;
case "DetrimentFactor": return this.Result != JobResult.NoRun && this.Result != JobResult.Failed &&
ProbabilisticType == ProbabilisticType.Deterministic;
case "RequiredProbability": return this.Result != JobResult.NoRun && this.Result != JobResult.Failed &&
ProbabilisticType != ProbabilisticType.Deterministic;
case "FailureProbability": return this.Result != JobResult.NoRun && this.Result != JobResult.Failed &&
ProbabilisticType != ProbabilisticType.Deterministic;
case "WaterLevelTimeSerie":
return HasLocationResults;
case "RWScenarioResults":
return HasRWScenarioResults;
default: return true;
}
}
public override string ToString()
{
return this.Location != null ? this.Location.ToString() : "";
}
}
}