private void DrawProgressByDetectionResult(Point detectionPoint, AnomalyLastDetectResult detectionResult, AnomalyInfo anomalyInfo, double yScale, double yZeroLine = 0)
        {
            double upperMarginOnUI        = detectionResult.ExpectedValue + detectionResult.UpperMargin;
            double lowerMarginOnUI        = detectionResult.ExpectedValue - detectionResult.LowerMargin;
            double offsetY1               = yScale * upperMarginOnUI;
            double offsetY2               = lowerMarginOnUI > 0 ? yScale * lowerMarginOnUI : 0;
            int    indexOfFirstValidPoint = curScenario.MinIndexOfRequiredPoints;

            Point newUpperPoint = new Point(detectionPoint.X, (yZeroLine + resultGrid.ActualHeight - offsetY1) > 0 ? (yZeroLine + resultGrid.ActualHeight - offsetY1) : 0);
            Point newLowerPoint = new Point(detectionPoint.X, yZeroLine + resultGrid.ActualHeight - offsetY2);

            if (detectionResult.IsAnomaly)
            {
                SpriteVisual anomalyIndicator = GetNewAnomalyIndicator(detectionPoint);
                containerRoot.Children.InsertAtTop(anomalyIndicator);
                allAnomalyIndicators.Add(new Tuple <SpriteVisual, AnomalyInfo>(anomalyIndicator, anomalyInfo));
            }

            int endOfUpper = progressPolyline.Points.Count / 2;
            int endOfLower = progressPolyline.Points.Count / 2 + 1;

            progressPolyline.Points.Insert(endOfUpper, newUpperPoint);
            progressPolyline.Points.Insert(endOfLower, newLowerPoint);

            detectWindowPolyline.Points.Insert((detectWindowPolyline.Points.Count / 2), new Point(detectionPoint.X, 0));
            detectWindowPolyline.Points.Insert((detectWindowPolyline.Points.Count / 2 + 1), new Point(detectionPoint.X, resultGrid.ActualHeight));
            if ((detectWindowPolyline.Points.Count / 2) >= indexOfFirstValidPoint)
            {
                detectWindowPolyline.Points.RemoveAt(0);
                detectWindowPolyline.Points.RemoveAt(detectWindowPolyline.Points.Count - 1);
            }

            progressIndicator.Offset = new Vector3((float)(detectionPoint.X), (float)(resultGrid.ActualHeight), resultGrid.CenterPoint.Z);

            progressLine.X1 = detectionPoint.X;
            progressLine.X2 = detectionPoint.X;
        }
        private async Task StartStreamingModeProcessAsync()
        {
            try
            {
                if (dataPolyline.Points != null)
                {
                    dataPolyline.Points.Clear();
                }
                else
                {
                    dataPolyline.Points = new PointCollection();
                }

                double dataRange = curScenario.MaxValue - curScenario.MinValue;
                double yScale    = resultGrid.ActualHeight / dataRange;
                double xOffset   = resultGrid.ActualWidth / (curScenario.AllData.Count - 1);
                double yZeroLine = yScale * curScenario.MinValue;

                string timestampFormat = curScenario.ScenarioType == AnomalyDetectionScenarioType.Telecom ? ShortDateFormat : ShortDateWithTimeFormat;
                int    startIndex      = curScenario.MinIndexOfRequiredPoints;

                for (int i = 0; i < startIndex; i++)
                {
                    Point point = new Point(xOffset * i, yZeroLine + resultGrid.ActualHeight - (yScale * curScenario.AllData[i].Value));
                    dataPolyline.Points.Add(point);

                    Point newUpperPoint = new Point(dataPolyline.Points[i].X, 0);
                    Point newLowerPoint = new Point(dataPolyline.Points[i].X, resultGrid.ActualHeight);

                    int endOfUpper = detectWindowPolyline.Points.Count / 2;
                    int endOfLower = detectWindowPolyline.Points.Count / 2 + 1;

                    detectWindowPolyline.Points.Insert(endOfUpper, newUpperPoint);
                    detectWindowPolyline.Points.Insert(endOfLower, newLowerPoint);
                }

                for (int i = startIndex; i < curScenario.AllData.Count; i++)
                {
                    if (shouldStopCurrentRun)
                    {
                        break;
                    }

                    AnomalyLastDetectResult result = await GetStreamingAnomalyDetectionResultAsync(i);

                    Point point = new Point(xOffset * i, yZeroLine + resultGrid.ActualHeight - (yScale * curScenario.AllData[i].Value));
                    dataPolyline.Points.Add(point);

                    if (result != null)
                    {
                        TimeSeriesData timeSeriesData = curScenario.AllData[i];
                        AnomalyInfo    anomalyInfo    = new AnomalyInfo
                        {
                            Text          = Util.StringToDateFormat(timeSeriesData.Timestamp, timestampFormat),
                            Value         = timeSeriesData.Value.ToString("F2"),
                            ExpectedValue = result.ExpectedValue.ToString("F2")
                        };

                        DrawProgressByDetectionResult(dataPolyline.Points[i], result, anomalyInfo, yScale, yZeroLine);
                    }
                }
            }
            catch (Exception ex)
            {
                await Util.GenericApiCallExceptionHandler(ex, "Failure during streaming detection.");
            }
        }
        private async Task StartLiveDemoProcessAsync()
        {
            try
            {
                double yScale  = resultGrid.ActualHeight / MaxVolumeValue;
                double xOffset = resultGrid.ActualWidth / DefaultDurationOfLiveDemoInSecond;

                DateTime currentTime = DateTime.Now;
                DateTime startTime   = currentTime.AddMinutes((double)DefaultDurationOfLiveDemoInSecond * -1);

                progressLine.X1 = progressIndicator.CenterPoint.X;
                progressLine.X2 = progressIndicator.CenterPoint.X;

                dataPolyline.Points.Clear();

                int startIndex = AnomalyDetectionScenario.DefaultRequiredPoints;
                for (int i = 0; i < startIndex; i++)
                {
                    float volume = GetCurrentVolumeValue();

                    curScenario.AllData.Insert(i, new TimeSeriesData(startTime.ToString(), volume));
                    startTime = startTime.AddMinutes(AnomalyDetectorScenarioLoader.GetTimeOffsetInMinute(curScenario.Granularity));

                    double yOffset = yScale * (curScenario.AllData[i].Value - BaseVolume);
                    Point  point   = new Point(xOffset * i, resultGrid.ActualHeight - yOffset);
                    dataPolyline.Points.Add(point);

                    Point newUpperPoint = new Point(dataPolyline.Points[i].X, 0);
                    Point newLowerPoint = new Point(dataPolyline.Points[i].X, resultGrid.ActualHeight);

                    int endOfUpper = detectWindowPolyline.Points.Count / 2;
                    int endOfLower = detectWindowPolyline.Points.Count / 2 + 1;

                    detectWindowPolyline.Points.Insert(endOfUpper, newUpperPoint);
                    detectWindowPolyline.Points.Insert(endOfLower, newLowerPoint);
                }

                for (int i = startIndex; i < DefaultDurationOfLiveDemoInSecond; i++)
                {
                    if (shouldStopCurrentRun)
                    {
                        break;
                    }

                    float volume = GetCurrentVolumeValue();

                    curScenario.AllData.Insert(i, new TimeSeriesData(startTime.ToString(), volume));
                    startTime = startTime.AddMinutes(AnomalyDetectorScenarioLoader.GetTimeOffsetInMinute(curScenario.Granularity));

                    double yOffset = yScale * (curScenario.AllData[i].Value - BaseVolume);
                    Point  point   = new Point(xOffset * i, resultGrid.ActualHeight - yOffset);
                    dataPolyline.Points.Add(point);

                    AnomalyLastDetectResult result = await GetLiveDemoAnomalyDetectionResultAsync(i);

                    if (result != null)
                    {
                        result.ExpectedValue -= BaseVolume;
                        AnomalyInfo anomalyInfo = new AnomalyInfo
                        {
                            Text          = i.ToString(),
                            Value         = (volume - BaseVolume).ToString("F2"),
                            ExpectedValue = result.ExpectedValue.ToString("F2")
                        };
                        DrawProgressByDetectionResult(dataPolyline.Points[i], result, anomalyInfo, yScale);
                    }
                }

                this.StopLiveAudio?.Invoke(this, EventArgs.Empty);
            }
            catch (Exception ex)
            {
                await Util.GenericApiCallExceptionHandler(ex, "Failure during streaming detection.");
            }
        }