namespace Jint.Tests.Runtime.Domain { public class Dimensional : IComparable, IEquatable { private readonly MeasureUnit[] PossibleMeasureUnits = new MeasureUnit[] { new MeasureUnit("Mass", "kg", 1.0), new MeasureUnit("Mass", "gr", 0.001), new MeasureUnit("Count", "piece", 1.0) }; public MeasureUnit MeasureUnit { get; private set; } public double Value { get; private set; } public double NormalizatedValue { get { return Value * MeasureUnit.RelativeValue; } } public Dimensional(string measureUnit, double value) { MeasureUnit = GetMeasureUnitByName(measureUnit); Value = value; } public static Dimensional operator +(Dimensional left, Dimensional right) { if (left.MeasureUnit.MeasureType != right.MeasureUnit.MeasureType) throw new InvalidOperationException("Dimensionals with different measure types are non-summable"); return new Dimensional(left.MeasureUnit.RelativeValue <= right.MeasureUnit.RelativeValue ? left.MeasureUnit.Name : right.MeasureUnit.Name, left.Value * left.MeasureUnit.RelativeValue + right.Value * right.MeasureUnit.RelativeValue); } private MeasureUnit GetMeasureUnitByName(string name) { return PossibleMeasureUnits.FirstOrDefault(mu => mu.Name == name); } public int CompareTo(Dimensional obj) { if (MeasureUnit.MeasureType != obj.MeasureUnit.MeasureType) throw new InvalidOperationException("Dimensionals with different measure types are non-comparable"); return NormalizatedValue.CompareTo(obj.NormalizatedValue); } public override string ToString() { return Value + " " + MeasureUnit.Name; } public bool Equals(Dimensional other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return Value.Equals(other.Value) && Equals(MeasureUnit, other.MeasureUnit); } public override bool Equals(object obj) { return Equals(obj as Dimensional); } public override int GetHashCode() { return Value.GetHashCode(); } } public class MeasureUnit : IEquatable { public string MeasureType { get; set; } public string Name { get; set; } public double RelativeValue { get; set; } public MeasureUnit(string measureType, string name, double relativeValue) { this.MeasureType = measureType; this.Name = name; this.RelativeValue = relativeValue; } public bool Equals(MeasureUnit other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return MeasureType == other.MeasureType && Name == other.Name && RelativeValue.Equals(other.RelativeValue); } public override bool Equals(object obj) { return Equals(obj as MeasureUnit); } public override int GetHashCode() { return MeasureType.GetHashCode() ^ Name.GetHashCode() ^ RelativeValue.GetHashCode(); } } }