/// /// Copyright (c) 2013-2015 Sensus Metering Systems /// using System; using System.Collections.Generic; using System.Globalization; using Config.Entities; namespace TBF { public class Utils { /// /// Parse unsigned float /// public static bool TryParseUFloat(string text, out float result) { return float.TryParse(text, NumberStyles.AllowDecimalPoint, CultureInfo.CurrentCulture, out result) || float.TryParse(text, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out result) || (Program.AltCulture != null && float.TryParse(text, NumberStyles.AllowDecimalPoint, Program.AltCulture, out result)); } public static float ParseUFloat(string text, float dfltVal) { float result; if (float.TryParse(text, NumberStyles.AllowDecimalPoint, CultureInfo.CurrentCulture, out result)) return result; if (float.TryParse(text, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out result)) return result; if (Program.AltCulture != null && float.TryParse(text, NumberStyles.AllowDecimalPoint, Program.AltCulture, out result)) return result; return dfltVal; } public static float ParseUFloat(string text) { return ParseUFloat(text, 0); } /// /// Parse float, sign allowed /// public static bool TryParseSFloat(string text, out float result) { return float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.CurrentCulture, out result) || float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out result) || (Program.AltCulture != null && float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, Program.AltCulture, out result)); } public static float ParseSFloat(string text, float dfltVal) { float result; if (float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.CurrentCulture, out result)) return result; if (float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out result)) return result; if (Program.AltCulture != null && float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, Program.AltCulture, out result)) return result; return dfltVal; } public static float ParseSFloat(string text) { return ParseSFloat(text, 0); } /// /// Parse float, sign allowed, exponent allowed /// public static bool TryParseEFloat(string text, out float result) { return float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, CultureInfo.CurrentCulture, out result) || float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out result) || (Program.AltCulture != null && float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, Program.AltCulture, out result)); } public static float ParseEFloat(string text, float dfltVal) { float result; if (float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, CultureInfo.CurrentCulture, out result)) return result; if (float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out result)) return result; if (Program.AltCulture != null && float.TryParse(text, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, Program.AltCulture, out result)) return result; return dfltVal; } public static float ParseEFloat(string text) { return ParseEFloat(text, 0); } /// /// Get a list of IValve-s from an entity implementing IHasValves /// /// Entity implementing IHasValves /// A list of IValves public static IList ValvesOpen(IHasValves entity) { var valvesOpen = new List(); if (entity != null && entity.ValvesOpen != null && entity.ValvesOpen != string.Empty) { string[] vOpen = entity.ValvesOpen.Split(new char[] { ';' }); foreach (var vName in vOpen) { valvesOpen.Add((BenchControl.GenericDevices.IValve)BenchControl.TbfComponents.FindComponent(vName)); } } return valvesOpen; } /// /// Get a list of IValve-s from an entity implementing IHasValves /// /// Entity implementing IHasValves /// A list of IValves public static IList ValvesClose(IHasValves entity) { var valvesClose = new List(); if (entity != null && entity.ValvesClose != null && entity.ValvesClose != string.Empty) { string[] vClose = entity.ValvesClose.Split(new char[] { ';' }); foreach (var vName in vClose) { valvesClose.Add((BenchControl.GenericDevices.IValve)BenchControl.TbfComponents.FindComponent(vName)); } } return valvesClose; } /// /// Get an array of RegulValve positions from a TransitionStep entity /// /// TransitionStep entity /// float[] of regulation valve positions from 0 to 100.0f public static float[] GetRegulValvesPositions(TransitionStep step) { int regvCount = BenchControl.Sequences.SequenceBase.RegulValves.Count; float[] result = new float[regvCount]; string[] rvPosStr = (step.RegulValvesPct != null) ? step.RegulValvesPct.Split(new char[] { ';' }) : new string[0]; for (int i = 0; i < regvCount; i++) { float fdummy; if ((i < rvPosStr.Length) && Utils.TryParseUFloat(rvPosStr[i], out fdummy) && (fdummy >= 0) && (fdummy <= 100.0f)) { result[i] = fdummy; } else // if ((i < rvPosStr.Length) && rvPosStr[i].Equals("---")) { result[i] = -1.0f; /// Negative value means no regulation valve position change } } return result; } /// /// Get an array of Pump-With-FM power percentages from a TransitionStep entity /// /// TransitionStep entity /// float[] of FM-pump power percentages from 0 to 100.0f public static float[] GetPumpWithFMPcts(TransitionStep step) { int fmPumpCount = BenchControl.Sequences.SequenceBase.PumpsWithFM.Count; float[] result = new float[fmPumpCount]; string[] fmPctsStr = (step.PumpWithFMPcts != null) ? step.PumpWithFMPcts.Split(new char[] { ';' }) : new string[0]; for (int i = 0; i < fmPumpCount; i++) { float fdummy; if ((i < fmPctsStr.Length) && Utils.TryParseUFloat(fmPctsStr[i], out fdummy) && (fdummy >= 0) && (fdummy <= 100.0f)) { result[i] = fdummy; } else if ((i < fmPctsStr.Length) && fmPctsStr[i].Equals("Dflt")) { result[i] = -2.0f; /// This value means default pump power defined by the Test parameter } else //if ((i < rvPosStr.Length) && rvPosStr[i].Equals("---")) { result[i] = -1.0f; /// This value means no pump power change } } return result; } /// /// Pre-fetch the test results from the currently available results. /// The order of the returned results is the same as the order of tests in the procedure specification. /// /// Current procedure, it is used to determine the order of resulting test results /// Currently available unsorted test results (can also be null) /// Water meter number (1-based) or 0=all (also compared with nonzero 'Part' number) /// Ordered list of test results containing null-s for missing results public static IList GetSortedTestResults(Procedure procedure, IList testResults, int meterPartNr) { IList rslts = new List(); if (procedure == null) return rslts; /// Return an empty list if no procedure specified foreach (var test in procedure.Tests) { BenchControl.GenericDevices.ITestMethod method = BenchControl.TbfComponents.FindComponent(test.Method) as BenchControl.GenericDevices.ITestMethod; if ((method != null) && method.Publish(test) && ((test.Part == 0) || (meterPartNr == 0) || (test.Part == meterPartNr))) { for (int rpt = 1; rpt <= test.Repeats; rpt++) { bool added = false; if (testResults != null) { foreach (var testRslt in testResults) { if ((testRslt.TestId == test.Id) && (testRslt.RepetitionNr == rpt)) { rslts.Add(testRslt); added = true; break; } } } if (!added) rslts.Add(null); } } } return rslts; } /// /// Pre-fetch the test names given the procedure and the meter number. /// The order or test names is the same as in the procedure specification. /// /// Procedure /// Water meter number (1-based) or 0=all (also compared with nonzero 'Part' number) /// Ordered list of test names public static IList GetDecoratedTestNames(Procedure procedure, int meterPartNr) { IList names = new List(); if (procedure == null) return names; /// Return an empty list if no procedure specified foreach (var test in procedure.Tests) { BenchControl.GenericDevices.ITestMethod method = BenchControl.TbfComponents.FindComponent(test.Method) as BenchControl.GenericDevices.ITestMethod; if ((method != null) && method.Publish(test) && ((test.Part == 0) || (meterPartNr == 0) || (test.Part == meterPartNr))) { if (test.Repeats == 1) { names.Add(test.Name); continue; } for (int rpt = 1; rpt <= test.Repeats; rpt++) { names.Add(test.Name + string.Format(" ({0}/{1})", rpt, test.Repeats)); } } } return names; } /// /// To prepare the last argument of GetSortedTestResults() and GetDecoratedTestNames() functions /// /// Watermeter nr. (1-based) /// Meter: false=standard, true=combined /// Part nr. of the meter public static int PartNr(int wmNr1, bool combined) { if (wmNr1 == 0) return 0; if (combined) return wmNr1; int wmPartSize = (wmNr1 - 1) / Config.Data.LineSize + 1; return wmPartSize; } /// /// Return test title for a given test and repetition number /// /// Test entity /// 1 .. Nr. repetitions /// Test title (string) public static string TestTitle(Test test, int repetitonNr) { if (test.Repeats == 1) { if (test.Part == 0) { return test.Name; /// Single test } else { return string.Format("{0} ({1})", test.Name, test.Part); /// A part of a single test } } else { /// More test repetitions return string.Format("{0} ({1}/{2})", test.Name, repetitonNr, test.Repeats); } } /// /// Converts a float number to a string with the specified number of valid digits /// /// Float value to be converted to a string /// Number of valid digits: 4, 3, or 2 (otherwise a full precision number is printed) /// String representation of a float number public static string FloatToStr(float value, int validDigits) { if (-float.Epsilon <= value && value <= float.Epsilon) { return "0"; } else if (validDigits == 4) { if (value >= 999.5 || value < -999.5) return value.ToString("F0"); else if (value >= 99.95 || value < -99.95) return value.ToString("F1"); else if (value >= 9.995 || value < -9.995) return value.ToString("F2"); else if (value >= 0.9995 || value < -0.9995) return value.ToString("F3"); else if (value >= 0.09995 || value < -0.09995) return value.ToString("F4"); else if (value >= 0.009995 || value < -0.009995) return value.ToString("F5"); else return value.ToString("F6"); } else if (validDigits == 3) { if (value >= 99.5 || value < -99.5) return value.ToString("F0"); else if (value >= 9.95 || value < -9.95) return value.ToString("F1"); else if (value >= 0.995 || value < -0.995) return value.ToString("F2"); else if (value >= 0.0995 || value < -0.0995) return value.ToString("F3"); else if (value >= 0.00995 || value < -0.00995) return value.ToString("F4"); else if (value >= 0.000995 || value < -0.000995) return value.ToString("F5"); else return value.ToString("F6"); } else if (validDigits == 2) { if (value >= 9.5 || value < -9.5) return value.ToString("F0"); else if (value >= 0.95 || value < -0.95) return value.ToString("F1"); else if (value >= 0.095 || value < -0.095) return value.ToString("F2"); else if (value >= 0.0095 || value < -0.0095) return value.ToString("F3"); else if (value >= 0.00095 || value < -0.00095) return value.ToString("F4"); else return value.ToString("F5"); } else return value.ToString(); } /// /// Converts a double number to a string with the specified number of valid digits /// /// Double value to be converted to a string /// Number of valid digits: 4, 3, or 2 (otherwise a full precision number is printed) /// String representation of a double number public static string DoubleToStr(double value, int validDigits) { if (-float.Epsilon <= value && value <= float.Epsilon) { return "0"; } else if (validDigits == 4) { if (value >= 999.5 || value < -999.5) return value.ToString("F0"); else if (value >= 99.95 || value < -99.95) return value.ToString("F1"); else if (value >= 9.995 || value < -9.995) return value.ToString("F2"); else if (value >= 0.9995 || value < -0.9995) return value.ToString("F3"); else if (value >= 0.09995 || value < -0.09995) return value.ToString("F4"); else if (value >= 0.009995 || value < -0.009995) return value.ToString("F5"); else return value.ToString("F6"); } else if (validDigits == 3) { if (value >= 99.5 || value < -99.5) return value.ToString("F0"); else if (value >= 9.95 || value < -9.95) return value.ToString("F1"); else if (value >= 0.995 || value < -0.995) return value.ToString("F2"); else if (value >= 0.0995 || value < -0.0995) return value.ToString("F3"); else if (value >= 0.00995 || value < -0.00995) return value.ToString("F4"); else if (value >= 0.000995 || value < -0.000995) return value.ToString("F5"); else return value.ToString("F6"); } else if (validDigits == 2) { if (value >= 9.5 || value < -9.5) return value.ToString("F0"); else if (value >= 0.95 || value < -0.95) return value.ToString("F1"); else if (value >= 0.095 || value < -0.095) return value.ToString("F2"); else if (value >= 0.0095 || value < -0.0095) return value.ToString("F3"); else if (value >= 0.00095 || value < -0.00095) return value.ToString("F4"); else return value.ToString("F5"); } else return value.ToString(); } public static string ShowRoute(ulong route) { string str = string.Empty; int i = 0; for (ulong bitmask = 0x8000000000000000; bitmask > 0; bitmask /= 2) { str += ((route & bitmask) != 0) ? "1" : "0"; i++; if (i < 64) { if ((i % 16) == 0) str += "-"; else if ((i % 8) == 0) str += " "; } } return str; } public static string ToMyString(DateTime dateTime) { return string.Format("{0}{1}{2}_{3}{4}", dateTime.Year, dateTime.Month.ToString("D2"), dateTime.Day.ToString("D2"), dateTime.Hour.ToString("D2"), dateTime.Minute.ToString("D2")); } } }