Innovenergy_trunk/csharp/Lib/Units/Units.cs

175 lines
4.7 KiB
C#

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<String>();
var visited = new HashSet<Object>();
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<Object>().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<String> Big = new[]
{
"",
"k",
"M",
"G",
"T",
"P",
"E",
"Y",
};
private static readonly IReadOnlyList<String> 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}";
}
}