using System.Collections; using System.Reflection; using InnovEnergy.Lib.Units.Power; using InnovEnergy.Lib.Utils; using static System.Reflection.BindingFlags; namespace InnovEnergy.Lib.Units; public static class Units { public static Byte DisplaySignificantDigits { get; set; } = 3; public static Byte JsonSignificantDigits { get; set; } = 3; public static Current A (this Double value) => value; public static Voltage V (this Double value) => value; public static ActivePower W (this Double value) => value; public static ReactivePower Var (this Double value) => value; public static ApparentPower Va (this Double value) => value; public static Resistance Ohm (this Double value) => value; public static Frequency Hz (this Double value) => value; public static Angle Rad (this Double value) => value; public static Temperature Celsius(this Double value) => value; public static Energy KWh (this Double value) => value; public static String ToCsv(this Object thing) { var csvLines = new List(); var visited = new HashSet(); GetCsv(thing); return csvLines.JoinLines(); void GetCsv(Object? parent, String path = "") { if (parent == null) return; var type = parent.GetType(); if (parent is Unit u) { csvLines.Add($"{path};{u.Value};{u.Symbol}"); // leaf: unit } else if (parent is String s) { csvLines.Add($"{path};{s};"); // leaf: unit } else if(type.IsEnum || (type.IsValueType && !type.IsNested)) { csvLines.Add($"{path};{parent};"); // leaf: value type } else if (parent is IEnumerable enumerable) { var enumerableType = enumerable.GetType(); var elementType = enumerableType.GetGenericArguments().SingleOrDefault() ?? enumerableType.GetElementType(); // for arrays if (elementType is null) return; if (elementType.IsValueType || elementType == typeof(String)) { var value = enumerable.Cast().JoinWith(","); csvLines.Add($"{path};{value};"); } else { var i = 1; foreach (var o in enumerable) GetCsv(o, $"{path}/{i++}"); } } else { if (!visited.Add(parent)) return; foreach (var p in type.GetProperties(Instance | Public)) { var name = p.Name; var value = p.GetValue(parent); GetCsv(value, $"{path}/{name}"); } } } } } public static class Prefixes { private static readonly IReadOnlyList Big = new[] { "", "k", "M", "G", "T", "P", "E", "Y", }; private static readonly IReadOnlyList Small = new[] { "", "m", "ยต", "n", "p", "f", "a", "z", "y", }; public static String TestGetPrefix(Double v, String unit) { if (v == 0) return ""; var log10 = Math.Log10(v / 10); var l = (Int32)Math.Floor(log10 / 3); var lookUp = l > 0 ? Big : Small; var i = Math.Abs(l); return $"{v / Math.Pow(10.0, l * 3.0)} {lookUp[i]}{unit}"; } public static String TestGetPrefix(Decimal v, String unit) { if (v == 0m) return ""; var d = (Double)v; var log10 = Math.Log10(d / 10); var l = (Int32)Math.Floor(log10 / 3); var lookUp = l > 0 ? Big : Small; var i = Math.Abs(l); return $"{d / Math.Pow(10.0, l * 3.0)} {lookUp[i]}{unit}"; } public static String TestGetPrefix2(Decimal v, String unit) { if (v == 0m) return ""; var a = Math.Abs(v); var s = Math.Sign(v); var i = 0; while (a >= 10000m) { a /= 1000; i++; } while (a < 10m) { a *= 1000; i--; } var lookUp = i >= 0 ? Big : Small; var r = Decimal.Floor(a * 10m) / 10m; return $"{r*s} {lookUp[Math.Abs(i)]}{unit}"; } }