/* * Copyright (C) 2016 Vyacheslav Shevelyov (slavash at aha dot ru) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ using IStation.Epanet.Enums; using System.Globalization; namespace IStation.Epanet.Util { ///Epanet utilities methods. public static class Utilities { /// Check if two strings match (case independent), based on the shortest string length. /// string A. /// string B. /// Boolean is the two strings are similar. public static bool Match2(this string a, string b) { if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b)) return false; return a.Length > b.Length ? a.StartsWith(b, StringComparison.OrdinalIgnoreCase) : b.StartsWith(a, StringComparison.OrdinalIgnoreCase); } /// /// Sees if substr matches any part of str (not case sensitive). /// /// string being searched /// substring being searched for /// returns true if substr found in str, false if not public static bool Match(this string str, string substr) { /* Fail if substring is empty */ if (string.IsNullOrEmpty(str) || string.IsNullOrEmpty(substr)) return false; /* Skip leading blanks of str. */ str = str.TrimStart(); /* Check if substr matches remainder of str. */ return str.StartsWith(substr, StringComparison.OrdinalIgnoreCase); } public static int FindMatch(this string str, params string[] substrings) { for (int i = 0; i < substrings.Length; i++) { if (Match(str, substrings[i])) { return i; } } return -1; } /// Converts time from units to hours. /// string containing a time value /// string containing time units (PM or AM) /// numerical value of time in hours (1.0 is 3600 seconds), or -1 if an error occurs public static double GetHour(string time, string units = null) { const int COUNT = 3; double[] y = new double[COUNT]; // Separate clock time into hrs, min, sec. string[] s = (time ?? string.Empty).Split(':'); int n; for (n = 0; n < COUNT && n < s.Length; n++) { if (!s[n].ToDouble(out y[n])) return -1; } // If decimal time with units attached then convert to hours. if (n == 1) { if (string.IsNullOrEmpty(units)) return y[0]; if (Match(units, Keywords.w_SECONDS)) return y[0] / 3600.0; if (Match(units, Keywords.w_MINUTES)) return y[0] / 60.0; if (Match(units, Keywords.w_HOURS)) return y[0]; if (Match(units, Keywords.w_DAYS)) return y[0] * 24.0; } // Convert hh:mm:ss format to decimal hours if (n > 1) y[0] = y[0] + y[1] / 60.0 + y[2] / 3600.0; // If am/pm attached then adjust hour accordingly // (12 am is midnight, 12 pm is noon) if (string.IsNullOrEmpty(units)) return y[0]; if (units.Equals(Keywords.w_AM, StringComparison.OrdinalIgnoreCase)) { if (y[0] >= 13.0) return -1.0; if (y[0] >= 12.0) return y[0] - 12.0; return y[0]; } if (units.Equals(Keywords.w_PM, StringComparison.OrdinalIgnoreCase)) { if (y[0] >= 13.0) return -1.0; if (y[0] >= 12.0) return y[0]; return y[0] + 12.0; } return -1.0; } public static TimeSpan TimeOfDay(this TimeSpan t) { return new TimeSpan(t.Ticks % TimeSpan.TicksPerDay); } /// Converts time from units to hours. /// string containing a time value /// string containing time units (PM or AM) /// numerical value of time in hours (1.0 is 3600 seconds), or -1 if an error occurs public static TimeSpan ToTimeSpan(string time, string units = null) { const int COUNT = 3; double[] y = new double[COUNT]; // Separate clock time into hrs, min, sec. string[] s = (time ?? string.Empty).Split(':'); int n; for (n = 0; n < COUNT && n < s.Length; n++) { if (!s[n].ToDouble(out y[n])) return TimeSpan.MinValue; } // If decimal time with units attached then convert to hours. if (n == 1) { if (string.IsNullOrEmpty(units)) return TimeSpan.FromHours(y[0]); if (Match(units, Keywords.w_SECONDS)) return TimeSpan.FromSeconds(y[0]); if (Match(units, Keywords.w_MINUTES)) return TimeSpan.FromMinutes(y[0]); if (Match(units, Keywords.w_HOURS)) return TimeSpan.FromHours(y[0]); if (Match(units, Keywords.w_DAYS)) return TimeSpan.FromDays(y[0]); } // Convert hh:mm:ss format to decimal hours if (n > 1) y[0] = y[0] + y[1] / 60.0 + y[2] / 3600.0; // If am/pm attached then adjust hour accordingly // (12 am is midnight, 12 pm is noon) if (string.IsNullOrEmpty(units)) return TimeSpan.FromHours(y[0]); if (units.Equals(Keywords.w_AM, StringComparison.OrdinalIgnoreCase)) { if (y[0] >= 13.0) return TimeSpan.MinValue; if (y[0] >= 12.0) return TimeSpan.FromHours(y[0] - 12.0); return TimeSpan.FromHours(y[0]); } if (units.Equals(Keywords.w_PM, StringComparison.OrdinalIgnoreCase)) { if (y[0] >= 13.0) return TimeSpan.MinValue; if (y[0] >= 12.0) return TimeSpan.FromHours(y[0]); return TimeSpan.FromHours(y[0] + 12.0); } return TimeSpan.MinValue; } public static string GetClockTime(this TimeSpan ts) => string.Format("{0:00}:{1:00}:{2:00}", (int)ts.TotalHours, ts.Minutes, ts.Seconds); ///Get value signal, if bigger than 0 returns 1, -1 otherwise. /// Any real number. /// -1 or 1 public static double Sign(this double val) => val < 0 ? -1d : 1d; public static void Reverse(this LinkedList linkedList) { if (linkedList == null || linkedList.Count < 2) return; LinkedListNode next; var head = linkedList.First; while ((next = head.Next) != null) { linkedList.Remove(next); linkedList.AddFirst(next.Value); } } public static bool ToDouble(this string s, out double result) { return double.TryParse( s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.InvariantInfo, out result); } private const double DOUBLE_EPSILON = double.Epsilon * 100; public static bool IsZero(this double value) { return Math.Abs(value) < DOUBLE_EPSILON; } public static bool EqualsTo(this double value, double other) { return Math.Abs(value - other) < DOUBLE_EPSILON; } public static bool IsZero(this TimeSpan value) { return value.Ticks == 0L; } } }