/// <summary> /// Determine if this instance of PQ semantically equals another /// instance of a data type. /// </summary> public override BL SemanticEquals(IAny other) { // Base equality var baseEq = base.SemanticEquals(other); if (!(bool)baseEq) { return(baseEq); } // Values are equal? PQ pqOther = other as PQ; if (pqOther == null) { return(false); } else if (this.Value.HasValue && pqOther.Value.HasValue) { return(pqOther.Convert(this.Unit).Value.Value == this.Value.Value); } else if (this.UncertainRange != null && !this.UncertainRange.IsNull && pqOther.UncertainRange != null && !pqOther.UncertainRange.IsNull) { return(this.UncertainRange.Equals(pqOther.UncertainRange)); } return(false); }
/// <summary> /// Compares this PQ to another PQ /// </summary> /// <exception cref="T:System.ArgumentException">When the units of both PQ instances do not match</exception> public int CompareTo(PQ other) { if (other == null || other.IsNull) { return(1); } else if (this.IsNull && !other.IsNull) { return(-1); } else if (this.Value.HasValue && !other.Value.HasValue) { return(1); } else if (other.Value.HasValue && !this.Value.HasValue) { return(-1); } else if (!other.Value.HasValue && !this.Value.HasValue) { return(0); } else if (!this.IsUnitComparable(other.Unit)) { throw new ArgumentException("Units must match to compare PQ"); } else { return(this.Value.Value.CompareTo(other.Convert(this.Unit).Value.Value)); } }
/// <summary> /// Gets the number of days (total) between <paramref name="a"/> /// and <paramref name="b"/> /// </summary> internal static PQ GetLeapDays(TS a, TS b) { if (a == null || b == null) { return(null); } PQ retVal = new PQ(0, "d"); TS low = a, high = b; int val = 1; if (a.CompareTo(b) > 0) { low = b; high = a; val = -1; } for (int i = low.DateValue.Year; i < high.DateValue.Year; i++) { if (DateTime.IsLeapYear(i)) { retVal += new PQ(val, "d"); } } return(retVal); }
/// <summary> /// Validate the data type and return the validation errors detected /// </summary> public override IEnumerable <IResultDetail> ValidateEx() { List <IResultDetail> retVal = new List <IResultDetail>(base.ValidateEx()); if (this.Offset != null) { if (this.Offset.Low != null && !this.Offset.Low.IsNull && !PQ.IsValidTimeFlavor(this.Offset.Low)) { retVal.Add(new DatatypeValidationResultDetail(ResultDetailType.Error, "EIVL", "When populated, the Offset.Low property must contain a valid PQ.TIME instance", null)); } if (this.Offset.High != null && !this.Offset.High.IsNull && !PQ.IsValidTimeFlavor(this.Offset.High)) { retVal.Add(new DatatypeValidationResultDetail(ResultDetailType.Error, "EIVL", "When populated, the Offset.High property must contain a valid PQ.TIME instance", null)); } if (this.Offset.Width != null && !this.Offset.Width.IsNull && !PQ.IsValidTimeFlavor(this.Offset.Width)) { retVal.Add(new DatatypeValidationResultDetail(ResultDetailType.Error, "EIVL", "When populated, the Offset.Width property must contain a valid PQ.TIME instance", null)); } if (this.Offset.Value != null && !this.Offset.Value.IsNull && !PQ.IsValidTimeFlavor(this.Offset.Value)) { retVal.Add(new DatatypeValidationResultDetail(ResultDetailType.Error, "EIVL", "When populated, the Offset.Value property must contain a valid PQ.TIME instance", null)); } } string cc = Util.ToWireFormat(this.Event); if (!((cc.StartsWith("IC") || cc.StartsWith("AC") || cc.StartsWith("PC")) ^ (this.Offset != null))) { retVal.Add(new DatatypeValidationResultDetail(ResultDetailType.Error, "EIVL", "When the Event property implies before, after or between meals the Offset property must not be populated", null)); } return(retVal); }
/// <summary> /// Translates this IVL by the specified quantity /// </summary> /// <exception cref="T:System.InvalidOperationException">Thrown when the function cannot determine the /// a reliable translation point (ie: either low or high are null)</exception> public IVL <T> Translate(PQ translation) { if (this.IsNull) { return new IVL <T>() { NullFlavor = this.NullFlavor } } ; // Low and high references T low = this.Low, high = this.High, value = this.Value; // Is a width specified? If so, then we need a // valid low/high to translate if (low == null || high == null) { // Determine if we can calculate bounds if (this.Width != null && (low is IPqTranslatable <T> || high is IPqTranslatable <T>)) { if (low != null) { high = (low as IPqTranslatable <T>).Translate(Width); } else if (high != null) { low = (high as IPqTranslatable <T>).Translate(-Width); } } else if (value == null) { throw new InvalidOperationException("Cannot determine set bounds"); } } // Translate IPqTranslatable <T> pqLow = low as IPqTranslatable <T>, pqHigh = high as IPqTranslatable <T>, pqValue = value as IPqTranslatable <T>; low = low == null ? default(T) : pqLow.Translate(translation); high = pqHigh == null ? default(T) : pqHigh.Translate(translation); value = pqValue == null ? default(T) : pqValue.Translate(translation); return(new IVL <T>(low, high) { Value = value, LowClosed = this.LowClosed, HighClosed = this.HighClosed }); }
/// <summary> /// Determine if this PQ equals another instance of PQ /// </summary> public bool Equals(PQ other) { bool result = false; if (other != null) { result = base.Equals((QTY <Nullable <Decimal> >)other) && (other.CodingRationale != null ? other.CodingRationale.Equals(this.CodingRationale) : this.CodingRationale == null) && other.Precision == this.Precision && (other.Translation != null ? other.Translation.Equals(this.Translation) : this.Translation == null) && other.Unit == this.Unit; } return(result); }
/// <summary> /// Determine if this instance of PIVL contains <paramref name="member"/> according /// to the PIVL's definition /// </summary> /// <remarks> /// <para>Please note that the contains method does not adhere to the <see cref="P:Alignment"/> property and /// the determination of containment is defined strictly on <see cref="P:Phase"/> and <see cref="P:Period"/>.</para> /// <para>The algorithm for determining containment is as follows:</para> /// <list type="number"> /// <item><description>Distance <paramref name="member"/> from the low bound of <see cref="P:Phase"/></description></item> /// <item><description>Divide the result of the previous operation by <see cref="P:Period"/></description></item> /// <item><description>Round the result of the previous operation to a whole number based on the unit specified in <see cref="P:Period"/></description></item> /// <item><description>Multiply the result of the previous operation by the <see cref="P:Period"/></description></item> /// <item><description>Translate <see cref="P:Phase"/> by the result of the previous operation</description></item> /// <item><description>Determine if <paramref name="member"/> resides in the translated <see cref="P:Phase"/> from the previous operation</description></item> /// </list> /// </remarks> /// <param name="member">The proposed member of the set</param> /// <returns>True if the PIVL contains <paramref name="member"/></returns> /// <exception cref="T:System.ArgumentException">When the distance between two instances of <typeparamref name="T"/> is not calculable. This occurs when /// <typeparamref name="T"/> does not implement <see cref="T:MARC.Everest.DataTypes.Interfaces.IDistanceable{T}"/></exception> /// <exception cref="T:System.InvalidOperationException">When the <see cref="P:Phase"/> property is not populated</exception> public bool Contains(T member) { // Algorithm: // phase.translate((int)((member - low) / period) * period) // if (!(member is IDistanceable <T>)) { throw new ArgumentException("Unable to calculate the distance between objects of specified type", "member"); } if (this.Phase == null) { throw new InvalidOperationException("Cannot determine containment of a PIVL that is not bound with a Phase"); } var distMemb = member as IDistanceable <T>; var period = this.Period; if (period == null && this.Frequency != null) // If frequency is specified, then make period the reciprocal { period = this.Frequency.Denominator / this.Frequency.Numerator; } // Get the distance between the target iteration and the phase PQ desiredTranslation = distMemb.Distance(this.Phase.Low); // Get the desired translation in repeats desiredTranslation /= period; desiredTranslation.Value = Math.Round(desiredTranslation.Value.Value, 0); if (this.Count != null && this.Count.CompareTo((int)desiredTranslation.Value) > 0) // number of iterations exceeds limit { return(false); } else if (desiredTranslation.Value < 0) // Happens before offset, meaning first { return(false); } // Correct to periods we need to translate by desiredTranslation *= period; // Translate phase var translatedPhase = this.Phase.Translate(desiredTranslation); return(translatedPhase.Contains(member)); }
/// <summary> /// Validate this EIVL /// </summary> public override bool Validate() { bool valid = (NullFlavor != null) ^ (Offset != null || Event != null); if (this.Offset != null) { valid &= this.Offset.Low == null || this.Offset.Low.IsNull || PQ.IsValidTimeFlavor(this.Offset.Low); valid &= this.Offset.High == null || this.Offset.High.IsNull || PQ.IsValidTimeFlavor(this.Offset.High); valid &= this.Offset.Width == null || this.Offset.Width.IsNull || PQ.IsValidTimeFlavor(this.Offset.Width); valid &= this.Offset.Value == null || this.Offset.Value.IsNull || PQ.IsValidTimeFlavor(this.Offset.Value); } string cc = Util.ToWireFormat(this.Event); valid &= (cc.StartsWith("IC") || cc.StartsWith("AC") || cc.StartsWith("PC")) ^ (this.Offset != null); return(valid); }
/// <summary> /// Create a new instance of the PIVL type using the phase and period specified /// </summary> /// <param name="phase">The phase of the PIVL</param> /// <param name="period">The period of the PIVL</param> /// <param name="count">The maximum number of times the PIVL can repreat</param> public PIVL(IVL <T> phase, PQ period, INT count) : this(phase, period) { this.Count = count; }
/// <summary> /// Create a new instance of the PIVL type using the phase and period specified /// </summary> /// <param name="phase">The phase of the PIVL</param> /// <param name="period">The period of the PIVL</param> public PIVL(IVL <T> phase, PQ period) { this.Phase = phase; this.Period = period; }
/// <summary> /// Calculate the distance between this PQ and /// another PQ with the same unit of measure /// </summary> /// <exception cref="T:System.InvalidOperationException">Thrown units of this and <paramref name="other"/> are not comparable</exception> public PQ Distance(PQ other) { return(this - other); }
/// <summary> /// Scales this PQ by <paramref name="scale"/> /// </summary> /// <param name="scale">The scale by which this instance should be scaled</param> /// <remarks>Results in a new PQ with the result</remarks> public PQ Scale(PQ scale) { return(this * scale); }
/// <summary> /// Translates this PQ by a factor of <paramref name="translation"/> /// by applying the addition operator /// </summary> /// <param name="translation">The quantity to translate (or shift) this PQ by</param> /// <remarks>Results in a new PQ containing the result of the translation</remarks> /// <exception cref="T:System.ArgumentException">If the units of the PQ do not match</exception> public PQ Translate(PQ translation) { return(this + translation); }
public static bool IsValidTimeFlavor(PQ a) { return(s_tickMap.ContainsKey(a.Unit)); }
/// <summary> /// Validates that this TS meets the basic validation criteria /// </summary> /// <remarks> /// <para>Basic validation criteria is considered:</para> /// <list type="bullet"> /// <item><description>If <see cref="P:NullFlavor"/> is not null, then <see cref="P:DateValue"/> and <see cref="P:UncertainRange"/> cannot be set</description></item> /// <item><description>If <see cref="P:DateValue"/> or <see cref="P:UncertainRange"/> are populated, then <see cref="P:NullFlavor"/> cannot be set</description></item> /// <item><description>Both <see cref="P:DateValue"/> and <see cref="P:UncertainRange"/> cannot be set at the same time</description></item> /// <item><description>Any uncertainty (<see cref="P:Uncertainty"/>, or <see cref="P:UncertainRange"/>) must contain valid <see cref="T:PQ"/>.TIME or <see cref="T:IVL`1"/>of PQ.TIME</description></item> /// </list> /// </remarks> public override bool Validate() { return((NullFlavor != null) ^ ((DateValue != default(DateTime) || UncertainRange != null) && ((this.Uncertainty != null && this.Uncertainty is PQ && PQ.IsValidTimeFlavor(this.Uncertainty as PQ)) || (this.Uncertainty == null)) && ((this.UncertainRange != null && this.UncertainRange.Low is PQ && this.UncertainRange.High is PQ && PQ.IsValidTimeFlavor(this.UncertainRange.Low as PQ) && PQ.IsValidTimeFlavor(this.UncertainRange.High as PQ)) || this.UncertainRange == null) && (((DateValue != default(DateTime)) ^ (this.UncertainRange != null)) || (this.DateValue == null && this.UncertainRange == null)))); }