// Copyright (C) Stichting Deltares 2017. 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;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Deltares.DamEngine.Data.Geotechnics;
using Deltares.DamEngine.Data.Standard;
namespace Deltares.DamEngine.Data.General.Sensors
{
///
/// Association class for sensor data and a location
///
public class SensorLocation
{
#region Business Rules
///
/// Specication to test if the value of the candidate is valid
///
// internal class IgnoreOrLocationData : PredicateSpecification
// {
// public IgnoreOrLocationData()
// : base(x => x == DataSourceTypeSensors.Ignore || x == DataSourceTypeSensors.LocationData)
// {
// Description = "Only Ignore or LocationData value allowed for this property.";
// }
// }
///
/// Specication to test if the value of the candidate is valid
///
// internal class SensorOrLocationData : PredicateSpecification
// {
// public SensorOrLocationData()
// : base(x => x == DataSourceTypeSensors.Sensor || x == DataSourceTypeSensors.LocationData)
// {
// Description = "Only Sensor or LocationData value allowed for this property.";
// }
// }
#endregion
///
/// Constructor is needed for XML deserialization
///
public SensorLocation()
{
PL1WaterLevelAtRiver = DataSourceTypeSensors.LocationData;
PL1WaterLevelAtPolder = DataSourceTypeSensors.LocationData;
}
private Group sensorGroup;
///
/// Gets the PL line offset below dike top at river.
///
public double PLLineOffsetBelowDikeTopAtRiver
{
get { return Location.PlLineOffsetBelowDikeTopAtRiver; }
}
///
/// Gets the PL line offset below dike top at polder.
///
public double PLLineOffsetBelowDikeTopAtPolder
{
get { return Location.PLLineOffsetDryBelowDikeTopAtPolder; }
}
///
/// Gets the PL line offset below dike toe at polder.
///
public double PLLineOffsetBelowDikeToeAtPolder
{
get { return Location.PlLineOffsetBelowDikeToeAtPolder; }
}
///
/// Gets the PL line offset dry below shoulder base inside.
///
public double PLLineOffsetDryBelowShoulderBaseInside
{
get { return Location.PlLineOffsetBelowShoulderBaseInside; }
}
///
/// Gets or sets the DAM location.
///
///
/// The location.
///
// [Specification(typeof(NotNullSpecification))]
public Location Location { get; set; }
///
/// Gets the location Name.
///
///
/// If the Name is empty it could indicate that there is no reference
/// to a valid location
///
public string LocationName
{
get { return (Location != null) ? Location.Name : string.Empty; }
}
///
/// Gets or sets the sensor group.
///
///
/// The group.
///
// [Specification(typeof(NotNullSpecification))]
public Group Group
{
get { return sensorGroup; }
set
{
sensorGroup = value;
}
}
public void ResetGroupID(int id)
{
sensorGroup.ID = id;
}
///
/// Gets the group ID.
///
///
/// If the ID has value -1 then the there is no valid reference (null)
/// or the group is transient.
///
public int GroupID
{
get
{
if (sensorGroup == null)
return -1;
return sensorGroup.ID;
}
}
///
/// Gets the sensor selection.
///
public IEnumerable Sensors
{
get
{
if (sensorGroup == null)
return new Sensor[0];
return sensorGroup.Selection;
}
}
///
/// Gets or sets the PL3 data source type.
///
///
/// The PL3.
///
// [Specification(typeof(SensorOrLocationData))]
public DataSourceTypeSensors PL3 { get; set; }
///
/// Gets or sets the PL4 data source type.
///
///
/// The PL4.
///
// [Specification(typeof(SensorOrLocationData))]
public DataSourceTypeSensors PL4 { get; set; }
///
/// Gets or sets the outer water level data source type.
///
///
/// The outer water level.
///
// [Specification(typeof(SensorOrLocationData))]
public DataSourceTypeSensors PL1WaterLevelAtRiver { get; set; }
///
/// Gets or sets the PL1 PL line offset below dike top at river data source type.
///
///
/// Data source type for PL1 PLLine offset below dike top at river.
///
// [Specification(typeof(IgnoreOrLocationData))]
public DataSourceTypeSensors PL1PLLineOffsetBelowDikeTopAtRiver { get; set; }
///
/// Gets or sets the PL1 PL line offset below dike top at polder data source type
///
///
/// The PL1 PL line offset below dike top at polder.
///
// [Specification(typeof(IgnoreOrLocationData))]
public DataSourceTypeSensors PL1PLLineOffsetBelowDikeTopAtPolder { get; set; }
///
/// Gets or sets the PL1 PL line offset below shoulder base inside data source type
///
///
/// The PL1 PL line offset below shoulder base inside.
///
// [Specification(typeof(IgnoreOrLocationData))]
public DataSourceTypeSensors PL1PLLineOffsetBelowShoulderBaseInside { get; set; }
///
/// Gets or sets the PL1 PL line offset below dike toe at polder data source type.
///
///
/// The PL1 PL line offset below dike toe at polder.
///
//[Specification(typeof(IgnoreOrLocationData))]
public DataSourceTypeSensors PL1PLLineOffsetBelowDikeToeAtPolder { get; set; }
///
/// Gets or sets the PL1 polder level data source type.
///
///
/// The PL1 polder level.
///
//[Specification(typeof(SensorOrLocationData))]
public DataSourceTypeSensors PL1WaterLevelAtPolder { get; set; }
///
/// Gets the sensor count.
///
public int SensorCount
{
get
{
return sensorGroup == null ? 0 : Group.SensorCount;
}
}
public SurfaceLine2 SurfaceLine
{
get { return Location.SurfaceLine2; }
}
public double RiverLevel
{
get { return Location.RiverLevel; }
}
public double PolderLevel
{
get { return Location.PolderLevel; }
}
public double? HeadPl3
{
get { return Location.HeadPl3; }
}
public double? HeadPl4
{
get { return Location.HeadPl4; }
}
public string Alias { get; set; } // ToDo Tom/Kin Sun Waarvoor nodig? Wordt nergens gebruikt. Kan gewoon weg!?
public string Profile
{
get; //{ return SoilProfile2D } ;
set;
}
public string MStabFile
{
get; //{ return SoilProfile2D } ;
set;
}
///
/// Gets the PiezometricHead type sensors sorted by relative location along profile.
///
/// Type of the pl line.
///
// internal SortedDictionary GetSensorsSortedByRelativeLocationAlongProfile(PLLineType plLineType)
// {
// var calculatedRelativeLocations = BuildRelativeLocationTable();
//
// var table = new SortedDictionary();
//
// // leave out the water level and polder level sensors
// var candidateSensors =
// Sensors.GetBySpecification(new PiezometricHeadSensorSpecification());
//
// foreach (var sensor in candidateSensors)
// {
// if (sensor.PLLineMappings.Contains(plLineType))
// {
// double relativeLocation = sensor.RelativeLocationSpecified ?
// sensor.RelativeLocation : calculatedRelativeLocations[sensor];
//
// if (table.ContainsKey(relativeLocation))
// {
// throw new InvalidOperationException(
// "Error creating lookup table with sensors sorted by relative location along profile. The x-location " + relativeLocation + " already exists. Sensor " + sensor);
// }
//
// table.Add(relativeLocation, sensor);
// }
// }
// return table;
// } ##Bka
///
/// Builds the relative location table.
///
///
internal IDictionary BuildRelativeLocationTable()
{
var surfaceLevelOutside = SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelOutside);
if (surfaceLevelOutside == null)
throw new InvalidOperationException("No SurfaceLevelOutside point on surface line defined");
double startPoint = surfaceLevelOutside.X;
var dict = new Dictionary();
foreach (Sensor sensor in Sensors)
{
double relativeLocation = startPoint + (Location.XRdDikeLine - sensor.XRd);
dict.Add(sensor, relativeLocation);
}
return dict;
}
internal static class MemberNames
{
internal static readonly string OffsetBelowDikeToeAtPolder = StaticReflection.GetMemberName(x => x.PL1PLLineOffsetBelowDikeToeAtPolder);
internal static readonly string OffsetBelowDikeTopAtPolder = StaticReflection.GetMemberName(x => x.PL1PLLineOffsetBelowDikeTopAtPolder);
internal static readonly string OffsetBelowDikeTopAtRiver = StaticReflection.GetMemberName(x => x.PL1PLLineOffsetBelowDikeTopAtRiver);
internal static readonly string OffsetBelowShoulderBaseInside = StaticReflection.GetMemberName(x => x.PL1PLLineOffsetBelowShoulderBaseInside);
internal static readonly string WaterLevelAtRiver = StaticReflection.GetMemberName(x => x.PL1WaterLevelAtRiver);
internal static readonly string PolderLevel = StaticReflection.GetMemberName(x => x.PL1WaterLevelAtPolder);
internal static readonly string PL3 = StaticReflection.GetMemberName(x => x.PL3);
internal static readonly string PL4 = StaticReflection.GetMemberName(x => x.PL4);
}
public double? GetValue(Expression> expression, IDictionary sensorValues, Sensor sensor)
{
if (sensorValues == null) throw new ArgumentNullException("sensorValues");
if (sensor == null) throw new ArgumentNullException("sensor");
if (!sensorValues.ContainsKey(sensor))
throw new ArgumentException("The given sensor is not an item/key in the table of sensor values");
var memberName = StaticReflection.GetMemberName(expression);
if (memberName == MemberNames.OffsetBelowDikeToeAtPolder)
{
if (PL1PLLineOffsetBelowDikeToeAtPolder == DataSourceTypeSensors.LocationData)
return Location.PlLineOffsetBelowDikeToeAtPolder;
}
if (memberName == MemberNames.OffsetBelowDikeTopAtPolder)
{
if (PL1PLLineOffsetBelowDikeTopAtPolder == DataSourceTypeSensors.LocationData)
return Location.PlLineOffsetBelowDikeTopAtPolder;
}
if (memberName == MemberNames.OffsetBelowDikeTopAtRiver)
{
if (PL1PLLineOffsetBelowDikeTopAtRiver == DataSourceTypeSensors.LocationData)
return Location.PlLineOffsetBelowDikeTopAtRiver;
}
if (memberName == MemberNames.OffsetBelowShoulderBaseInside)
{
if (PL1PLLineOffsetBelowShoulderBaseInside == DataSourceTypeSensors.LocationData)
return Location.PlLineOffsetBelowShoulderBaseInside;
}
if (memberName == MemberNames.WaterLevelAtRiver)
{
if (PL1WaterLevelAtRiver == DataSourceTypeSensors.LocationData)
return Location.RiverLevel;
if (PL1WaterLevelAtRiver == DataSourceTypeSensors.Sensor)
return sensorValues[sensor];
}
if (memberName == MemberNames.PolderLevel)
{
if (PL1WaterLevelAtPolder == DataSourceTypeSensors.LocationData)
return Location.PolderLevel;
if (PL1WaterLevelAtPolder == DataSourceTypeSensors.Sensor)
return sensorValues[sensor];
}
if (memberName == MemberNames.PL3)
{
if (PL3 == DataSourceTypeSensors.LocationData)
return Location.HeadPl3;
if (PL3 == DataSourceTypeSensors.Sensor)
return sensorValues[sensor];
}
if (memberName == MemberNames.PL4)
{
if (PL4 == DataSourceTypeSensors.LocationData)
return Location.HeadPl4;
if (PL4 == DataSourceTypeSensors.Sensor)
return sensorValues[sensor];
}
return null;
}
///
/// Determines whether this instance is valid.
///
///
/// true if this instance is valid; otherwise, false.
///
// public bool IsValid()
// {
// return !Validator.Validate(this).Any();
// }
///
/// Gets or sets the GetGroups function (injectable list, for UI purposes).
///
///
/// The list of available Groups.
///
public static Func> GetGroups { get; set; }
}
}