//############################################################################// // RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION // PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS // AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO // UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO // RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS // CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS // OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON // COMPANY. // // THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT // // UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. // // WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE // EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED // BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION // 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION // 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER // OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER // LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS // BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT // APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL // PENALTIES. // // DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 : // FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R, // INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS // DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR // RECONSTRUCTION OF THE DOCUMENT. //############################################################################// using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.Serialization; using System.Text; namespace Raytheon.Units { /// /// This class represents a Flow Rate. /// /// It has no constructors. Instead, it provides multiple methods for creating objects of this /// type. Those methods are of the form FromXXX, where XXX is a unit (e.g. FromCubicMetersPerSecond). /// /// Properties (e.g. CubicMetersPerSecond) are provided to convert the value to other units and return /// as type double. /// [Serializable] [DataContract] public class FlowRate { public enum Unit { CubicMetersPerSecond, CubicMetersPerMinute, CubicMetersPerHour, GallonsPerMinute } public static IDictionary> UnitAbbreviations = new Dictionary>() { {Unit.CubicMetersPerSecond, new List(){ "m^3/s" } }, {Unit.CubicMetersPerMinute, new List(){ "m^3/min" } }, {Unit.CubicMetersPerHour, new List(){ "m^3/h" } }, {Unit.GallonsPerMinute, new List(){ "gal/min" } }, }; private const Unit DefaultUnits = Unit.CubicMetersPerSecond; private const double CubicMetersToGalPerSecMultipler = 15850; private const int SecondsPerMinute = 60; private const int SecondsPerHour = 3600; [DataMember(Name = "CubicMetersPerSecond", IsRequired = true)] private readonly double _flowRate; // map: unit => abbreviation, conversion method and property private static readonly IDictionary> _unitInfo = new Dictionary>() { { Unit.CubicMetersPerSecond, new UnitInfo(UnitAbbreviations[Unit.CubicMetersPerSecond], FromCubicMetersPerSecond, typeof(FlowRate).GetProperty("CubicMetersPerSecond").GetGetMethod()) }, { Unit.CubicMetersPerMinute, new UnitInfo(UnitAbbreviations[Unit.CubicMetersPerMinute], FromCubicMetersPerMinute, typeof(FlowRate).GetProperty("CubicMetersPerMinute").GetGetMethod()) }, { Unit.CubicMetersPerHour, new UnitInfo(UnitAbbreviations[Unit.CubicMetersPerHour], FromCubicMetersPerHour, typeof(FlowRate).GetProperty("CubicMetersPerHour").GetGetMethod()) }, { Unit.GallonsPerMinute, new UnitInfo(UnitAbbreviations[Unit.GallonsPerMinute], FromGallonsPerMinute, typeof(FlowRate).GetProperty("GallonsPerMinute").GetGetMethod()) } }; /// /// Prevents a default instance of the class from being created /// Use FromXXX methods to create objects of this type. /// private FlowRate() { throw new InvalidOperationException("No one should be calling this, it is only here to prevent users from creating default object"); } /// /// Constructor used by this class to create objects in FromXXX methods. /// /// The flow rate - Cubic Meters per second private FlowRate(double cubicMetersPerSecond) { _flowRate = cubicMetersPerSecond; } #region conversion properties /// /// Returns Cubic Meters Per Second as type double /// public double CubicMetersPerSecond { get { return _flowRate; } } /// /// Returns Cubic Meters Per Minutes as type double /// public double CubicMetersPerMinute { get { return _flowRate * SecondsPerMinute; } } /// /// Returns Cubic Meters Per Hour as type double /// public double CubicMetersPerHour { get { return _flowRate * SecondsPerHour; } } /// /// Returns Gallons Per Minute /// public double GallonsPerMinute { get { return _flowRate * CubicMetersToGalPerSecMultipler; } } #endregion #region Creation Methods /// /// Returns FlowRate object interpreting passed value as Cubic Meters Per Second /// /// Cubic Meters Per Second /// public static FlowRate FromCubicMetersPerSecond(double m3PerSec) { return new FlowRate(m3PerSec); } public static FlowRate FromCubicMetersPerMinute(double m3PerMin) { return new FlowRate(m3PerMin / SecondsPerMinute); } public static FlowRate FromCubicMetersPerHour(double m3PerHr) { return new FlowRate(m3PerHr / SecondsPerHour); } public static FlowRate FromGallonsPerMinute(double gallonPerMin) { return new FlowRate(gallonPerMin / CubicMetersToGalPerSecMultipler); } #endregion public override bool Equals(object obj) { FlowRate flowRate = obj as FlowRate; return (flowRate == null) ? false : (this._flowRate == flowRate._flowRate); } public override int GetHashCode() { return _flowRate.GetHashCode(); } #region Binary Operators // not implementing %, &, |, ^, <<, >> public static FlowRate operator +(FlowRate left, FlowRate right) { if (null == left) { throw new ArgumentNullException("left", "Cannot add a null Flow Rate"); } if (null == right) { throw new ArgumentNullException("right", "Cannot add null Flow Rate"); } return new FlowRate(left._flowRate + right._flowRate); } public static FlowRate operator *(FlowRate flowRate, double scalar) { if (null == flowRate) { throw new ArgumentNullException("flowRate", "Cannot multiply a null Flow Rate"); } return new FlowRate(flowRate._flowRate * scalar); } public static FlowRate operator *(double scalar, FlowRate flowRate) { if (null == flowRate) { throw new ArgumentNullException("flowRate", "Cannot multiply a null Flow Rate"); } return new FlowRate(scalar * flowRate._flowRate); } public static FlowRate operator /(FlowRate flowRate, double scalar) { if (null == flowRate) { throw new ArgumentNullException("flowRate", "Cannot divide a null Flow Rate"); } if (0.0 == scalar) { throw new DivideByZeroException("Cannot divide Flow Rate by 0"); } return new FlowRate(flowRate._flowRate / scalar); } #endregion #region comparison operators public static bool operator ==(FlowRate left, FlowRate right) { bool bReturn = false; if (object.ReferenceEquals(left, null)) { if (object.ReferenceEquals(right, null)) { //both are null, so we are == bReturn = true; } } else { if (!object.ReferenceEquals(left, null) && !object.ReferenceEquals(right, null)) { bReturn = left._flowRate == right._flowRate; } } return bReturn; } public static bool operator !=(FlowRate left, FlowRate right) { return !(left == right); } public static bool operator <(FlowRate left, FlowRate right) { if (null == left) { throw new ArgumentNullException("left", "Cannot compare null Flow Rate"); } if (null == right) { throw new ArgumentNullException("right", "Cannot compare null Flow Rate"); } return (left._flowRate < right._flowRate); } public static bool operator >(FlowRate left, FlowRate right) { if (null == left) { throw new ArgumentNullException("left", "Cannot compare null Flow Rate"); } if (null == right) { throw new ArgumentNullException("right", "Cannot compare null Flow Rate"); } return (left._flowRate > right._flowRate); } public static bool operator <=(FlowRate left, FlowRate right) { if (null == left) { throw new ArgumentNullException("left", "Cannot compare null Flow Rate"); } if (null == right) { throw new ArgumentNullException("right", "Cannot compare null Flow Rate"); } return (left._flowRate <= right._flowRate); } public static bool operator >=(FlowRate left, FlowRate right) { if (null == left) { throw new ArgumentNullException("left", "Cannot compare null Flow Rate"); } if (null == right) { throw new ArgumentNullException("right", "Cannot compare null Flow Rate"); } return (left._flowRate >= right._flowRate); } #endregion #region parsing public static FlowRate Parse(string s) { return Common.Parse(s, _unitInfo); } public static bool TryParse(string s, out FlowRate value) { try { value = FlowRate.Parse(s); return true; } catch (Exception) { value = null; return false; } } #endregion /// /// Returns a appended with units symbol (e.g. "1.23 M^3/s"). /// /// /// A that represents this instance. /// public override string ToString() { return ToString(DefaultUnits); } /// /// overload that returns a string appended with specified units (e.g. "1.23 ft/sec^2"). /// /// /// public string ToString(Unit units) { double value = (double)_unitInfo[units].PropertyGetter.Invoke(this, null); return $"{value} {_unitInfo[units].Abbreviation[0]}"; } } }