Exemplo n.º 1
0
        protected abstract bool Comparison(DataValue value1, DataValue value2); // true if keep value1.

        public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
        {
            int       numGood     = 0;
            int       numBad      = 0;
            DataValue valueToKeep = new DataValue()
            {
                SourceTimestamp = bucket.From, StatusCode = StatusCodes.BadNoData
            };
            bool moreData    = false;
            bool hasGoodData = false;

            foreach (DataValue dv in bucket.Values)
            {
                if (state.RawValueIsGood(dv))
                {
                    hasGoodData = true;
                    if (valueToKeep.StatusCode == StatusCodes.BadNoData)
                    {
                        valueToKeep = dv;
                    }
                    else
                    {
                        moreData = valueToKeep == dv;
                        if (Comparison(dv, valueToKeep))
                        {
                            valueToKeep = dv;
                        }
                    }
                    numGood++;
                }
                else
                {
                    numBad++;
                    if (!hasGoodData)
                    {
                        valueToKeep = dv;
                    }
                }
            }
            DataValue retval = valueToKeep.StatusCode == StatusCodes.BadNoData ? valueToKeep : (DataValue)valueToKeep.Clone();

            if (hasGoodData)
            {
                StatusCode code = StatusCodes.Good;
                code = ComputeStatus(context, numGood, numBad, bucket).Code;
                code.AggregateBits = moreData ? AggregateBits.ExtraData : AggregateBits.Raw;
                if (bucket.Incomplete)
                {
                    code.AggregateBits |= AggregateBits.Partial;
                }
                retval.StatusCode = code;
            } // numGood = 0, hasGoodData = false beyond this point, i.e., no good data
            else if (numBad > 0)
            {
                retval.Value      = null;
                retval.StatusCode = StatusCodes.Bad;
                retval.StatusCode = retval.StatusCode.SetAggregateBits(AggregateBits.Raw);
            }
            return(retval);
        }
Exemplo n.º 2
0
        public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
        {
            int numGood = 0;
            int numBad = 0;
            DataValue previous = RightState(bucket.EarlyBound.Value) ? bucket.EarlyBound.Value : null;
            double total = 0.0;

            DataValue retval = new DataValue { SourceTimestamp = bucket.From };
            StatusCode code = StatusCodes.BadNoData;

            foreach (DataValue v in bucket.Values)
            {
                if (state.RawValueIsGood(v))
                {
                    numGood += 1;
                    if (previous != null)
                        total += (v.SourceTimestamp - previous.SourceTimestamp).TotalMilliseconds;
                    previous = RightState(v) ? v : null;
                }
                else
                {
                    numBad += 1;
                }
            }
            if (previous != null)
                total += (bucket.LateBound.Value.SourceTimestamp - previous.SourceTimestamp).TotalMilliseconds;
            retval.Value = total;
            code = ComputeStatus(context, numGood, numBad, bucket).Code;
            code.AggregateBits = AggregateBits.Calculated;
            if (bucket.Incomplete) code.AggregateBits |= AggregateBits.Partial;
            retval.StatusCode = code;
            return retval;
        }
Exemplo n.º 3
0
 public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
 {
     int numGood = 0;
     int numBad = 0;
     double total = 0.0;
     foreach (DataValue v in bucket.Values)
     {
         if (state.RawValueIsGood(v))
         {
             numGood += 1;
             total += Convert.ToDouble(v.Value, CultureInfo.InvariantCulture);
         }
         else
         {
             numBad += 1;
         }
     }
     DataValue retval = new DataValue { SourceTimestamp = bucket.From };
     StatusCode code = ComputeStatus(context, numGood, numBad, bucket).Code;
     code.AggregateBits = AggregateBits.Calculated;
     if (bucket.Incomplete) code.AggregateBits |= AggregateBits.Partial;
     if (StatusCode.IsNotBad(code))
         retval.Value = total;
     retval.StatusCode = code;
     GoodDataCount = numGood;
     return retval;
 }
Exemplo n.º 4
0
        public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
        {
            int numGood = 0;
            int numBad  = 0;

            foreach (DataValue v in bucket.Values)
            {
                if (state.RawValueIsGood(v))
                {
                    numGood += 1;
                }
                else
                {
                    numBad += 1;
                }
            }
            StatusCode code   = StatusCodes.Good;
            DataValue  retval = new DataValue {
                SourceTimestamp = bucket.From
            };

            retval.Value       = numGood;
            code               = ComputeStatus(context, numGood, numBad, bucket).Code;
            code.AggregateBits = AggregateBits.Calculated;
            if (bucket.Incomplete)
            {
                code.AggregateBits |= AggregateBits.Partial;
            }
            retval.StatusCode = code;
            return(retval);
        }
Exemplo n.º 5
0
        public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
        {
            int    numGood = 0;
            int    numBad  = 0;
            double minV    = double.MaxValue;
            double maxV    = double.MinValue;
            bool   uncertainDataSubNormal = false;
            double range = double.NaN;

            foreach (DataValue dv in bucket.Values)
            {
                if (state.RawValueIsGood(dv))
                {
                    double v = Convert.ToDouble(dv.Value);
                    if (minV > v)
                    {
                        minV = v;
                    }
                    if (maxV < v)
                    {
                        maxV = v;
                    }
                    numGood++;
                }
                else
                {
                    uncertainDataSubNormal = true;
                    numBad++;
                }
            }
            if (minV != double.MaxValue && maxV != double.MinValue)
            {
                range = Math.Abs(maxV - minV);
            }

            StatusCode code = (uncertainDataSubNormal)
                ? StatusCodes.UncertainDataSubNormal
                : StatusCodes.Good;

            if (numGood + numBad == 0)
            {
                code = StatusCodes.BadNoData;
            }
            DataValue retval = new DataValue {
                SourceTimestamp = bucket.From
            };

            if (!double.IsNaN(range))
            {
                retval.Value = range;
            }
            code.AggregateBits = AggregateBits.Calculated;
            if (bucket.Incomplete)
            {
                code.AggregateBits |= AggregateBits.Partial;
            }
            retval.StatusCode = code;
            return(retval);
        }
Exemplo n.º 6
0
        public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
        {
            int numGood = 0;
            int numBad = 0;
            DataValue firstGoodDv = null;
            DataValue lastGoodDv = null;
            DataValue lastDv = null;
            bool uncertainDataSubNormal = false;
            double delta = double.NaN;
            
            foreach (DataValue dv in bucket.Values)
            {
                if (state.RawValueIsGood(dv))
                {
                    if (firstGoodDv == null)
                    {
                        firstGoodDv = dv;
                    }
                    lastGoodDv = dv;                   
                    numGood++;
                }
                else
                {
                    // check for non-good value occuring before first good value
                    if (firstGoodDv == null)
                        uncertainDataSubNormal = true;
                    numBad++;
                }
                lastDv = dv;
            }
            if (firstGoodDv != null)
            {
                double fv = Convert.ToDouble(firstGoodDv.Value);
                double lv = Convert.ToDouble(lastGoodDv.Value);
                delta = lv - fv;
            }
            
            // check for non-good value occuring after latest good value
            if (!uncertainDataSubNormal && lastGoodDv != null && lastGoodDv.SourceTimestamp < lastDv.SourceTimestamp)
                uncertainDataSubNormal = true;

            StatusCode code = (uncertainDataSubNormal)
                ? StatusCodes.UncertainDataSubNormal
                : (numGood > 0) ? StatusCodes.Good : StatusCodes.BadNoData;
            DataValue retval = new DataValue { SourceTimestamp = bucket.From };
            if (!double.IsNaN(delta))
                retval.Value = delta;
            code.AggregateBits = AggregateBits.Calculated;
            if (bucket.Incomplete) code.AggregateBits |= AggregateBits.Partial;
            retval.StatusCode = code;
            return retval;
        }
        protected abstract bool Comparison(DataValue value1, DataValue value2); // true if keep value1.

        public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
        {
            int numGood = 0;
            int numBad = 0;
            DataValue valueToKeep = new DataValue() { SourceTimestamp = bucket.From, StatusCode = StatusCodes.BadNoData };
            bool moreData = false;
            bool hasGoodData = false;
            foreach (DataValue dv in bucket.Values)
            {
                if (state.RawValueIsGood(dv))
                {
                    hasGoodData = true;
                    if (valueToKeep.StatusCode == StatusCodes.BadNoData)
                    {
                        valueToKeep = dv;
                    }
                    else
                    {
                        moreData = valueToKeep == dv;
                        if (Comparison(dv, valueToKeep))
                        {
                            valueToKeep = dv;
                        }
                    }
                    numGood++;
                }
                else
                {
                    numBad++;
                    if (!hasGoodData)
                        valueToKeep = dv;
                }
            }
            DataValue retval = valueToKeep.StatusCode == StatusCodes.BadNoData ? valueToKeep : (DataValue)valueToKeep.Clone();
            if (hasGoodData)
            {
                StatusCode code = StatusCodes.Good;
                code = ComputeStatus(context, numGood, numBad, bucket).Code;
                code.AggregateBits = moreData ? AggregateBits.ExtraData : AggregateBits.Raw;
                if (bucket.Incomplete) code.AggregateBits |= AggregateBits.Partial;
                retval.StatusCode = code;
            } // numGood = 0, hasGoodData = false beyond this point, i.e., no good data
            else if(numBad > 0)
            {
                retval.Value = null;
                retval.StatusCode = StatusCodes.Bad;
                retval.StatusCode = retval.StatusCode.SetAggregateBits(AggregateBits.Raw);
            }
            return retval;
        }
Exemplo n.º 8
0
        public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
        {
            int numGood = 0;
            int numBad = 0;
            double minV = double.MaxValue;
            double maxV = double.MinValue;
            bool uncertainDataSubNormal = false;
            double range = double.NaN;

            foreach (DataValue dv in bucket.Values)
            {
                if (state.RawValueIsGood(dv))
                {
                    double v = Convert.ToDouble(dv.Value);
                    if (minV > v)
                    {
                        minV = v;
                    }
                    if (maxV < v)
                    {
                        maxV = v;
                    }
                    numGood++;
                }
                else
                {
                    uncertainDataSubNormal = true;
                    numBad++;
                }
            }
            if (minV != double.MaxValue && maxV != double.MinValue)
            {
                range = Math.Abs(maxV - minV);
            }

            StatusCode code = (uncertainDataSubNormal)
                ? StatusCodes.UncertainDataSubNormal
                : StatusCodes.Good;
            if (numGood + numBad == 0) code = StatusCodes.BadNoData;
            DataValue retval = new DataValue { SourceTimestamp = bucket.From };
            if (!double.IsNaN(range))
                retval.Value = range;
            code.AggregateBits = AggregateBits.Calculated;
            if (bucket.Incomplete) code.AggregateBits |= AggregateBits.Partial;
            retval.StatusCode = code;
            return retval;
        }
Exemplo n.º 9
0
        public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
        {
            int       numGood  = 0;
            int       numBad   = 0;
            DataValue previous = RightState(bucket.EarlyBound.Value) ? bucket.EarlyBound.Value : null;
            double    total    = 0.0;

            DataValue retval = new DataValue {
                SourceTimestamp = bucket.From
            };
            StatusCode code = StatusCodes.BadNoData;

            foreach (DataValue v in bucket.Values)
            {
                if (state.RawValueIsGood(v))
                {
                    numGood += 1;
                    if (previous != null)
                    {
                        total += (v.SourceTimestamp - previous.SourceTimestamp).TotalMilliseconds;
                    }
                    previous = RightState(v) ? v : null;
                }
                else
                {
                    numBad += 1;
                }
            }
            if (previous != null)
            {
                total += (bucket.LateBound.Value.SourceTimestamp - previous.SourceTimestamp).TotalMilliseconds;
            }
            retval.Value       = total;
            code               = ComputeStatus(context, numGood, numBad, bucket).Code;
            code.AggregateBits = AggregateBits.Calculated;
            if (bucket.Incomplete)
            {
                code.AggregateBits |= AggregateBits.Partial;
            }
            retval.StatusCode = code;
            return(retval);
        }
Exemplo n.º 10
0
        public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
        {
            int    numGood = 0;
            int    numBad  = 0;
            double total   = 0.0;

            foreach (DataValue v in bucket.Values)
            {
                if (state.RawValueIsGood(v))
                {
                    numGood += 1;
                    total   += Convert.ToDouble(v.Value, CultureInfo.InvariantCulture);
                }
                else
                {
                    numBad += 1;
                }
            }
            DataValue retval = new DataValue {
                SourceTimestamp = bucket.From
            };
            StatusCode code = ComputeStatus(context, numGood, numBad, bucket).Code;

            code.AggregateBits = AggregateBits.Calculated;
            if (bucket.Incomplete)
            {
                code.AggregateBits |= AggregateBits.Partial;
            }
            if (StatusCode.IsNotBad(code))
            {
                retval.Value = total;
            }
            retval.StatusCode = code;
            GoodDataCount     = numGood;
            return(retval);
        }
Exemplo n.º 11
0
 public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
 {
     int numGood = 0;
     int numBad = 0;
     foreach (DataValue v in bucket.Values)
     {
         if (state.RawValueIsGood(v))
         {
             numGood += 1;
         }
         else
         {
             numBad += 1;
         }
     }
     StatusCode code = StatusCodes.Good;
     DataValue retval = new DataValue { SourceTimestamp = bucket.From };
     retval.Value = numGood;
     code = ComputeStatus(context, numGood, numBad, bucket).Code;
     code.AggregateBits = AggregateBits.Calculated;
     if (bucket.Incomplete) code.AggregateBits |= AggregateBits.Partial;
     retval.StatusCode = code;
     return retval;
 }
Exemplo n.º 12
0
        public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
        {
            int       numGood                = 0;
            int       numBad                 = 0;
            DataValue firstGoodDv            = null;
            DataValue lastGoodDv             = null;
            DataValue lastDv                 = null;
            bool      uncertainDataSubNormal = false;
            double    delta = double.NaN;

            foreach (DataValue dv in bucket.Values)
            {
                if (state.RawValueIsGood(dv))
                {
                    if (firstGoodDv == null)
                    {
                        firstGoodDv = dv;
                    }
                    lastGoodDv = dv;
                    numGood++;
                }
                else
                {
                    // check for non-good value occuring before first good value
                    if (firstGoodDv == null)
                    {
                        uncertainDataSubNormal = true;
                    }
                    numBad++;
                }
                lastDv = dv;
            }
            if (firstGoodDv != null)
            {
                double fv = Convert.ToDouble(firstGoodDv.Value);
                double lv = Convert.ToDouble(lastGoodDv.Value);
                delta = lv - fv;
            }

            // check for non-good value occuring after latest good value
            if (!uncertainDataSubNormal && lastGoodDv != null && lastGoodDv.SourceTimestamp < lastDv.SourceTimestamp)
            {
                uncertainDataSubNormal = true;
            }

            StatusCode code = (uncertainDataSubNormal)
                ? StatusCodes.UncertainDataSubNormal
                : (numGood > 0) ? StatusCodes.Good : StatusCodes.BadNoData;
            DataValue retval = new DataValue {
                SourceTimestamp = bucket.From
            };

            if (!double.IsNaN(delta))
            {
                retval.Value = delta;
            }
            code.AggregateBits = AggregateBits.Calculated;
            if (bucket.Incomplete)
            {
                code.AggregateBits |= AggregateBits.Partial;
            }
            retval.StatusCode = code;
            return(retval);
        }
Exemplo n.º 13
0
        public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
        {
            DataValue retval = new DataValue { SourceTimestamp = bucket.From };
            DataValue initValue = bucket.EarlyBound.Value, finalValue = bucket.LateBound.Value;
            IEnumerator<DataValue> enumerator = bucket.Values.GetEnumerator();
            StatusCode code = StatusCodes.BadNoData;
            if (initValue == null && enumerator.MoveNext()) // first element
            {
                initValue = enumerator.Current;
            }
            if (finalValue == null)
            {
                while (enumerator.MoveNext())
                {
                    finalValue = enumerator.Current;
                }
            }
            if (initValue != null && finalValue != null)
            {
                int numGood = 0;
                int numBad = 0;
                double total = 0.0;
                double early = 0.0;
                double late = 0.0;
                double width = 0.0;

                Debug.WriteLine(String.Format("bucket starts @ {0}, ends @ {1}", bucket.From.TimeOfDay, bucket.To.TimeOfDay));

                if ((initValue.StatusCode.AggregateBits & AggregateBits.Raw) == 0)
                {
                    if (state.RawValueIsGood(initValue))
                        numGood += 1;
                    else
                        numBad += 1;
                }
                if ((finalValue.StatusCode.AggregateBits & AggregateBits.Raw) == 0)
                {
                    if (state.RawValueIsGood(finalValue))
                        numGood += 1;
                    else
                        numBad += 1;
                }
                DataValue preceding = initValue;
                foreach (DataValue v in bucket.Values)
                {
                    if (state.RawValueIsGood(v))
                    {
                        numGood += 1;
                        early = Convert.ToDouble(preceding.Value, CultureInfo.InvariantCulture);
                        late = Convert.ToDouble(v.Value, CultureInfo.InvariantCulture);
                        width = (v.SourceTimestamp - preceding.SourceTimestamp).TotalMilliseconds;
                        total += SteppedVariable ? width * early : width * (late + early) / 2;
                        preceding = v;
                    }
                    else
                    {
                        numBad += 1;
                    }
                }
                early = Convert.ToDouble(preceding.Value, CultureInfo.InvariantCulture);
                late = Convert.ToDouble(finalValue.Value, CultureInfo.InvariantCulture);
                width = (finalValue.SourceTimestamp - preceding.SourceTimestamp).TotalMilliseconds;
                total += SteppedVariable ? width * early : width * (late + early) / 2;
                retval.Value = total;
                code = ComputeStatus(context, numGood, numBad, bucket).Code;
            }
            code.AggregateBits = AggregateBits.Calculated;
            if (StatusCode.IsNotBad(code) && bucket.Incomplete)
                code.AggregateBits |= AggregateBits.Partial;
            retval.StatusCode = code;
            return retval;
        }
Exemplo n.º 14
0
        public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
        {
            DataValue retval = new DataValue { SourceTimestamp = bucket.From };
            DataValue initValue = bucket.EarlyBound.Value, finalValue = bucket.LateBound.Value;
            IEnumerator<DataValue> enumerator = bucket.Values.GetEnumerator();
            StatusCode code = StatusCodes.BadNoData;
            if (initValue == null && enumerator.MoveNext()) // first element
            {
                initValue = enumerator.Current;
            }
            if (finalValue == null)
            {
                while (enumerator.MoveNext())
                {
                    finalValue = enumerator.Current;
                }
            }
            if (initValue != null && finalValue != null)
            {
                int numGood = 0;
                int numBad = 0;
                double total = 0.0;
                double early = 0.0;
                double late = 0.0;
                double width = 0.0;

                Debug.WriteLine(String.Format("bucket starts @ {0}, ends @ {1}", bucket.From.TimeOfDay, bucket.To.TimeOfDay));

                if ((initValue.StatusCode.AggregateBits & AggregateBits.Raw) == 0)
                {
                    if (state.RawValueIsGood(initValue))
                        numGood += 1;
                    else
                        numBad += 1;
                }
                if ((finalValue.StatusCode.AggregateBits & AggregateBits.Raw) == 0)
                {
                    if (state.RawValueIsGood(finalValue))
                        numGood += 1;
                    else
                        numBad += 1;
                }
                DataValue preceding = initValue;
                foreach (DataValue v in bucket.Values)
                {
                    if (state.RawValueIsGood(v))
                    {
                        numGood += 1;
                        early = Convert.ToDouble(preceding.Value, CultureInfo.InvariantCulture);
                        late = Convert.ToDouble(v.Value, CultureInfo.InvariantCulture);
                        width = (v.SourceTimestamp - preceding.SourceTimestamp).TotalMilliseconds;
                        total += SteppedVariable ? width * early : width * (late + early) / 2;
                        preceding = v;
                    }
                    else
                    {
                        numBad += 1;
                    }
                }
                early = Convert.ToDouble(preceding.Value, CultureInfo.InvariantCulture);
                late = Convert.ToDouble(finalValue.Value, CultureInfo.InvariantCulture);
                width = (finalValue.SourceTimestamp - preceding.SourceTimestamp).TotalMilliseconds;
                total += SteppedVariable ? width * early : width * (late + early) / 2;
                retval.Value = total;
                code = ComputeStatus(context, numGood, numBad, bucket).Code;
            }
            code.AggregateBits = AggregateBits.Calculated;
            if (StatusCode.IsNotBad(code) && bucket.Incomplete) 
                code.AggregateBits |= AggregateBits.Partial;
            retval.StatusCode = code;
            return retval;
        }
Exemplo n.º 15
0
        public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
        {
            int  numGood      = 0;
            int  numBad       = 0;
            int  nTransitions = 0;
            long stateCode    = -1;
            IEnumerator <DataValue> enumerator = bucket.Values.GetEnumerator();
            bool bucketValueNotEmpty           = enumerator.MoveNext();

            if (bucketValueNotEmpty && enumerator.Current != null)
            {
                if (bucket.EarlyBound != null)
                {
                    if (enumerator.Current.SourceTimestamp == bucket.EarlyBound.Timestamp && bucket.EarlyBound.PriorPoint != null)
                    {
                        stateCode = Convert.ToInt32(Convert.ToBoolean(bucket.EarlyBound.PriorPoint.Value));
                    }
                    else if (bucket.EarlyBound.Value != null)
                    {
                        stateCode = Convert.ToInt32(Convert.ToBoolean(bucket.EarlyBound.Value.Value));
                    }
                }
            }

            // viz. UA MultiStateNodeState & TwoStateNodeState,
            // assume DataValue.Value is either an EnumValueType or a bool
            if (bucketValueNotEmpty)
            {
                do
                {
                    DataValue dv = enumerator.Current;
                    if (state.RawValueIsGood(dv))
                    {
                        EnumValueType ev = dv.Value as EnumValueType;
                        if (ev == null)
                        {
                            bool b;
                            if (bool.TryParse(dv.Value.ToString(), out b))
                            {
                                if (stateCode < 0)
                                {
                                    stateCode = b ? 1 : 0;
                                }
                                else if (b.CompareTo(Convert.ToBoolean(stateCode)) != 0)
                                {
                                    nTransitions++;
                                    stateCode = b ? 1 : 0;
                                }
                            }
                            else
                            {
                                continue;
                            }
                        }
                        else
                        {
                            long s = ev.Value;
                            if (stateCode < 0)
                            {
                                stateCode = s;
                            }
                            else if (!s.Equals(stateCode))
                            {
                                nTransitions++;
                                stateCode = s;
                            }
                        }
                        numGood++;
                    }
                    else
                    {
                        numBad++;
                    }
                } while (enumerator.MoveNext());
            }

            StatusCode code   = ComputeStatus(context, numGood, numBad, bucket).Code;
            DataValue  retval = new DataValue {
                SourceTimestamp = bucket.From, Value = nTransitions
            };

            code.AggregateBits = AggregateBits.Calculated;
            if (bucket.Incomplete)
            {
                code.AggregateBits |= AggregateBits.Partial;
            }
            retval.StatusCode = code;
            return(retval);
        }
        public override DataValue Compute(IAggregationContext context, TimeSlice bucket, AggregateState state)
        {
            int numGood = 0;
            int numBad = 0;
            int nTransitions = 0;
            long stateCode = -1;
            IEnumerator<DataValue> enumerator = bucket.Values.GetEnumerator();
            bool bucketValueNotEmpty = enumerator.MoveNext();
            if (bucketValueNotEmpty && enumerator.Current != null)
            {
                if (bucket.EarlyBound != null)
                {
                    if (enumerator.Current.SourceTimestamp == bucket.EarlyBound.Timestamp && bucket.EarlyBound.PriorPoint != null)
                    {
                        stateCode = Convert.ToInt32(Convert.ToBoolean(bucket.EarlyBound.PriorPoint.Value));
                    }
                    else if (bucket.EarlyBound.Value != null)
                    {
                        stateCode = Convert.ToInt32(Convert.ToBoolean(bucket.EarlyBound.Value.Value));
                    }
                }
            }

            // viz. UA MultiStateNodeState & TwoStateNodeState, 
            // assume DataValue.Value is either an EnumValueType or a bool
            if (bucketValueNotEmpty)
            {
                do
                {
                    DataValue dv = enumerator.Current;
                    if (state.RawValueIsGood(dv))
                    {
                        EnumValueType ev = dv.Value as EnumValueType;
                        if (ev == null)
                        {
                            bool b;
                            if (bool.TryParse(dv.Value.ToString(), out b))
                            {
                                if (stateCode < 0)
                                    stateCode = b ? 1 : 0;
                                else if (b.CompareTo(Convert.ToBoolean(stateCode)) != 0)
                                {
                                    nTransitions++;
                                    stateCode = b ? 1 : 0;
                                }
                            }
                            else
                                continue;
                        }
                        else
                        {
                            long s = ev.Value;
                            if (stateCode < 0)
                                stateCode = s;
                            else if (!s.Equals(stateCode))
                            {
                                nTransitions++;
                                stateCode = s;
                            }
                        }
                        numGood++;
                    }
                    else
                    {
                        numBad++;
                    }
                } while (enumerator.MoveNext());
            }

            StatusCode code = ComputeStatus(context, numGood, numBad, bucket).Code;
            DataValue retval = new DataValue { SourceTimestamp = bucket.From, Value = nTransitions };
            code.AggregateBits = AggregateBits.Calculated;
            if (bucket.Incomplete) code.AggregateBits |= AggregateBits.Partial;
            retval.StatusCode = code;
            return retval;
        }