using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Sql.Common;
///
/// Per-bucket statistics one aggregate query row produces (one non-empty bucket). Every backend's SQL fills the same
/// fields; turns them into the OPC UA value and status.
///
///
/// Sample classes: usable = severity Good or Uncertain AND a stored value (an Empty sample is an outage marker
/// and counts as Bad whatever its code); good = usable with severity Good; bad = not usable.
/// / / / / are computed over
/// Good numeric samples only (#684 — Part 13 defines Average / Minimum / Maximum / Range / *ActualTime over Good
/// raw values, as the SDK's calculators do); / over the Uncertain
/// ones (the Part 13 Minimum/Maximum/Range status rule); / over usable samples;
/// / over every sample.
///
public sealed class BucketRow
{
/// Zero-based bucket index within the window.
public long Bucket { get; set; }
/// All samples in the bucket.
public int Total { get; set; }
/// Usable samples.
public int Usable { get; set; }
/// Good samples.
public int Good { get; set; }
/// Bad (not usable) samples.
public int Bad { get; set; }
/// Usable String / DateTime samples (Delta's refusal check).
public int NonNumeric { get; set; }
///
/// Good String / DateTime samples — the refusal check of the Good-value aggregates (Average / Minimum / Maximum /
/// Range / *ActualTime, #684 review): an Uncertain non-numeric sample is not part of their value set. Filled by the
/// Simple and ActualTime queries; null (a row that does not carry it) falls back to , the
/// pre-#684 (stricter) check.
///
public int? GoodNonNumeric { get; set; }
/// , or when the row does not carry it.
internal int GoodNonNumericOrAll => GoodNonNumeric ?? NonNumeric;
/// Average of the Good numeric values (null when none — #684).
public double? Avg { get; set; }
/// Minimum of the Good numeric values (null when none — #684).
public double? Min { get; set; }
/// Maximum of the Good numeric values (null when none — #684).
public double? Max { get; set; }
/// Sum of the Good numeric values (null when none — #684).
public double? Sum { get; set; }
/// First usable sample's value by time (Empty when none).
public HistorianValue First { get; set; }
/// Last usable sample's value by time (Empty when none).
public HistorianValue Last { get; set; }
/// Extreme (min or max) Good numeric value (null when none — #684).
public double? Extreme { get; set; }
/// Time of (ties ⇒ earliest; null when none).
public DateTime? ExtremeTime { get; set; }
///
/// Minimum of the bucket's Uncertain (usable, not Good) numeric values (null when none). Not a result value:
/// Part 13 makes Minimum / MinimumActualTime / Range Uncertain_DataSubNormal when an Uncertain value is less
/// than the minimum Good value (#684).
///
public double? UncertainMin { get; set; }
///
/// Maximum of the bucket's Uncertain numeric values (null when none): Maximum / MaximumActualTime / Range are
/// Uncertain when one is greater than the maximum Good value (#684).
///
public double? UncertainMax { get; set; }
///
/// The bucket's first sample by time of any quality (null when the bucket is empty): Start returns it raw, and
/// Delta is Uncertain when it is not usable (#680, Part 13 Tables 73/74 — the SDK's StartEndAggregateCalculator).
///
public StoredSample? FirstAny { get; set; }
/// The bucket's last sample by time of any quality (null when the bucket is empty): End, Delta (#680).
public StoredSample? LastAny { get; set; }
}