private ITimeSeriesValue[] ProcessLastEvent(Gemstone.Ticks ticks)
        {
            double TrendTime   = ticks - m_trendTicks;
            double TrendAmount = m_prevFiltered - m_trendValue;

            double DetSlope = (m_settings.MaxChange - m_settings.MinChange) / ((m_settings.MaxDuration - m_settings.MinChange) * Ticks.PerSecond);
            double DetYint  = m_settings.MaxChange - DetSlope * m_settings.MaxDuration * Ticks.PerSecond;
            bool   isEvent  = Math.Abs(TrendAmount) > m_settings.MinChange &&
                              (TrendTime < m_settings.MinDuration * Ticks.PerSecond) &&
                              Math.Abs(TrendAmount) > (DetSlope * TrendTime + DetYint);



            if (isEvent)
            {
                return new ITimeSeriesValue[] { new AdaptEvent("Ramping Occurred", m_trendTicks, TrendTime,
                                                               new KeyValuePair <string, double>("Power Change", TrendAmount),
                                                               new KeyValuePair <string, double>("Avg Rate", TrendAmount / TrendTime)
                                                               ) }
            }
            ;

            return(new ITimeSeriesValue[0]);
        }
    }
        /// <summary>
        /// Starts the Process of computing any analytics.
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Task StartProcessor(CancellationToken cancellationToken)
        {
            return(Task.Run(async() =>
            {
                try
                {
                    IFrame point;
                    m_futureFrameBuffer = new Queue <IFrame>(m_futureFrameBufferSize + 1);
                    int nPoints = 0;
                    Gemstone.Ticks lastProcessed = Ticks.MinValue;

                    while (await m_queueInput.Reader.WaitToReadAsync(cancellationToken))
                    {
                        if (!m_queueInput.Reader.TryRead(out point))
                        {
                            continue;
                        }


                        // Tolerance withing a few Ticks of expected TimeStamp
                        Ticks aligned = Ticks.AlignToMicrosecondDistribution(point.Timestamp, FramesPerSecond);
                        long diff = aligned - point.Timestamp;

                        if (diff > Ticks.PerMillisecond || diff < -Ticks.PerMillisecond)
                        {
                            continue;
                        }

                        // Generate Timestamps in between if necessary
                        while (aligned - (m_lastProcessedTS + (long)(Ticks.PerSecond * (1.0D / (double)FramesPerSecond))) > (long)(Ticks.PerSecond * (0.5D / (double)FramesPerSecond)) &&
                               m_lastProcessedTS != Ticks.MinValue)
                        {
                            m_lastProcessedTS = m_lastProcessedTS + (long)(Ticks.PerSecond * (1.0D / (double)FramesPerSecond));
                            IFrame frame = new Frame()
                            {
                                Timestamp = Ticks.AlignToMicrosecondDistribution(m_lastProcessedTS, FramesPerSecond),
                                Published = point.Published,
                                Measurements = new ConcurrentDictionary <string, ITimeSeriesValue>()
                            };
                            lastProcessed = frame.Timestamp;
                            nPoints++;
                            m_futureFrameBuffer.Enqueue(frame);
                            if (nPoints <= m_futureFrameBufferSize)
                            {
                                continue;
                            }

                            frame = m_futureFrameBuffer.Dequeue();

                            await ProcessPoint(frame);
                        }

                        nPoints++;
                        lastProcessed = point.Timestamp;
                        m_futureFrameBuffer.Enqueue(point);
                        if (nPoints <= m_futureFrameBufferSize)
                        {
                            continue;
                        }

                        point = m_futureFrameBuffer.Dequeue();
                        m_lastProcessedTS = aligned;
                        await ProcessPoint(point);
                    }

                    // Run through the last set of Points
                    int i = 0;
                    while (i < m_futureFrameBuffer.Count)
                    {
                        point = m_futureFrameBuffer.Dequeue();
                        lastProcessed = point.Timestamp;
                        await ProcessPoint(point);
                        i++;
                    }

                    Task[] analyticCleanups = m_analyticProcesors.Select(p => p.RunCleanup(lastProcessed)).ToArray();
                    await Task.WhenAll(analyticCleanups).ConfigureAwait(false);

                    int j = 0;
                    IFrame cleanupFrame = new Frame()
                    {
                        Measurements = new ConcurrentDictionary <string, ITimeSeriesValue>(),
                        Published = false,
                        Timestamp = Ticks.MaxValue
                    };

                    foreach (Task <ITimeSeriesValue[]> analyticResult in analyticCleanups)
                    {
                        m_analyticProcesors[j].RouteOutput(cleanupFrame, analyticResult.Result);
                        j++;
                    }

                    m_queueOutput.Writer.TryWrite(cleanupFrame);

                    Complete();
                }
                catch (Exception ex)
                {
                    int T = 1;
                }
            }, cancellationToken));
        }
 public override Task <ITimeSeriesValue[]> CompleteComputation(Gemstone.Ticks ticks)
 {
     return(Task.Run(() => ProcessLastEvent(ticks)));
 }