public async Task EvaluateStateEverySecondAsync()

in sensors/Tools/SensorExplorer/Scenario4_Distance.xaml.cs [165:479]


        public async Task EvaluateStateEverySecondAsync()
        {
            switch (_currentState)
            {
                case DistanceState.TapeMeasureTargetDistanceScreen:
                    CurrentTimerTextBox.Text = "Timer: " + _currentCountdown + " seconds";
                    if (_currentCountdown == GetCurrentTimeout())
                    {
                        _manualTargetDistances.Add(0);
                        _manualTargetTimestamps.Add(DateTime.Now);
                        _manualTargetDistances.Add(_proximityDistancesMm[_currentManualDistance]);
                        _manualTargetTimestamps.Add(DateTime.Now);
                    }
                    _currentCountdown--;

                    bool evaluateResult = false;

                    if (_proximitySensorReadingBuffer.Count > 0 && DateTimeOffset.Now.Subtract(_proximitySensorReadingBuffer.Peek().Timestamp) >= TimeSpan.FromSeconds(_proximitySensorDistanceThresholdTimeSec))
                    {
                        _proximitySensorReadingBuffer.Clear();
                        evaluateResult = true;
                    }
                    else if (_proximitySensorReadingBuffer.Count > 0 && _lastProximitySensorReading.Timestamp.Subtract(_proximitySensorReadingBuffer.Peek().Timestamp) >= TimeSpan.FromSeconds(_proximitySensorDistanceThresholdTimeSec))
                    {
                        while (_proximitySensorReadingBuffer.Count > 0 && _lastProximitySensorReading.Timestamp.Subtract(_proximitySensorReadingBuffer.Peek().Timestamp) >= TimeSpan.FromSeconds(_proximitySensorDistanceThresholdTimeSec))
                        {
                            _proximitySensorReadingBuffer.Dequeue();
                        }

                        while (_proximitySensorReadingBuffer.Count > 0 &&
                            _proximitySensorReadingBuffer.Peek().DistanceInMillimeters * (100.0f + _proximitySensorDistanceThresholdPercent) / 100.0f >= _lastProximitySensorReading.DistanceInMillimeters &&
                            _lastProximitySensorReading.DistanceInMillimeters * (100.0f + _proximitySensorDistanceThresholdPercent) / 100.0f >= _proximitySensorReadingBuffer.Peek().DistanceInMillimeters)
                        {
                            _proximitySensorReadingBuffer.Dequeue();
                        }
                        evaluateResult = true;
                    }

                    if (evaluateResult && (_proximitySensorReadingBuffer.Count == 0))
                    {
                        int errorPercent = _proximitySensorDefaultErrorPercent;
                        bool parsedSuccess = Int32.TryParse(ManualErrorMarginPercentTextBox.Text, out errorPercent);
                        if (!parsedSuccess || (errorPercent > _proximitySensorMaxErrorPercent))
                        {
                            errorPercent = _proximitySensorDefaultErrorPercent;
                        }

                        if (_proximityDistancesMm[_currentManualDistance] * (100.0f + errorPercent) / 100.0f >= _lastProximitySensorReading.DistanceInMillimeters &&
                            _lastProximitySensorReading.DistanceInMillimeters * (100.0f + errorPercent) / 100.0f >= _proximityDistancesMm[_currentManualDistance])
                        {
                            SuccessImage.Visibility = Visibility.Visible;
                            _currentState = DistanceState.TapeMeasureSingleTestPassScreen;
                            _manualDistancesSucceeded[_currentManualDistance] = true;
                        }
                        else
                        {
                            FailureImage.Visibility = Visibility.Visible;
                            _currentState = DistanceState.TapeMeasureSingleTestFailedScreen;
                            _manualDistancesSucceeded[_currentManualDistance] = false;
                        }
                        _currentCountdown = GetCurrentTimeout();

                        _manualTargetDistances.Add(_proximityDistancesMm[_currentManualDistance]);
                        _manualTargetTimestamps.Add(DateTime.Now);
                        _manualTargetDistances.Add(0);
                        _manualTargetTimestamps.Add(DateTime.Now);
                    }

                    if (_currentCountdown <= 0)
                    {
                        FailureImage.Visibility = Visibility.Visible;
                        _currentState = DistanceState.TapeMeasureSingleTestFailedScreen;
                        _manualDistancesSucceeded[_currentManualDistance] = false;
                        _currentCountdown = GetCurrentTimeout();
                        _proximitySensorReadingBuffer.Clear();

                        _manualTargetDistances.Add(_proximityDistancesMm[_currentManualDistance]);
                        _manualTargetTimestamps.Add(DateTime.Now);
                        _manualTargetDistances.Add(0);
                        _manualTargetTimestamps.Add(DateTime.Now);
                    }
                    break;
                case DistanceState.TapeMeasureSingleTestPassScreen:
                case DistanceState.TapeMeasureSingleTestFailedScreen:
                    _singleResultWaitTimer++;
                    if (_singleResultWaitTimer >= _singleResultTotalWaitTimer)
                    {
                        SuccessImage.Visibility = Visibility.Collapsed;
                        FailureImage.Visibility = Visibility.Collapsed;
                        _currentManualDistance++;
                        if (_currentManualDistance >= _proximityDistancesMm.Length)
                        {
                            PassedDistances.Text = "Passed Distances: ";
                            FailedDistances.Text = "Failed Distances: ";
                            for (int i = 0; i < _manualDistancesSucceeded.Length; i++)
                            {
                                if (_manualDistancesSucceeded[i])
                                {
                                    if (PassedDistances.Text[PassedDistances.Text.Length - 1] != ' ')
                                    {
                                        PassedDistances.Text += ", ";
                                    }
                                    PassedDistances.Text += _proximityDistancesMm[i] + "mm";
                                }
                                else
                                {
                                    if (FailedDistances.Text[FailedDistances.Text.Length - 1] != ' ')
                                    {
                                        FailedDistances.Text += ", ";
                                    }
                                    FailedDistances.Text += _proximityDistancesMm[i] + "mm";
                                }
                            }

                            List<List<int>> distanceMatrix = new List<List<int>>();
                            List<List<DateTimeOffset>> timestampMatrix = new List<List<DateTimeOffset>>();

                            string[] vAxisLabel = new string[_plotYNumIntervals + 1];
                            for (int i = 0; i <= _plotYNumIntervals; i++)
                            {
                                vAxisLabel[i] = (_maxDistancePlotMm - Convert.ToDouble(i) / _plotYNumIntervals * (_maxDistancePlotMm - _minDistancePlotMm)).ToString();
                            }

                            _plotCanvas = new PlotCanvas(_minDistancePlotMm, _maxDistancePlotMm, Constants.ProximitySensorColors, ManualResultsPlot, vAxisLabel);

                            distanceMatrix.Add(_manualProximityDistances);
                            timestampMatrix.Add(_manualProximityTimestamps);
                            distanceMatrix.Add(_manualTargetDistances);
                            timestampMatrix.Add(_manualTargetTimestamps);

                            _plotCanvas.PlotGroup(distanceMatrix, timestampMatrix);

                            ManualResultsPanel.Visibility = Visibility.Visible;
                            ManualPanel.Visibility = Visibility.Collapsed;
                            ManualLongTextTextBox.Visibility = Visibility.Visible;
                            ProximityImageManual.Visibility = Visibility.Visible;
                            ManualCustomConfigOptionsTextBox.Visibility = Visibility.Visible;
                            ManualErrorMarginPercentTextBox.Visibility = Visibility.Visible;
                            TestTimeLengthInSecondsTextBox.Visibility = Visibility.Visible;
                            StartManualTestsButton.Visibility = Visibility.Visible;
                            ManualGoToDistanceTextBox.Visibility = Visibility.Collapsed;
                            CurrentTimerTextBox.Visibility = Visibility.Collapsed;
                            ManualDistanceTextBox.Visibility = Visibility.Collapsed;
                            CurrentDistanceFromSensorTextBox.Visibility = Visibility.Collapsed;
                            _currentState = DistanceState.TapeMeasureResultsScreen;
                            _currentManualDistance = 0;
                            ManualDistanceTextBox.Text = _proximityDistancesMm[_currentManualDistance] + "mm";
                            ManualDistanceTextBox.Foreground = new SolidColorBrush(_manualTestColors[_currentManualDistance]);
                            ManualGoToDistanceTextBox.Foreground = new SolidColorBrush(_manualTestColors[_currentManualDistance]);
                        }
                        else
                        {
                            ManualDistanceTextBox.Text = _proximityDistancesMm[_currentManualDistance] + "mm";
                            ManualDistanceTextBox.Foreground = new SolidColorBrush(_manualTestColors[_currentManualDistance]);
                            ManualGoToDistanceTextBox.Foreground = new SolidColorBrush(_manualTestColors[_currentManualDistance]);
                            _currentState = DistanceState.TapeMeasureTargetDistanceScreen;
                            _proximitySensorReadingBuffer.Clear();
                        }
                        _singleResultWaitTimer = 0;
                    }
                    break;
                case DistanceState.CameraTestsMoveBackScreen:
                    if (_cameraReadingTimeStamps.Count > 0)
                    {
                        if (_lastCameraDistanceMm > _stopMovingBackwardsThresholdMm)
                        {
                            MoveDirectionTextBox.Text = "Move forwards!";
                            MoveDirectionTextBox.Foreground = new SolidColorBrush(Colors.DarkMagenta);
                            _currentState = DistanceState.CameraTestsMoveForwardScreen;
                        }
                    }
                    break;
                case DistanceState.CameraTestsMoveForwardScreen:
                    if (_lastCameraDistanceMm < _stopMovingForwardThresholdMm)
                    {
                        if (_proximitySensorReadingBuffer.Count == 0)
                        {
                            CloseDistancesRatio.Text = "Proximity Sensor did not report any samples.";
                            MediumDistancesRatio.Text = "Please check your sensor on the View page";
                            FarDistancesRatio.Text = "";
                            AutoPlotHeader1.Visibility = Visibility.Collapsed;
                            AutoPlotHeader2.Visibility = Visibility.Collapsed;
                            AutoPlotHeader3.Visibility = Visibility.Collapsed;
                            AutoResultsPlot.Visibility = Visibility.Collapsed;
                        }
                        else
                        {
                            int closeTotalDistanceCount = 0;
                            int closeGoodDistanceCount = 0;
                            int mediumTotalDistanceCount = 0;
                            int mediumGoodDistanceCount = 0;
                            int farTotalDistanceCount = 0;
                            int farGoodDistanceCount = 0;
                            ProximitySensorReading previousSensorReading = _proximitySensorReadingBuffer.Peek();

                            List<List<int>> distanceMatrix = new List<List<int>>();
                            List<List<DateTimeOffset>> timestampMatrix = new List<List<DateTimeOffset>>();

                            List<int> proximityDistances = new List<int>();
                            List<DateTimeOffset> proximityTimestamps = new List<DateTimeOffset>();
                            List<int> cameraDistances = new List<int>();
                            List<DateTimeOffset> cameraTimestamps = new List<DateTimeOffset>();

                            // For each camera reading, find the sensor reading with the timestamp slightly before it and the timestamp after it. Use the value closest to the real distance
                            while (_cameraReadingTimeStamps.Count > 0)
                            {
                                int curCameraDistanceMm = _cameraReadingDistancesMm.Peek();
                                DateTimeOffset curCameraTimestamp = _cameraReadingTimeStamps.Peek();
                                while ((_proximitySensorReadingBuffer.Count > 0) && (_proximitySensorReadingBuffer.Peek().Timestamp < curCameraTimestamp))
                                {
                                    previousSensorReading = _proximitySensorReadingBuffer.Peek();
                                    proximityDistances.Add((int)previousSensorReading.DistanceInMillimeters);
                                    proximityTimestamps.Add(previousSensorReading.Timestamp);
                                    _proximitySensorReadingBuffer.Dequeue();
                                }

                                ProximitySensorReading nextSensorReading = previousSensorReading;
                                if (_proximitySensorReadingBuffer.Count > 0)
                                {
                                    nextSensorReading = _proximitySensorReadingBuffer.Peek();
                                }

                                int changeBetweenCameraAndPrevSensorDistanceMm = Math.Abs(curCameraDistanceMm - (int)(previousSensorReading.DistanceInMillimeters));
                                int changeBetweenCameraAndNextSensorDistanceMm = Math.Abs(curCameraDistanceMm - (int)(nextSensorReading.DistanceInMillimeters));

                                int errorPercent = _proximitySensorDefaultErrorPercent;
                                bool parsedSuccess = Int32.TryParse(AutoErrorMarginPercentTextBox.Text, out errorPercent);
                                if (!parsedSuccess || (errorPercent > _proximitySensorMaxErrorPercent))
                                {
                                    errorPercent = _proximitySensorDefaultErrorPercent;
                                }

                                if (Math.Min(changeBetweenCameraAndNextSensorDistanceMm, changeBetweenCameraAndPrevSensorDistanceMm) * 100.0f <= curCameraDistanceMm * errorPercent)
                                {
                                    if (curCameraDistanceMm > _midToFarDistanceCutoffMm)
                                    {
                                        farGoodDistanceCount++;
                                    }
                                    else if (curCameraDistanceMm < _closeToMidDistanceCutoffMm)
                                    {
                                        closeGoodDistanceCount++;
                                    }
                                    else
                                    {
                                        mediumGoodDistanceCount++;
                                    }
                                }

                                if (curCameraDistanceMm > _midToFarDistanceCutoffMm)
                                {
                                    farTotalDistanceCount++;
                                }
                                else if (curCameraDistanceMm < _closeToMidDistanceCutoffMm)
                                {
                                    closeTotalDistanceCount++;
                                }
                                else
                                {
                                    mediumTotalDistanceCount++;
                                }
                                cameraDistances.Add(_cameraReadingDistancesMm.Peek());
                                cameraTimestamps.Add(_cameraReadingTimeStamps.Peek());
                                _cameraReadingDistancesMm.Dequeue();
                                _cameraReadingTimeStamps.Dequeue();
                            }

                            while (_proximitySensorReadingBuffer.Count > 0)
                            {
                                previousSensorReading = _proximitySensorReadingBuffer.Peek();
                                proximityDistances.Add((int)previousSensorReading.DistanceInMillimeters);
                                proximityTimestamps.Add(previousSensorReading.Timestamp);
                                _proximitySensorReadingBuffer.Dequeue();
                            }
                            CloseDistancesRatio.Text = "Close Distances (<" + _closeToMidDistanceCutoffMm + "mm) Success Ratio: " + closeGoodDistanceCount + "/" + closeTotalDistanceCount + "=" + (int)(100.0f * closeGoodDistanceCount / Math.Max(closeTotalDistanceCount, 1)) + "%";
                            MediumDistancesRatio.Text = "Medium Distances (" + _closeToMidDistanceCutoffMm + "-" + _midToFarDistanceCutoffMm + "mm) Success Ratio: " + mediumGoodDistanceCount + "/" + mediumTotalDistanceCount + "=" + (int)(100.0f * mediumGoodDistanceCount / Math.Max(mediumTotalDistanceCount, 1)) + "%";
                            FarDistancesRatio.Text = "Far Distances(>" + _midToFarDistanceCutoffMm + "mm) Success Ratio: " + farGoodDistanceCount + "/" + farTotalDistanceCount + "=" + (int)(100.0f * farGoodDistanceCount / Math.Max(farTotalDistanceCount, 1)) + "%";
                            AutoPlotHeader1.Visibility = Visibility.Visible;
                            AutoPlotHeader2.Visibility = Visibility.Visible;
                            AutoPlotHeader3.Visibility = Visibility.Visible;
                            AutoResultsPlot.Visibility = Visibility.Visible;

                            string[] vAxisLabel = new string[_plotYNumIntervals + 1];
                            for (int i = 0; i <= _plotYNumIntervals; i++)
                            {
                                vAxisLabel[i] = (_maxDistancePlotMm - Convert.ToDouble(i) / _plotYNumIntervals * (_maxDistancePlotMm - _minDistancePlotMm)).ToString();
                            }

                            _plotCanvas = new PlotCanvas(_minDistancePlotMm, _maxDistancePlotMm, Constants.ProximitySensorColors, AutoResultsPlot, vAxisLabel);

                            distanceMatrix.Add(proximityDistances);
                            timestampMatrix.Add(proximityTimestamps);
                            distanceMatrix.Add(cameraDistances);
                            timestampMatrix.Add(cameraTimestamps);

                            _plotCanvas.PlotGroup(distanceMatrix, timestampMatrix);
                        }
                        PreviewControl.Visibility = Visibility.Collapsed;
                        FacesCanvas.Visibility = Visibility.Collapsed;
                        AutoPanel.Visibility = Visibility.Collapsed;
                        AutomaticLongTextTextBox.Visibility = Visibility.Visible;
                        AutoCustomConfigOptionsTextBox.Visibility = Visibility.Visible;
                        AutoErrorMarginPercentTextBox.Visibility = Visibility.Visible;
                        MoveDirectionTextBox.Visibility = Visibility.Collapsed;
                        StartAutomaticTestsButton.Visibility = Visibility.Visible;
                        AutoResultsPanel.Visibility = Visibility.Visible;
                        _currentState = DistanceState.CameraTestsResultsScreen;


                        await CleanupCameraAsync();
                    }
                    break;
                default: // Do nothing in the other states
                    break;
            }
        }