Skip to content

Commit

Permalink
Merge pull request #68 from WildernessLabs/feature/flow
Browse files Browse the repository at this point in the history
add volumetric flow
  • Loading branch information
adrianstevens authored Jan 2, 2025
2 parents cc93092 + ac033ad commit eb6b5d5
Show file tree
Hide file tree
Showing 3 changed files with 294 additions and 10 deletions.
24 changes: 24 additions & 0 deletions Source/Meadow.Units/Conversions/VolumetricFlowConversions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace Meadow.Units.Conversions;

internal static class VolumetricFlowConversions
{
public static double Convert(double value, VolumetricFlow.UnitType from, VolumetricFlow.UnitType to)
{
if (from == to)
{
return value;
}
return value * flowConversions[(int)to] / flowConversions[(int)from];
}

//must align to enum
private static readonly double[] flowConversions =
{
1.0, // CubicMetersPerSecond (SI unit)
2118.88, // CubicFeetPerMinute
60000, // LitersPerMinute
3600000, // LitersPerHour
15850.3, // GallonsPerMinute
951018, // GallonsPerHour
};
}
34 changes: 24 additions & 10 deletions Source/Meadow.Units/Frequency.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System;
using Meadow.Units.Conversions;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Runtime.InteropServices;
using Meadow.Units.Conversions;

namespace Meadow.Units;

Expand All @@ -17,6 +17,18 @@ public struct Frequency :
IComparable, IFormattable, IConvertible,
IEquatable<double>, IComparable<double>
{
private static Frequency _zero;

static Frequency()
{
_zero = new Frequency(0, UnitType.Hertz);
}

/// <summary>
/// Gets a length with a value of zero
/// </summary>
public static Frequency Zero => _zero;

/// <summary>
/// Creates a new <see cref="Frequency"/> object.
/// </summary>
Expand Down Expand Up @@ -78,7 +90,8 @@ public enum UnitType
/// </summary>
/// <param name="convertTo">unit to covert to</param>
/// <returns>the converted value</returns>
[Pure] public double From(UnitType convertTo)
[Pure]
public double From(UnitType convertTo)
{
return FrequencyConversions.Convert(Value, UnitType.Hertz, convertTo);
}
Expand Down Expand Up @@ -176,37 +189,37 @@ [Pure] public double From(UnitType convertTo)
/// <param name="left">left value</param>
/// <param name="right">right value</param>
/// <returns>A new Frequency object with a value of left + right</returns>
[Pure] public static Frequency operator +(Frequency left, Frequency right) => new (left.Value + right.Value);
[Pure] public static Frequency operator +(Frequency left, Frequency right) => new(left.Value + right.Value);

/// <summary>
/// Subtraction operator to subtract two Frequency objects
/// </summary>
/// <param name="left">left value</param>
/// <param name="right">right value</param>
/// <returns>A new Frequency object with a value of left - right</returns>
[Pure] public static Frequency operator -(Frequency left, Frequency right) => new (left.Value - right.Value);
[Pure] public static Frequency operator -(Frequency left, Frequency right) => new(left.Value - right.Value);

/// <summary>
/// Multiplication operator to multiply by a double
/// </summary>
/// <param name="value">object to multiply</param>
/// <param name="operand">operand to multiply object</param>
/// <returns>A new Frequency object with a value of value multiplied by the operand</returns>
[Pure] public static Frequency operator *(Frequency value, double operand) => new (value.Value * operand);
[Pure] public static Frequency operator *(Frequency value, double operand) => new(value.Value * operand);

/// <summary>
/// Division operator to divide by a double
/// </summary>
/// <param name="value">object to be divided</param>
/// <param name="operand">operand to divide object</param>
/// <returns>A new Frequency object with a value of value divided by the operand</returns>
[Pure] public static Frequency operator /(Frequency value, double operand) => new (value.Value / operand);
[Pure] public static Frequency operator /(Frequency value, double operand) => new(value.Value / operand);

/// <summary>
/// Returns the absolute value of the <see cref="Frequency"/>
/// </summary>
/// <returns></returns>
[Pure] public Frequency Abs() => new (Math.Abs(Value));
[Pure] public Frequency Abs() => new(Math.Abs(Value));

/// <summary>
/// Get a string representation of the object
Expand All @@ -228,7 +241,7 @@ [Pure] public double From(UnitType convertTo)
/// </summary>
/// <param name="obj">The other Frequency cast to object</param>
/// <returns>0 if equal</returns>
[Pure]
[Pure]
public int CompareTo(object obj)
{
if (obj is Frequency frequency)
Expand Down Expand Up @@ -363,7 +376,8 @@ public int CompareTo(object obj)
/// </summary>
/// <param name="other">value to compare</param>
/// <returns>0 if equal</returns>
[Pure] public int CompareTo(double? other)
[Pure]
public int CompareTo(double? other)
{
return (other is null) ? -1 : (Value).CompareTo(other.Value);
}
Expand Down
246 changes: 246 additions & 0 deletions Source/Meadow.Units/VolumetricFlow.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
using Meadow.Units.Conversions;
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;

namespace Meadow.Units;

/// <summary>
/// Represents a volumetric flow measurement.
/// Implements standard interfaces for comparison, formatting, and conversion operations.
/// </summary>
public struct VolumetricFlow :
IComparable, IFormattable
{
private static VolumetricFlow _zero;

static VolumetricFlow()
{
_zero = new VolumetricFlow(0, UnitType.CubicMetersPerSecond);
}

/// <summary>
/// Gets a flow of 0
/// </summary>
public static VolumetricFlow Zero => _zero;

/// <summary>
/// Creates a new <see cref="VolumetricFlow"/> object.
/// </summary>
/// <param name="value">The VolumetricFlow value.</param>
/// <param name="type">CubicMetersPerSecond by default.</param>
public VolumetricFlow(double value, UnitType type = UnitType.CubicMetersPerSecond)
{
Value = VolumetricFlowConversions.Convert(value, type, UnitType.CubicMetersPerSecond);
}

/// <summary>
/// Creates a new <see cref="VolumetricFlow"/> object from an existing VolumetricFlow object
/// </summary>
/// <param name="flow"></param>
public VolumetricFlow(VolumetricFlow flow)
{
Value = flow.Value;
}

/// <summary>
/// Internal canonical value.
/// </summary>
private readonly double Value;

/// <summary>
/// The type of units available to describe the VolumetricFlow.
/// </summary>
public enum UnitType
{
/// <summary>CubicMetersPerSecond</summary>
CubicMetersPerSecond,
/// <summary>CubicFeetPerMinute</summary>
CubicFeetPerMinute,
/// <summary>LitersPerMinute</summary>
LitersPerMinute,
/// <summary>LitersPerHour</summary>
LitersPerHour,
/// <summary>GallonsPerMinute</summary>
GallonsPerMinute,
/// <summary>GallonsPerHour</summary>
GallonsPerHour,
}

/// <summary>
/// Gets the flow rate in cubic meters per second (m³/s).
/// </summary>
public double CubicMetersPerSecond => From(UnitType.CubicMetersPerSecond);

/// <summary>
/// Gets the flow rate in cubic feet per minute (CFM).
/// </summary>
public double CubicFeetPerMinute => From(UnitType.CubicFeetPerMinute);

/// <summary>
/// Gets the flow rate in liters per minute (L/min).
/// </summary>
public double LitersPerMinute => From(UnitType.LitersPerMinute);

/// <summary>
/// Gets the flow rate in liters per hour (L/h).
/// </summary>
public double LitersPerHour => From(UnitType.LitersPerHour);

/// <summary>
/// Gets the flow rate in gallons per minute (GPM).
/// </summary>
public double GallonsPerMinute => From(UnitType.GallonsPerMinute);

/// <summary>
/// Gets the flow rate in gallons per hour (GPH).
/// </summary>
public double GallonsPerHour => From(UnitType.GallonsPerHour);

/// <summary>
/// Get a double value for a specific unit
/// </summary>
/// <param name="convertTo">unit to covert to</param>
/// <returns>the converted value</returns>
[Pure]
public double From(UnitType convertTo)
{
return VolumetricFlowConversions.Convert(Value, UnitType.CubicMetersPerSecond, convertTo);
}

/// <summary>
/// Determines whether the specified object is equal to the current unit.
/// </summary>
/// <param name="obj">The object to compare with the current unit.</param>
/// <returns>true if the specified object is equal to the current unit; otherwise, false.</returns>
[Pure] public override bool Equals(object obj) => CompareTo(obj) == 0;

/// <summary>
/// Returns the hash code for this unit.
/// </summary>
/// <returns>A hash code value generated from the underlying numerical value.</returns>
[Pure] public override int GetHashCode() => Value.GetHashCode();

/// <summary>
/// Determines whether the specified unit is equal to the current unit.
/// </summary>
/// <param name="other">The unit to compare with the current unit.</param>
/// <returns>true if the units are equal; otherwise, false.</returns>
[Pure] public bool Equals(VolumetricFlow other) => Value == other.Value;

/// <summary>
/// Determines whether two units are equal.
/// </summary>
/// <param name="left">The first unit to compare.</param>
/// <param name="right">The second unit to compare.</param>
/// <returns>true if the units are equal; otherwise, false.</returns>
[Pure] public static bool operator ==(VolumetricFlow left, VolumetricFlow right) => Equals(left.Value, right.Value);

/// <summary>
/// Determines whether two units are not equal.
/// </summary>
/// <param name="left">The first unit to compare.</param>
/// <param name="right">The second unit to compare.</param>
/// <returns>true if the units are not equal; otherwise, false.</returns>
[Pure] public static bool operator !=(VolumetricFlow left, VolumetricFlow right) => !Equals(left.Value, right.Value);

/// <summary>
/// Compares the current unit with another unit.
/// </summary>
/// <param name="other">The unit to compare with the current unit.</param>
/// <returns>A value that indicates the relative order of the units being compared. Returns 0 if equal,
/// less than 0 if less than the other value, or greater than 0 if greater than the other value.</returns>
[Pure] public int CompareTo(VolumetricFlow other) => Equals(Value, other.Value) ? 0 : Value.CompareTo(other.Value);

/// <summary>
/// Determines whether the first unit is less than the second unit.
/// </summary>
/// <param name="left">The first unit to compare.</param>
/// <param name="right">The second unit to compare.</param>
/// <returns>true if the first unit is less than the second unit; otherwise, false.</returns>
[Pure] public static bool operator <(VolumetricFlow left, VolumetricFlow right) => Comparer<double>.Default.Compare(left.Value, right.Value) < 0;

/// <summary>
/// Determines whether the first unit is greater than the second unit.
/// </summary>
/// <param name="left">The first unit to compare.</param>
/// <param name="right">The second unit to compare.</param>
/// <returns>true if the first unit is greater than the second unit; otherwise, false.</returns>
[Pure] public static bool operator >(VolumetricFlow left, VolumetricFlow right) => Comparer<double>.Default.Compare(left.Value, right.Value) > 0;

/// <summary>
/// Determines whether the first unit is less than or equal to the second unit.
/// </summary>
/// <param name="left">The first unit to compare.</param>
/// <param name="right">The second unit to compare.</param>
/// <returns>true if the first unit is less than or equal to the second unit; otherwise, false.</returns>
[Pure] public static bool operator <=(VolumetricFlow left, VolumetricFlow right) => Comparer<double>.Default.Compare(left.Value, right.Value) <= 0;

/// <summary>
/// Determines whether the first unit is greater than or equal to the second unit.
/// </summary>
/// <param name="left">The first unit to compare.</param>
/// <param name="right">The second unit to compare.</param>
/// <returns>true if the first unit is greater than or equal to the second unit; otherwise, false.</returns>
[Pure] public static bool operator >=(VolumetricFlow left, VolumetricFlow right) => Comparer<double>.Default.Compare(left.Value, right.Value) >= 0;

/// <summary>
/// Adds two volumetric flow values.
/// </summary>
/// <param name="left">The first value to add.</param>
/// <param name="right">The second value to add.</param>
/// <returns>The sum of the two volumetric flow values.</returns>
[Pure] public static VolumetricFlow operator +(VolumetricFlow left, VolumetricFlow right) => new(left.Value + right.Value);

/// <summary>
/// Subtracts one volumetric flow value from another.
/// </summary>
/// <param name="left">The value to subtract from.</param>
/// <param name="right">The value to subtract.</param>
/// <returns>The difference between the two volumetric flow values.</returns>
[Pure] public static VolumetricFlow operator -(VolumetricFlow left, VolumetricFlow right) => new(left.Value - right.Value);

/// <summary>
/// Multiplies a volumetric flow value by a scalar value.
/// </summary>
/// <param name="value">The volumetric flow value to multiply.</param>
/// <param name="operand">The scalar value to multiply by.</param>
/// <returns>The product of the volumetric flow and scalar values.</returns>
[Pure] public static VolumetricFlow operator *(VolumetricFlow value, double operand) => new(value.Value * operand);

/// <summary>
/// Divides a volumetric flow value by a scalar value.
/// </summary>
/// <param name="value">The volumetric flow value to divide.</param>
/// <param name="operand">The scalar value to divide by.</param>
/// <returns>The quotient of the volumetric flow value and scalar value.</returns>
[Pure] public static VolumetricFlow operator /(VolumetricFlow value, double operand) => new(value.Value / operand);

/// <summary>
/// Compares the current unit with another object.
/// </summary>
/// <param name="obj">The object to compare with the current unit.</param>
/// <returns>A value that indicates the relative order of the objects being compared.</returns>
/// <exception cref="ArgumentException">The object is not a VolumetricFlow.</exception>
[Pure]
public int CompareTo(object obj)
{
if (obj is VolumetricFlow VolumetricFlow)
{
return Value.CompareTo(VolumetricFlow.Value);
}
throw new ArgumentException("Object is not a VolumetricFlow");
}

/// <summary>
/// Returns the TypeCode for the underlying value type.
/// </summary>
/// <returns>The TypeCode for the underlying double value.</returns>
[Pure] public TypeCode GetTypeCode() => Value.GetTypeCode();

/// <inheritdoc/>
[Pure] public string ToString(string format, IFormatProvider formatProvider) => Value.ToString(format, formatProvider);
/// <inheritdoc/>
[Pure] public string ToString(IFormatProvider provider) => Value.ToString(provider);

}

0 comments on commit eb6b5d5

Please sign in to comment.