Skip to content
This repository has been archived by the owner on Jul 5, 2023. It is now read-only.

Implemented Length type #63 #68

Merged
merged 6 commits into from
Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 19 additions & 48 deletions src/Nox.Types/Common/MeasurementConversionFactor.cs
rochar marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,66 +1,37 @@
using System;
using System.Linq;
using System.Collections.Generic;

namespace Nox.Common;

public class MeasurementConversionFactor
internal sealed class MeasurementConversionFactor
{
private const string Foot = "Foot";
private const string Meter = "Meter";
private const string Kilometer = "Kilometer";
private const string Mile = "Mile";
private static readonly string[] _lengthUnits = new[] { Foot, Meter, Kilometer, Mile };

private const string SquareFoot = "SquareFoot";
private const string SquareMeter = "SquareMeter";
private static readonly string[] _areaUnits = new[] { SquareFoot, SquareMeter };
private static readonly Dictionary<(MeasurementTypeUnit, MeasurementTypeUnit), double> DefinedConversionFactors = new()
{
{ (MeasurementTypeUnit.Foot, MeasurementTypeUnit.Meter), 0.30480000033},
{ (MeasurementTypeUnit.Meter, MeasurementTypeUnit.Foot), 3.28083989142},
{ (MeasurementTypeUnit.Kilometer, MeasurementTypeUnit.Mile), 0.62137119102},
{ (MeasurementTypeUnit.Mile, MeasurementTypeUnit.Kilometer), 1.60934400315},
{ (MeasurementTypeUnit.SquareFoot, MeasurementTypeUnit.SquareMeter), 0.09290304},
{ (MeasurementTypeUnit.SquareMeter, MeasurementTypeUnit.SquareFoot), 10.76391042},
};

public double Value { get; }

public MeasurementConversionFactor(Enum sourceUnit, Enum targetUnit)
: this(sourceUnit.ToString(), targetUnit.ToString())
public MeasurementConversionFactor(MeasurementTypeUnit sourceUnit, MeasurementTypeUnit targetUnit)
{
Value = ResolveConversionFactor(sourceUnit, targetUnit);
}

public MeasurementConversionFactor(string sourceUnit, string targetUnit)
private static double ResolveConversionFactor(MeasurementTypeUnit sourceUnit, MeasurementTypeUnit targetUnit)
{
Value = ResolveConversionFactor(sourceUnit, targetUnit)
?? throw new NotImplementedException($"No conversion defined from {sourceUnit} to {targetUnit}.");
}
var conversion = (sourceUnit, targetUnit);

private double? ResolveConversionFactor(string sourceUnit, string targetUnit)
{
return IsSupported(sourceUnit) && IsSupported(targetUnit)
? ResolveConversionFactorForSupportedUnits(sourceUnit, targetUnit)
: null;
}
if (DefinedConversionFactors.ContainsKey(conversion))
return DefinedConversionFactors[conversion];

private bool IsSupported(string unit)
=> _lengthUnits.Contains(unit) || _areaUnits.Contains(unit);

private double? ResolveConversionFactorForSupportedUnits(string sourceUnit, string targetUnit)
{
if (sourceUnit == targetUnit)
else if (sourceUnit == targetUnit)
return 1;

else if (sourceUnit == Foot && targetUnit == Meter)
return 0.30480000033;

else if (sourceUnit == Meter && targetUnit == Foot)
return 3.28083989142;

else if (sourceUnit == Kilometer && targetUnit == Mile)
return 0.62137119102;

else if (sourceUnit == Mile && targetUnit == Kilometer)
return 1.60934400315;

else if (sourceUnit == SquareFoot && targetUnit == SquareMeter)
return 0.09290304;

else if (sourceUnit == SquareMeter && targetUnit == SquareFoot)
return 10.76391042;

return null;
throw new NotImplementedException($"No conversion defined from {sourceUnit} to {targetUnit}.");
}
}
14 changes: 14 additions & 0 deletions src/Nox.Types/Common/MeasurementTypeUnit.cs
rochar marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Nox.Common;

internal enum MeasurementTypeUnit
{
// Length
Foot = 1,
Meter = 2,
Kilometer = 3,
Mile = 4,

// Area
SquareFoot = 5,
SquareMeter = 6,
}
1 change: 1 addition & 0 deletions src/Nox.Types/Nox.Types.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@
</PropertyGroup>
<ItemGroup>
<None Include="..\..\images\nox.png" Pack="true" PackagePath="" />
<InternalsVisibleTo Include="Nox.Types.Tests" />
</ItemGroup>
</Project>
14 changes: 12 additions & 2 deletions src/Nox.Types/Types/Area/Area.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Nox.Common;
using System;
using System.Collections.Generic;
using System.Globalization;

namespace Nox.Types;

Expand Down Expand Up @@ -92,7 +93,16 @@ internal override ValidationResult Validate()
return result;
}

public override string ToString() => $"{Value:G} {Unit.ToSymbol()}";
public override string ToString()
=> $"{Value.ToString($"0.{new string('#', QuantityValueDecimalPrecision)}", CultureInfo.InvariantCulture)} {Unit.ToSymbol()}";

/// <summary>
/// Returns a string representation of the <see cref="Length"/> object using the specified <see cref="IFormatProvider"/>.
/// </summary>
/// <param name="formatProvider">The format provider for the length value.</param>
/// <returns>A string representation of the <see cref="Length"/> object with the value formatted using the specified <see cref="IFormatProvider"/>.</returns>
public string ToString(IFormatProvider formatProvider)
=> $"{Value.ToString(formatProvider)} {Unit.ToSymbol()}";

protected override IEnumerable<KeyValuePair<string, object>> GetEqualityComponents()
{
Expand All @@ -107,7 +117,7 @@ protected override IEnumerable<KeyValuePair<string, object>> GetEqualityComponen

private QuantityValue GetAreaIn(AreaTypeUnit targetUnit)
{
var factor = new MeasurementConversionFactor(Unit, targetUnit).Value;
var factor = new MeasurementConversionFactor((MeasurementTypeUnit)Unit, (MeasurementTypeUnit)targetUnit).Value;
return Round(Value * factor);
}

Expand Down
4 changes: 2 additions & 2 deletions src/Nox.Types/Types/Area/AreaTypeUnit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ namespace Nox.Types;

public enum AreaTypeUnit
{
SquareFoot,
SquareMeter,
SquareFoot = 5,
SquareMeter = 6,
}

public static class AreaTypeUnitExtensions
Expand Down
14 changes: 12 additions & 2 deletions src/Nox.Types/Types/Distance/Distance.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Nox.Common;
using System;
using System.Collections.Generic;
using System.Globalization;

namespace Nox.Types;

Expand Down Expand Up @@ -113,7 +114,16 @@ protected override IEnumerable<KeyValuePair<string, object>> GetEqualityComponen
yield return new KeyValuePair<string, object>(nameof(Value), ToKilometers());
}

public override string ToString() => $"{Value:G} {Unit.ToSymbol()}";
public override string ToString()
=> $"{Value.ToString($"0.{new string('#', QuantityValueDecimalPrecision)}", CultureInfo.InvariantCulture)} {Unit.ToSymbol()}";

/// <summary>
/// Returns a string representation of the <see cref="Length"/> object using the specified <see cref="IFormatProvider"/>.
/// </summary>
/// <param name="formatProvider">The format provider for the length value.</param>
/// <returns>A string representation of the <see cref="Length"/> object with the value formatted using the specified <see cref="IFormatProvider"/>.</returns>
public string ToString(IFormatProvider formatProvider)
=> $"{Value.ToString(formatProvider)} {Unit.ToSymbol()}";

private QuantityValue? _kilometers;

Expand All @@ -125,7 +135,7 @@ protected override IEnumerable<KeyValuePair<string, object>> GetEqualityComponen

private QuantityValue GetDistanceIn(DistanceTypeUnit targetUnit)
{
var factor = new MeasurementConversionFactor(Unit, targetUnit).Value;
var factor = new MeasurementConversionFactor((MeasurementTypeUnit)Unit, (MeasurementTypeUnit)targetUnit).Value;
return Round(Value * factor);
}

Expand Down
4 changes: 2 additions & 2 deletions src/Nox.Types/Types/Distance/DistanceTypeUnit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ namespace Nox.Types;

public enum DistanceTypeUnit
{
Kilometer,
Mile
Kilometer = 3,
Mile = 4,
}

public static class DistanceTypeUnitExtensions
Expand Down
16 changes: 12 additions & 4 deletions src/Nox.Types/Types/Length/Length.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Nox.Common;
using System;
using System.Collections.Generic;
using System.Globalization;

namespace Nox.Types;

Expand Down Expand Up @@ -75,7 +76,7 @@ internal override ValidationResult Validate()
{
var result = Value.Validate();

if (Value < 0)
if (Value < 0 && !double.IsNaN((double)Value) && !double.IsInfinity((double)Value))
rochar marked this conversation as resolved.
Show resolved Hide resolved
{
result.Errors.Add(new ValidationFailure(nameof(Value), $"Could not create a Nox Length type as negative length value {Value} is not allowed."));
}
Expand All @@ -93,9 +94,16 @@ protected override IEnumerable<KeyValuePair<string, object>> GetEqualityComponen
yield return new KeyValuePair<string, object>(nameof(Value), ToMeters());
}


public override string ToString()
rochar marked this conversation as resolved.
Show resolved Hide resolved
=> $"{Value:G} {Unit.ToSymbol()}";
=> $"{Value.ToString($"0.{new string('#', QuantityValueDecimalPrecision)}", CultureInfo.InvariantCulture)} {Unit.ToSymbol()}";

/// <summary>
/// Returns a string representation of the <see cref="Length"/> object using the specified <see cref="IFormatProvider"/>.
/// </summary>
/// <param name="formatProvider">The format provider for the length value.</param>
/// <returns>A string representation of the <see cref="Length"/> object with the value formatted using the specified <see cref="IFormatProvider"/>.</returns>
public string ToString(IFormatProvider formatProvider)
=> $"{Value.ToString(formatProvider)} {Unit.ToSymbol()}";

private QuantityValue? _meters;

Expand All @@ -109,7 +117,7 @@ public QuantityValue ToFeet()

private QuantityValue GetLengthIn(LengthTypeUnit targetUnit)
{
var factor = new MeasurementConversionFactor(Unit, targetUnit).Value;
var factor = new MeasurementConversionFactor((MeasurementTypeUnit)Unit, (MeasurementTypeUnit)targetUnit).Value;
return Round(Value * factor);
}

Expand Down
4 changes: 2 additions & 2 deletions src/Nox.Types/Types/Length/LengthTypeUnit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ namespace Nox.Types;

public enum LengthTypeUnit
{
Foot,
Meter
Foot = 1,
Meter = 2,
}

public static class LengthTypeUnitExtensions
Expand Down
16 changes: 8 additions & 8 deletions tests/Nox.Types.Tests/Common/MeasurementConversionFactorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,55 +7,55 @@ public class MeasurementConversionFactorTests
[Fact]
public void MeasurementUnitConverter_GetConversionFactor_FromFootToMeter_ReturnsValue()
{
var factor = new MeasurementConversionFactor("Foot", "Meter");
var factor = new MeasurementConversionFactor(MeasurementTypeUnit.Foot, MeasurementTypeUnit.Meter);

Assert.Equal(0.30480000033, factor.Value);
rochar marked this conversation as resolved.
Show resolved Hide resolved
}

[Fact]
public void MeasurementUnitConverter_GetConversionFactor_FromMeterToFoot_ReturnsValue()
{
var factor = new MeasurementConversionFactor("Meter", "Foot");
var factor = new MeasurementConversionFactor(MeasurementTypeUnit.Meter, MeasurementTypeUnit.Foot);

Assert.Equal(3.28083989142, factor.Value);
}

[Fact]
public void MeasurementUnitConverter_GetConversionFactor_FromKilometerToMile_ReturnsValue()
{
var factor = new MeasurementConversionFactor("Kilometer", "Mile");
var factor = new MeasurementConversionFactor(MeasurementTypeUnit.Kilometer, MeasurementTypeUnit.Mile);

Assert.Equal(0.62137119102, factor.Value);
}

[Fact]
public void MeasurementUnitConverter_GetConversionFactor_FromMileToKilometer_ReturnsValue()
{
var factor = new MeasurementConversionFactor("Mile", "Kilometer");
var factor = new MeasurementConversionFactor(MeasurementTypeUnit.Mile, MeasurementTypeUnit.Kilometer);

Assert.Equal(1.60934400315, factor.Value);
}

[Fact]
public void MeasurementUnitConverter_GetConversionFactor_FromSquareFootToSquareMeter_ReturnsValue()
{
var factor = new MeasurementConversionFactor("SquareFoot", "SquareMeter");
var factor = new MeasurementConversionFactor(MeasurementTypeUnit.SquareFoot, MeasurementTypeUnit.SquareMeter);

Assert.Equal(0.09290304, factor.Value);
}

[Fact]
public void MeasurementUnitConverter_GetConversionFactor_FromSquareMeterToSquareFoot_ReturnsValue()
{
var factor = new MeasurementConversionFactor("SquareMeter", "SquareFoot");
var factor = new MeasurementConversionFactor(MeasurementTypeUnit.SquareMeter, MeasurementTypeUnit.SquareFoot);

Assert.Equal(10.76391042, factor.Value);
}

[Fact]
public void MeasurementUnitConverter_GetConversionFactor_WithSameSourceAndTargetUnit_ReturnsValue()
{
var factor = new MeasurementConversionFactor("Foot", "Foot");
var factor = new MeasurementConversionFactor(MeasurementTypeUnit.Foot, MeasurementTypeUnit.Foot);

Assert.Equal(1, factor.Value);
}
Expand All @@ -64,7 +64,7 @@ public void MeasurementUnitConverter_GetConversionFactor_WithSameSourceAndTarget
public void MeasurementUnitConverter_GetConversionFactor_WithUnsupportedConversion_ThrowsException()
{
var exception = Assert.Throws<NotImplementedException>(() => _ =
new MeasurementConversionFactor("SquareMeter", "Meter")
new MeasurementConversionFactor(MeasurementTypeUnit.SquareMeter, MeasurementTypeUnit.Meter)
);

Assert.Equal("No conversion defined from SquareMeter to Meter.", exception.Message);
Expand Down
Loading