From 7e58b78572fc041f41a7ca846796e8527630bc1b Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 8 Mar 2023 14:06:39 +0100 Subject: [PATCH] add new Unit: Energy (kWh) --- csharp/Lib/Units/Energy.cs | 15 +++++ csharp/Lib/Units/Energy.generated.cs | 97 ++++++++++++++++++++++++++++ csharp/Lib/Units/Power.cs | 4 +- 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 csharp/Lib/Units/Energy.cs create mode 100644 csharp/Lib/Units/Energy.generated.cs diff --git a/csharp/Lib/Units/Energy.cs b/csharp/Lib/Units/Energy.cs new file mode 100644 index 000000000..0f50ba858 --- /dev/null +++ b/csharp/Lib/Units/Energy.cs @@ -0,0 +1,15 @@ +using InnovEnergy.Lib.Units.Generator; + + +namespace InnovEnergy.Lib.Units; + +[Sum] +public readonly partial struct Energy +{ + public static String Unit => "kWh"; + public static String Symbol => "E"; + + public Energy(Decimal value) => Value = value; + + public static Power operator /(Energy energy, TimeSpan timeSpan) => energy.Value / (Decimal) timeSpan.TotalHours * 1000m; +} \ No newline at end of file diff --git a/csharp/Lib/Units/Energy.generated.cs b/csharp/Lib/Units/Energy.generated.cs new file mode 100644 index 000000000..90496238b --- /dev/null +++ b/csharp/Lib/Units/Energy.generated.cs @@ -0,0 +1,97 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +#define Sum + +using static System.Math; +using System.Text.Json; +using System.Text.Json.Serialization; +using InnovEnergy.Lib.Utils; + +namespace InnovEnergy.Lib.Units; + +using T = Energy; + +[JsonConverter(typeof(EnergyConverter))] +public readonly partial struct Energy +{ + public Decimal Value { get; } + public override String ToString() => Value.RoundToSignificantDigits(Units.DisplaySignificantDigits) + Unit; + + // scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + // parallel + + #if Sum + + public static T operator |(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T t) => new T(-t.Value); + + #elif Mean + + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); + + #elif Equal + + public static T operator |(T left, T right) + { + var d = Max(Abs(left.Value), Abs(right.Value)); + + if (d == 0m) + return new T(0m); + + var relativeError = Abs(left.Value - right.Value) / d; + + const Decimal maxRelativeError = 0.05m; + + if (relativeError > maxRelativeError) + throw new Exception($"{nameof(left)} and {nameof(right)} must be approximately equal.\n" + + $"Difference > {maxRelativeError * 100}% detected\n" + + $"{nameof(left)} : {left}\n" + + $"{nameof(right)}: {right}"); + + return new T((left.Value + right.Value) / 2m); + } + #endif + + // compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + // conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + // equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + +} + + +internal class EnergyConverter : JsonConverter +{ + public override Energy Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new Energy(reader.GetDecimal()); + } + + public override void Write(Utf8JsonWriter writer, Energy value, JsonSerializerOptions options) + { + var rounded = value.Value.RoundToSignificantDigits(Units.JsonSignificantDigits); + + writer.WriteNumberValue(rounded); + } +} \ No newline at end of file diff --git a/csharp/Lib/Units/Power.cs b/csharp/Lib/Units/Power.cs index 00d8b01c1..eb58ffeb3 100644 --- a/csharp/Lib/Units/Power.cs +++ b/csharp/Lib/Units/Power.cs @@ -14,5 +14,7 @@ public readonly partial struct Power // P=UI public static Voltage operator /(Power power, Current current) => new Voltage(power.Value / current.Value); public static Current operator /(Power power, Voltage voltage) => new Current(power.Value / voltage.Value); - + + public static Energy operator *(Power power, TimeSpan timeSpan) => power.Value / 1000m * (Decimal) timeSpan.TotalHours; + public static Energy operator *(TimeSpan timeSpan, Power power) => power.Value / 1000m * (Decimal) timeSpan.TotalHours; } \ No newline at end of file