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; namespace DTS.Common.Classes.Sensors { /// /// 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 /// public class InitialOffset : Base.BasePropertyChanged { /// /// copy constructor /// /// public InitialOffset(InitialOffset copy) { if (null == copy) { return; } EU = copy.EU; MV = copy.MV; Form = copy.Form; } /// /// default constructor /// public InitialOffset() { Form = InitialOffsetTypes.None; EU = 0D; MV = 0D; } /// /// constructor for the old format Initial EU (a single double representing offset in EU) /// /// public InitialOffset(double d) { Form = InitialOffsetTypes.EU; EU = d; MV = 0D; } /// /// constructor for string from db /// /// public InitialOffset(string s) { FromDbSerializeString(s); } public override string ToString() { var converter = new EnumDescriptionTypeConverter(typeof(InitialOffsetTypes)); return converter.ConvertToString(Form); } /// /// serializes to a db safe string /// /// public string ToDbSerializeString() { var s = new List { 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()); } /// /// deserializes from a string suitable for db storage /// /// 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; /// /// the format this intial offset instance is in /// 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; /// /// 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 /// public double EU { get => _eu; set => SetProperty(ref _eu, value, Fields.EU.ToString()); } private double _mv = 0D; /// /// 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 /// public double MV { get => _mv; set => SetProperty(ref _mv, value, Fields.MV.ToString()); } private enum Fields { Form, EU, MV } /// /// Displays initial offset structure to string /// created for FB5429 /// /// string resource similar to "None" /// string resource similar to "EU" /// string resource similar to "mV" /// 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(); } /// /// Compares attributes to another InitialOffset object /// created for FB5429 /// /// an InitialOffset object /// if contents are equal public override bool Equals(object obj) { if (obj is InitialOffset io) { var fields = Enum.GetValues(typeof(Fields)).Cast().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 initialOffsets = new List(); 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.First(); } } 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(); } /// /// This produces an instance of the class based on an existing instance, /// but without the first Initial Offset, only additional Initial Offsets /// /// /// 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) { 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(); foreach (string token in tokens) { offsets.Add(new InitialOffset(token)); } Offsets = offsets.ToArray(); SeedNoneInInitialOffsets(); } internal const string MySeparator = "__x__"; internal const string MySeparatorBackup = "___xx___"; public string ToSerializedString() { var offsets = new List(); 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); } } }