using System; using System.Collections.Generic; using System.Xml.Linq; using System.ComponentModel; using System.Globalization; using DTS.Common.Enums.Sensors; using DTS.Common.Interface.Sensors.SoftwareFilters; using DTS.Common.Interface.Sensors; using System.Linq; namespace DTS.Common.Classes.Sensors { public class FilterClass : INotifyPropertyChanged, IFilterClass { public event PropertyChangedEventHandler PropertyChanged; protected bool SetProperty(ref T storage, T value, String propertyName = null) { if (Equals(storage, value)) return false; storage = value; OnPropertyChanged(propertyName); return true; } protected void OnPropertyChanged(string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public FilterClassType FClass { get; set; } //FB 13120 used for filter options drop down localization public string FilterName { get { string name = ""; if (FClass == FilterClassType.None) { name = Strings.Strings.FilterClassType_None; } else if (FClass == FilterClassType.Unfiltered) { name = Strings.Strings.FilterClassType_Unfiltered; } else if (FClass == FilterClassType.AdHoc) { name = Frequency.ToString(); } else { name = Frequency + " (" + FClass.ToString() + ")"; } return name; } } /// /// Gets the numeric filter class value for the filter class; EX CFC60 returns 60, CFC1000 returns 1000 /// /// integer for filter class name public int GetFilterClassNumericValue() { switch (FClass) { case FilterClassType.CFC10: return 10; case FilterClassType.CFC60: return 60; case FilterClassType.CFC180: return 180; case FilterClassType.CFC600: return 600; case FilterClassType.None: return 0; case FilterClassType.Unfiltered: return -2; default: // adhoc and cfc1000 enter here return 1000; } } private double _Frequency; public double Frequency { get { return _Frequency; } set { _Frequency = value; } } #region Tags internal const string FilterClassTag = "FilterClass"; internal const string ClassTag = "Class"; internal const string FrequencyTag = "Frequency"; #endregion private string TableName; public FilterClass(XElement elem, string prefix, string tblName, string id) { TableName = tblName; XElement inner = null; try { inner = elem.Element(mkTag(prefix)); } catch (ArgumentNullException) { if (!string.IsNullOrEmpty(id)) { throw new System.Exception(string.Format("{0}: Can't find tag {1} for entry {2}", TableName, prefix + "-" + FilterClassTag, id)); } throw new System.Exception(string.Format("{0}: Can't find tag {1} in file", TableName, prefix + "-" + FilterClassTag)); } FClass = (FilterClassType)Enum.Parse(typeof(FilterClassType), inner.Attribute(ClassTag).Value); switch (FClass) { case FilterClassType.None: _Frequency = (double)FilterClassType.None; break; case FilterClassType.Unfiltered: _Frequency = (double)FilterClassType.Unfiltered; break; case FilterClassType.CFC10: _Frequency = (double)FilterClassType.CFC10; break; case FilterClassType.CFC60: _Frequency = (double)FilterClassType.CFC60; break; case FilterClassType.CFC180: _Frequency = (double)FilterClassType.CFC180; break; case FilterClassType.CFC600: _Frequency = (double)FilterClassType.CFC600; break; case FilterClassType.CFC1000: _Frequency = (double)FilterClassType.CFC1000; break; case FilterClassType.AdHoc: if (!double.TryParse(inner.Value, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out _Frequency)) { throw new System.Exception(string.Format("{0}: Invalid filter frequency {1}", TableName, inner.Value)); } break; } } public FilterClass(FilterClassType fc, double freq) { FClass = fc; Frequency = freq; } public static FilterClassType GetFilterClassTypeFromNumericFC(int fc) { switch (fc) { case 1000: case -1: return FilterClassType.CFC1000; case 600: return FilterClassType.CFC600; case 180: return FilterClassType.CFC180; case 60: return FilterClassType.CFC60; case 10: return FilterClassType.CFC10; case 0: return FilterClassType.None; case -2: return FilterClassType.Unfiltered; default: return FilterClassType.None; } } public FilterClass(double freq) { Frequency = freq; if (freq == (double)FilterClassType.CFC10) { FClass = FilterClassType.CFC10; } else if (freq == (double)FilterClassType.CFC60) { FClass = FilterClassType.CFC60; } else if (freq == (double)FilterClassType.CFC180) { FClass = FilterClassType.CFC180; } else if (freq == (double)FilterClassType.CFC600) { FClass = FilterClassType.CFC600; } else if (freq == (double)FilterClassType.CFC1000) { FClass = FilterClassType.CFC1000; } else if (freq == 0) { FClass = FilterClassType.None; } else if (freq == (double)FilterClassType.Unfiltered) { FClass = FilterClassType.Unfiltered; } else { FClass = FilterClassType.AdHoc; //FB 13120 set the frequency for ad hoc filters Frequency = freq; } } /// ///FB 13120 Specify and return the default filter class /// /// public static FilterClass GetDefaultFilterClass(List softwareFilters) { if (softwareFilters == null) { return new FilterClass(FilterClassType.CFC1000); } var softwareFilter = softwareFilters.Find(p => p.IsDefault); FilterClass fc = null; switch (softwareFilter?.ISOCode) { case '0': fc = new FilterClass(FilterClassType.Unfiltered); break; case 'P': fc = new FilterClass(FilterClassType.None); break; case 'S': fc = new FilterClass(FilterClassType.AdHoc, softwareFilter.Frequency); break; case 'A': fc = new FilterClass(FilterClassType.CFC1000); break; case 'B': fc = new FilterClass(FilterClassType.CFC600); break; case 'C': fc = new FilterClass(FilterClassType.CFC180); break; case 'D': fc = new FilterClass(FilterClassType.CFC60); break; default: fc = new FilterClass(FilterClassType.CFC1000); break; } return fc; } /// /// FB 13120 Get the filter class based on the isoCode provided /// /// /// this frequency will be used for AdHoc filter /// public static FilterClass GetFilterClassFromIsoCode(string isoCode, double frequency = 0) { if (string.IsNullOrEmpty(isoCode)) { return new FilterClass(FilterClassType.CFC1000); } FilterClass fc = null; switch (isoCode.ToUpper()) { case "0": fc = new FilterClass(FilterClassType.Unfiltered); break; case "P": fc = new FilterClass(FilterClassType.None); break; case "S": fc = new FilterClass(FilterClassType.AdHoc, frequency); break; case "A": fc = new FilterClass(FilterClassType.CFC1000); break; case "B": fc = new FilterClass(FilterClassType.CFC600); break; case "C": fc = new FilterClass(FilterClassType.CFC180); break; case "D": fc = new FilterClass(FilterClassType.CFC60); break; default: fc = new FilterClass(FilterClassType.CFC1000); break; } return fc; } /// /// FB 15574 Get the FilterClass setting from cfc iso code /// /// cfc iso code ex: A /// filter class setting on format of FilterType,Frequency ex: None,0 public static string GetFilterClassSettingFromCFC(string cfcIsoCode) { var filterClass = GetFilterClassFromIsoCode(cfcIsoCode); return $"{filterClass.FClass.ToString()},{filterClass.Frequency}"; } /// ///FB 15574 Get the FilterClass setting from FilterClass /// /// /// filter class setting on format of FilterType,Frequency ex: None,0 public static string GetFilterClassSettingFromFilterClass(IFilterClass filterClass) { return $"{filterClass.FClass.ToString()},{filterClass.Frequency}"; } public static double GetFrequencyFromFilterClassType(FilterClassType filterClassType) { if (filterClassType == FilterClassType.AdHoc) { throw new Exception("GetFrequencyFromFilterClassType: AdHoc FilterClassType does not have frequency associated"); } return (double)filterClassType; } public static FilterClass GetFilterClassFromFilterClassType(FilterClassType filterClassType, double adHocFrequency = 0) { if (filterClassType == FilterClassType.AdHoc) { return new FilterClass(filterClassType, adHocFrequency); } return new FilterClass(filterClassType); } public static FilterClass GetFilterClassFromFilterClassSetting(string filterClassSetting) { if (string.IsNullOrEmpty(filterClassSetting)) { return GetFilterClassFromFilterClassType(FilterClassType.Unfiltered); } var setting = filterClassSetting.Split(','); if (Enum.TryParse(setting[0], out FilterClassType fct)) { return GetFilterClassFromFilterClassType(fct, Convert.ToDouble(setting[1])); } return GetFilterClassFromFilterClassType(FilterClassType.Unfiltered); } public FilterClass(FilterClassType fc) { FClass = fc; switch (fc) { case FilterClassType.None: Frequency = 0; break; case FilterClassType.AdHoc: Frequency = (double)FilterClassType.AdHoc; break; case FilterClassType.Unfiltered: Frequency = (double)FilterClassType.Unfiltered; break; case FilterClassType.CFC10: Frequency = (double)FilterClassType.CFC10; break; case FilterClassType.CFC60: Frequency = (double)FilterClassType.CFC60; break; case FilterClassType.CFC180: Frequency = (double)FilterClassType.CFC180; break; case FilterClassType.CFC600: Frequency = (double)FilterClassType.CFC600; break; case FilterClassType.CFC1000: Frequency = (double)FilterClassType.CFC1000; break; default: throw new System.Exception("FilterClass: unknown class"); } } public XElement ToXElement(string prefix) { var element = new XElement(mkTag(prefix), Frequency); element.SetAttributeValue(ClassTag, FClass.ToString()); return element; } public void Update(XElement elem, string prefix) { elem.SetElementValue(mkTag(prefix), Frequency); var element = elem.Element(mkTag(prefix)); element.SetAttributeValue(ClassTag, FClass.ToString()); } public static string mkTag(string prefix) { return prefix + "-" + FilterClassTag; } public override string ToString() { switch (FClass) { case FilterClassType.None: return "None"; case FilterClassType.Unfiltered: return "Unfiltered"; case FilterClassType.CFC10: return string.Format("{0} (CFC10)", (int)FilterClassType.CFC10); case FilterClassType.CFC60: return string.Format("{0} (CFC60)", (int)FilterClassType.CFC60); case FilterClassType.CFC180: return string.Format("{0} (CFC180)", (int)FilterClassType.CFC180); case FilterClassType.CFC600: return string.Format("{0} (CFC600)", (int)FilterClassType.CFC600); case FilterClassType.CFC1000: return string.Format("{0} (CFC1000)", (int)FilterClassType.CFC1000); case FilterClassType.AdHoc: return ((int)Frequency).ToString(); } throw new System.Exception("FilterClass.ToString: Invalid class=" + FClass.ToString()); } public FilterClass(string fclass) { int fc; if (int.TryParse(fclass, NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out fc)) { switch (fc) { case 17: FClass = FilterClassType.CFC10; _Frequency = (double)FClass; return; case 100: FClass = FilterClassType.CFC60; _Frequency = (double)FClass; return; case 300: FClass = FilterClassType.CFC180; _Frequency = (double)FClass; return; case 1000: FClass = FilterClassType.CFC600; _Frequency = (double)FClass; return; case 1650: FClass = FilterClassType.CFC1000; _Frequency = (double)FClass; return; } } if (string.IsNullOrEmpty(fclass) || fclass == "None") { FClass = FilterClassType.None; } else if (fclass.Contains("Unfiltered")) { FClass = FilterClassType.Unfiltered; _Frequency = (double)FilterClassType.Unfiltered; } else if (fclass.Contains("CFC1000")) { FClass = FilterClassType.CFC1000; _Frequency = (double)FilterClassType.CFC1000; } else if (fclass.Contains("CFC600")) { FClass = FilterClassType.CFC600; _Frequency = (double)FilterClassType.CFC600; } else if (fclass.Contains("CFC60")) { FClass = FilterClassType.CFC60; _Frequency = (double)FilterClassType.CFC60; } else if (fclass.Contains("CFC180")) { FClass = FilterClassType.CFC180; _Frequency = (double)FilterClassType.CFC180; } else { //FB 13120 parse and set frequncy double freq = 0; if (double.TryParse(fclass, out freq)) { FClass = FilterClassType.AdHoc; _Frequency = freq; } else { FClass = FilterClassType.CFC1000; _Frequency = (double)FilterClassType.CFC1000; } } } public override bool Equals(object obj) { if (obj == null) { return false; } if (!(obj is FilterClass)) { return false; } var filterObj = obj as FilterClass; //FB 13120 needs this since the frequency would be different (-2 & 0) for unfiltered case if (FClass == filterObj.FClass && FClass == FilterClassType.Unfiltered) { return true; } return FClass == filterObj.FClass && Frequency == filterObj.Frequency; } public int CompareTo(object filterClass) { IFilterClass fc = filterClass as FilterClass; if (this == null) { if (fc == null) { // both null, equal return 0; } // left null but not right return -1; } if (fc == null) { // left not null, right null return 1; } if (FClass != FilterClassType.None) return fc.FClass == FilterClassType.None ? 1 : Frequency.CompareTo(fc.Frequency); if (fc.FClass == FilterClassType.None) { return 0; } return -1; } /// /// returns an identical hash index for any two "equal" filterclass objects /// /// public override int GetHashCode() { //.equals compares frequency and class, but we just need to guarantee that //equal objects hash to the same index return Convert.ToInt32(Frequency); } /// /// FB 13120 Factory method to create a filter class /// /// /// /// public static IFilterClass CreateFilterClass(FilterClassType fc, double frequency = 0) { if (fc == FilterClassType.AdHoc) { return new FilterClass(frequency); } else { return new FilterClass(fc); } } /// /// Get the filter class based on the string cfc /// /// /// public static IFilterClass GetFilterClassFromString(string s) { if (string.IsNullOrEmpty(s)) return new FilterClass(FilterClassType.Unfiltered); s = s.ToLower().Replace("cfc", "").Replace("hz", "").Trim(); double freq = 0; if (double.TryParse(s, out freq)) { switch (freq) { case 10: return new FilterClass(FilterClassType.CFC10); case 60: return new FilterClass(FilterClassType.CFC60); case 180: return new FilterClass(FilterClassType.CFC180); case 600: return new FilterClass(FilterClassType.CFC600); case 1000: return new FilterClass(FilterClassType.CFC1000); default: return new FilterClass(FilterClassType.AdHoc, freq); } } else { switch (s.ToLower()) { case "unfiltered": return new FilterClass(FilterClassType.Unfiltered); case "none": return new FilterClass(FilterClassType.None); default: return new FilterClass(FilterClassType.Unfiltered); } } } } }