405 lines
14 KiB
C#
405 lines
14 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.ComponentModel;
|
|||
|
|
using System.Diagnostics;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Text;
|
|||
|
|
using DTS.Common.Converters;
|
|||
|
|
using DTS.Common.Enums.Sensors;
|
|||
|
|
using DTS.Common.Interface.Sensors;
|
|||
|
|
using DTS.Common.Utilities.Logging;
|
|||
|
|
|
|||
|
|
namespace DTS.Common.Classes.Sensors
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// InitialOffset is the replacement for InitialEU
|
|||
|
|
/// it encompasses the old InitialOffset specified in EU with a offset of specifying it in mV @EU
|
|||
|
|
/// Initial EU is a post data collection adjustment to engineering units recorded
|
|||
|
|
/// </summary>
|
|||
|
|
public class InitialOffset : Base.BasePropertyChanged
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// copy constructor
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="copy"></param>
|
|||
|
|
public InitialOffset(InitialOffset copy)
|
|||
|
|
{
|
|||
|
|
if (null == copy) { return; }
|
|||
|
|
EU = copy.EU;
|
|||
|
|
MV = copy.MV;
|
|||
|
|
Form = copy.Form;
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// default constructor
|
|||
|
|
/// </summary>
|
|||
|
|
public InitialOffset()
|
|||
|
|
{
|
|||
|
|
Form = InitialOffsetTypes.None;
|
|||
|
|
EU = 0D;
|
|||
|
|
MV = 0D;
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// constructor for the old format Initial EU (a single double representing offset in EU)
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="d"></param>
|
|||
|
|
public InitialOffset(double d)
|
|||
|
|
{
|
|||
|
|
Form = InitialOffsetTypes.EU;
|
|||
|
|
EU = d;
|
|||
|
|
MV = 0D;
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// constructor for string from db
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="s"></param>
|
|||
|
|
public InitialOffset(string s)
|
|||
|
|
{
|
|||
|
|
FromDbSerializeString(s);
|
|||
|
|
}
|
|||
|
|
public override string ToString()
|
|||
|
|
{
|
|||
|
|
var converter = new EnumDescriptionTypeConverter(typeof(InitialOffsetTypes));
|
|||
|
|
return converter.ConvertToString(Form);
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// serializes to a db safe string
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public string ToDbSerializeString()
|
|||
|
|
{
|
|||
|
|
var s = new List<string>
|
|||
|
|
{
|
|||
|
|
Form.ToString(),
|
|||
|
|
EU.ToString(System.Globalization.CultureInfo.InvariantCulture),
|
|||
|
|
MV.ToString(System.Globalization.CultureInfo.InvariantCulture)
|
|||
|
|
};
|
|||
|
|
return string.Join(System.Globalization.CultureInfo.InvariantCulture.TextInfo.ListSeparator, s.ToArray());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// deserializes from a string suitable for db storage
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="input"></param>
|
|||
|
|
public void FromDbSerializeString(string input)
|
|||
|
|
{
|
|||
|
|
if (string.IsNullOrWhiteSpace(input))
|
|||
|
|
{
|
|||
|
|
Form = InitialOffsetTypes.None;
|
|||
|
|
EU = 0;
|
|||
|
|
MV = 0;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (input == "EU")
|
|||
|
|
{
|
|||
|
|
Form = InitialOffsetTypes.EU;
|
|||
|
|
EU = 0;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (input.Contains(InitialOffsets.MySeparator))
|
|||
|
|
{
|
|||
|
|
//we got an InputOffsets input. just take the first one
|
|||
|
|
input = input.Split(new[] { InitialOffsets.MySeparator }, StringSplitOptions.RemoveEmptyEntries)[0];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var tokens = input.Split(new string[] { System.Globalization.CultureInfo.InvariantCulture.TextInfo.ListSeparator }, StringSplitOptions.None);
|
|||
|
|
|
|||
|
|
if (Enum.TryParse(tokens[0], out InitialOffsetTypes form))
|
|||
|
|
{
|
|||
|
|
Form = form;
|
|||
|
|
if (tokens.Length < 3)
|
|||
|
|
{
|
|||
|
|
throw new System.IO.InvalidDataException($"Invalid InitialOffset number of parameters: {input}");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (double.TryParse(tokens[1], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var d))
|
|||
|
|
{
|
|||
|
|
EU = d;
|
|||
|
|
}
|
|||
|
|
else { throw new FormatException($"Invalid InitialOffset EU format: {tokens[1]}"); }
|
|||
|
|
if (double.TryParse(tokens[2], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out d))
|
|||
|
|
{
|
|||
|
|
MV = d;
|
|||
|
|
}
|
|||
|
|
else { throw new FormatException($"Invalid InitialOffset MV format: {tokens[2]}"); }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else { throw new System.IO.InvalidDataException("Invalid InitialOffset form: " + tokens[0]); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private InitialOffsetTypes _form;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// the format this intial offset instance is in
|
|||
|
|
/// </summary>
|
|||
|
|
public InitialOffsetTypes Form
|
|||
|
|
{
|
|||
|
|
get => _form;
|
|||
|
|
set => SetProperty(ref _form, value, Fields.Form.ToString());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//FB18158 Don't allow removal of None option
|
|||
|
|
public System.Windows.Visibility InitialOffsetVisibility
|
|||
|
|
{
|
|||
|
|
get => Form != InitialOffsetTypes.None ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private double _eu = 0D;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// EU value. In the case of Form == EU, this is the offset in EU
|
|||
|
|
/// In. the form of EU@mV, this is the EU@mV value, and offset in EU still needs to be calculated
|
|||
|
|
/// GetInitialEUValue calculates the offset in eu
|
|||
|
|
/// this value is not used for InitialOffset format None
|
|||
|
|
/// </summary>
|
|||
|
|
public double EU
|
|||
|
|
{
|
|||
|
|
get => _eu;
|
|||
|
|
set => SetProperty(ref _eu, value, Fields.EU.ToString());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private double _mv = 0D;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// mV value, only applies for the format EU@mV
|
|||
|
|
/// this is the value in mV that The value in EU is observed at by a calibrated instrument
|
|||
|
|
/// </summary>
|
|||
|
|
public double MV
|
|||
|
|
{
|
|||
|
|
get => _mv;
|
|||
|
|
set => SetProperty(ref _mv, value, Fields.MV.ToString());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private enum Fields
|
|||
|
|
{
|
|||
|
|
Form,
|
|||
|
|
EU,
|
|||
|
|
MV
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Displays initial offset structure to string
|
|||
|
|
/// created for FB5429
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="NONEFormatString">string resource similar to "None"</param>
|
|||
|
|
/// <param name="EUFormatString">string resource similar to "EU"</param>
|
|||
|
|
/// <param name="mVFormatString">string resource similar to "mV"</param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public string ToDisplayString(string NONEFormatString, string EUFormatString, string mVFormatString)
|
|||
|
|
{
|
|||
|
|
var sb = new StringBuilder();
|
|||
|
|
switch (Form)
|
|||
|
|
{
|
|||
|
|
case InitialOffsetTypes.EU:
|
|||
|
|
case InitialOffsetTypes.LHS:
|
|||
|
|
case InitialOffsetTypes.RHS:
|
|||
|
|
case InitialOffsetTypes.FRONTAL:
|
|||
|
|
sb.AppendFormat("{0} {1}", EU, EUFormatString);
|
|||
|
|
break;
|
|||
|
|
case InitialOffsetTypes.EUAtMV:
|
|||
|
|
sb.AppendFormat("{0} {1} @ {2} {3}", EU, EUFormatString, MV, mVFormatString);
|
|||
|
|
break;
|
|||
|
|
case InitialOffsetTypes.None:
|
|||
|
|
sb.AppendFormat("{0}", NONEFormatString);
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
return sb.ToString();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Compares attributes to another InitialOffset object
|
|||
|
|
/// created for FB5429
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="obj">an InitialOffset object</param>
|
|||
|
|
/// <returns>if contents are equal</returns>
|
|||
|
|
public override bool Equals(object obj)
|
|||
|
|
{
|
|||
|
|
if (obj is InitialOffset io)
|
|||
|
|
{
|
|||
|
|
var fields = Enum.GetValues(typeof(Fields)).Cast<Fields>().ToArray();
|
|||
|
|
foreach (var field in fields)
|
|||
|
|
{
|
|||
|
|
switch (field)
|
|||
|
|
{
|
|||
|
|
case Fields.Form: if (io.Form != Form) { return false; } break;
|
|||
|
|
case Fields.EU: if (io.EU != EU) { return false; } break;
|
|||
|
|
case Fields.MV: if (io.MV != MV) { return false; } break;
|
|||
|
|
default:
|
|||
|
|
throw new NotSupportedException("InitialOffset::Equals Unknown field " + field);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return base.Equals(obj);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public class InitialOffsets : IInitialOffsets
|
|||
|
|
{
|
|||
|
|
public InitialOffset[] Offsets { get; set; } = new InitialOffset[] { };
|
|||
|
|
//FB18158 Always add None option to InitialOffsets
|
|||
|
|
private void SeedNoneInInitialOffsets()
|
|||
|
|
{
|
|||
|
|
if (Offsets.Any(p => p.Form == InitialOffsetTypes.None))
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
List<InitialOffset> initialOffsets = new List<InitialOffset>();
|
|||
|
|
initialOffsets.Add(new InitialOffset());
|
|||
|
|
foreach (var io in Offsets)
|
|||
|
|
{
|
|||
|
|
initialOffsets.Add(io);
|
|||
|
|
}
|
|||
|
|
Offsets = initialOffsets.ToArray();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public InitialOffset DefaultOffset
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
//30442 Don't default InitialOffset to None if other options exist
|
|||
|
|
if (null != Offsets && Offsets.Any())
|
|||
|
|
{
|
|||
|
|
if ((Offsets.Count() > 1) && (Offsets[0].Form == InitialOffsetTypes.None))
|
|||
|
|
{
|
|||
|
|
return Offsets[1];
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
return Offsets[0];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
return new InitialOffset();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public InitialOffsets(InitialOffsets copy)
|
|||
|
|
{
|
|||
|
|
InitialOffset[] offsets = new InitialOffset[copy.Offsets.Length];
|
|||
|
|
for (int i = 0; i < copy.Offsets.Length; i++)
|
|||
|
|
{
|
|||
|
|
offsets[i] = new InitialOffset(copy.Offsets[i]);
|
|||
|
|
}
|
|||
|
|
Offsets = offsets;
|
|||
|
|
SeedNoneInInitialOffsets();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// This produces an instance of the class based on an existing instance,
|
|||
|
|
/// but without the first Initial Offset, only additional Initial Offsets
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="copy"></param>
|
|||
|
|
/// <param name="numAdditionalInitialOffsets"></param>
|
|||
|
|
public InitialOffsets(InitialOffsets copy, int numAdditionalInitialOffsets)
|
|||
|
|
{
|
|||
|
|
InitialOffset[] offsets = new InitialOffset[numAdditionalInitialOffsets];
|
|||
|
|
for (int i = 0; i < numAdditionalInitialOffsets; i++)
|
|||
|
|
{
|
|||
|
|
offsets[i] = new InitialOffset(copy.Offsets[i + 1]);
|
|||
|
|
}
|
|||
|
|
Offsets = offsets;
|
|||
|
|
SeedNoneInInitialOffsets();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public InitialOffsets()
|
|||
|
|
{
|
|||
|
|
Offsets = new InitialOffset[] { new InitialOffset() };
|
|||
|
|
SeedNoneInInitialOffsets();
|
|||
|
|
}
|
|||
|
|
public InitialOffsets(string offsets)
|
|||
|
|
{
|
|||
|
|
FromSerializedString(offsets);
|
|||
|
|
SeedNoneInInitialOffsets();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public InitialOffsets(InitialOffset startingOffset)
|
|||
|
|
{
|
|||
|
|
Offsets = new InitialOffset[] { startingOffset };
|
|||
|
|
SeedNoneInInitialOffsets();
|
|||
|
|
}
|
|||
|
|
public override bool Equals(object obj)
|
|||
|
|
{
|
|||
|
|
if (obj is InitialOffsets r)
|
|||
|
|
{
|
|||
|
|
if (r.Offsets.Length != Offsets.Length) { return false; }
|
|||
|
|
for (var i = 0; i < r.Offsets.Length; i++)
|
|||
|
|
{
|
|||
|
|
if (!r.Offsets[i].Equals(Offsets[i])) { return false; }
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return base.Equals(obj);
|
|||
|
|
}
|
|||
|
|
public void FromSerializedString(string s)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
var tokens = s.Split(new string[] { MySeparator }, StringSplitOptions.None);
|
|||
|
|
for (var i = 0; i < tokens.Length; i++) { tokens[i] = tokens[i].Replace(MySeparatorBackup, MySeparator); }
|
|||
|
|
|
|||
|
|
var offsets = new List<InitialOffset>();
|
|||
|
|
foreach (string token in tokens)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
offsets.Add(new InitialOffset(token));
|
|||
|
|
}
|
|||
|
|
catch (Exception ex) { APILogger.Log(ex); }
|
|||
|
|
}
|
|||
|
|
Offsets = offsets.ToArray();
|
|||
|
|
SeedNoneInInitialOffsets();
|
|||
|
|
}
|
|||
|
|
catch( Exception ex)
|
|||
|
|
{
|
|||
|
|
APILogger.Log(ex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
internal const string MySeparator = "__x__";
|
|||
|
|
internal const string MySeparatorBackup = "___xx___";
|
|||
|
|
public string ToSerializedString()
|
|||
|
|
{
|
|||
|
|
var offsets = new List<string>();
|
|||
|
|
|
|||
|
|
foreach (var r in Offsets) { offsets.Add(r.ToDbSerializeString()); }
|
|||
|
|
|
|||
|
|
for (int i = 0; i < offsets.Count; i++)
|
|||
|
|
{
|
|||
|
|
Trace.Assert(!offsets[i].Contains(MySeparatorBackup));
|
|||
|
|
offsets[i] = offsets[i].Replace(MySeparator, MySeparatorBackup);
|
|||
|
|
}
|
|||
|
|
return string.Join(MySeparator, offsets.ToArray());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public string ToDisplayString(string averageOverTimeFormatString, string diagnosticLevelFormatString, string absoluteZeroFormatString)
|
|||
|
|
{
|
|||
|
|
var sb = new StringBuilder();
|
|||
|
|
|
|||
|
|
for (var i = 0; i < Offsets.Length; i++)
|
|||
|
|
{
|
|||
|
|
if (i > 0) { sb.AppendLine(); }
|
|||
|
|
|
|||
|
|
var s = Offsets[i].ToDisplayString(averageOverTimeFormatString, diagnosticLevelFormatString, absoluteZeroFormatString);
|
|||
|
|
if (!string.IsNullOrEmpty(s))
|
|||
|
|
{
|
|||
|
|
sb.Append(s);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
return sb.ToString();
|
|||
|
|
}
|
|||
|
|
public override string ToString()
|
|||
|
|
{
|
|||
|
|
return ToDisplayString(Strings.Strings.SensorFields_InitialOffset_AverageOverTimeFormat, Strings.Strings.SensorFields_InitialOffset_DiagnosticLevelFormat,
|
|||
|
|
Strings.Strings.SensorFields_InitialOffset_AbsoluteZeroFormat);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|