/// <summary>
        /// Check if the declared goal is conform to the distance rules to other goals
        /// <para>will not check against itself</para>
        /// </summary>
        /// <param name="declaredGoal">the declared goal to be checked</param>
        /// <returns>true: is conform; false: is not conform</returns>
        public bool CheckConformance(DeclaredGoal declaredGoal)
        {
            bool isConform = true;

            foreach (DeclaredGoal otherGoal in DeclaredGoals)
            {
                if (declaredGoal.Equals(otherGoal))
                {
                    continue;
                }
                double distanceBetweenPositionOfDeclarationAndDeclaredGoal = CoordinateHelpers.Calculate2DDistance(declaredGoal.GoalDeclared, otherGoal.GoalDeclared);

                if (!double.IsNaN(MinimumDistance))
                {
                    if (distanceBetweenPositionOfDeclarationAndDeclaredGoal < MinimumDistance)
                    {
                        isConform = false;
                        break;
                    }
                }
                if (!double.IsNaN(MaximumDistance))
                {
                    if (distanceBetweenPositionOfDeclarationAndDeclaredGoal > MaximumDistance)
                    {
                        isConform = false;
                        break;
                    }
                }
            }
            return(isConform);
        }
        public static IEnumerable <string> InitLineSegmentation(AnnotateImageResponse data)
        {
            var yMax = CoordinateHelpers.GetYMax(data);

            data = CoordinateHelpers.InvertAxis(data, yMax);

            // The first index refers to the auto identified words which belongs to a sings line
            var lines = data.TextAnnotations[0].Description.Split('\n');

            // gcp vision full text
            var rawText = new List <EntityAnnotation>();

            for (int i = 1; i < data.TextAnnotations.Count; i++)
            {
                rawText.Add(data.TextAnnotations[i]);
            }

            // reverse to use lifo, because array.shift() will consume 0(n)
            lines = lines.Reverse().ToArray();
            rawText.Reverse();

            var mergedArray = GetMergedLines(lines, rawText);

            var boundingPolygon = CoordinateHelpers.GetBoundingPolygon(mergedArray);

            var combinedPolygon = CoordinateHelpers.CombineBoundingPolygon(boundingPolygon);

            return(ConstructLineWithBoundingPolygon(combinedPolygon));
        }
        /// <summary>
        /// Check if the marker is conform to the distance rules to the other markers
        /// <para>will not check against itself</para>
        /// </summary>
        /// <param name="marker">the marker to be checked</param>
        /// <returns>true: is conform; false: is not conform</returns>
        public bool CheckConformance(MarkerDrop marker)
        {
            bool isConform = true;

            foreach (MarkerDrop markerDrop in MarkerDrops)
            {
                if (marker.Equals(markerDrop))
                {
                    continue;
                }
                double distanceToOtherMarker = CoordinateHelpers.Calculate2DDistance(marker.MarkerLocation, markerDrop.MarkerLocation);
                if (!double.IsNaN(MinimumDistance))
                {
                    if (distanceToOtherMarker < MinimumDistance)
                    {
                        isConform = false;
                    }
                }
                if (!double.IsNaN(MaximumDistance))
                {
                    if (distanceToOtherMarker > MaximumDistance)
                    {
                        isConform = false;
                    }
                }
            }
            return(isConform);
        }
Exemple #4
0
        //private void renderCategoryLabels()
        //{
        //	if (FocusedSegment == null)
        //	{
        //		return;
        //	}
        //	var context = new ProviderContext(Data.Count);
        //	MaterialProvider.Reset(context);
        //	_categoryLabels.Children.Clear();
        //	var diameter = _segments.RenderSize.Smallest() * CircleScale;

        //	var outerLabelRadius = (diameter / 2) * OuterLabelPositionScale;
        //	var overlayedLabelRadius = (diameter / 2) * .7;

        //	var targetAngularOffset = FocusedSegment.RequireType<ArcPath>().CalculateAngularOffset();

        //	foreach (var d in Data)
        //	{
        //		var materialSet = MaterialProvider.ProvideNext(context);
        //		var categoryNameLabel = positionLabel(d, outerLabelRadius, targetAngularOffset, true);

        //		categoryNameLabel.Content = d.CategoryName;
        //		categoryNameLabel.BindTextualPrimitive<BarTotalPrimitive>(this);
        //		categoryNameLabel.Foreground = BarTotalForeground.GetMaterial(materialSet);
        //		_categoryLabels.Children.Add(categoryNameLabel);


        //		var valueLabel = positionLabel(d, overlayedLabelRadius, targetAngularOffset);

        //		valueLabel.Content = d.Value;
        //		valueLabel.BindTextualPrimitive<ValuePrimitive>(this);
        //		valueLabel.Foreground = ValueForeground.GetMaterial(materialSet);
        //		_categoryLabels.Children.Add(valueLabel);
        //	}
        //}

        private Label positionLabel(CategoricalDouble d, double radius, double targetAngularOffset,
                                    bool horizontalPositionSkew = false)
        {
            var categoryLabel = new Label
            {
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment   = VerticalAlignment.Center,
                IsHitTestVisible    = false
            };

            var pretransformedOffset     = d.RenderedVisual.RequireType <ArcPath>().PolarOffset;
            var arcAngle                 = d.RenderedVisual.RequireType <ArcPath>().ArcAngle;
            var pretransformedLabelAngle = pretransformedOffset + (arcAngle / 2);
            var actualLabelAngle         = pretransformedLabelAngle - targetAngularOffset;

            var horizontalLabelSkew = horizontalPositionSkew
                                ? Math.Cos(CoordinateHelpers.ToRadian(actualLabelAngle)) * HorizontalLabelPositionSkew
                                : 0;

            var labelRadius     = radius;
            var polarPoint      = new PolarPoint(actualLabelAngle, labelRadius);
            var labelCoordinate = polarPoint.ToCartesian();

            categoryLabel.Margin = new Thickness(labelCoordinate.X + horizontalLabelSkew, -labelCoordinate.Y,
                                                 -labelCoordinate.X - horizontalLabelSkew, labelCoordinate.Y);
            return(categoryLabel);
        }
Exemple #5
0
        public Point ToCartesian()
        {
            var angleRadian = CoordinateHelpers.ToRadian(Angle);
            var x           = Radius * Math.Cos(angleRadian);
            var y           = Radius * Math.Sin(angleRadian);

            return(new Point(x, y));
        }
Exemple #6
0
        public static PolarPoint FromCartesian(Point point)
        {
            var angle        = Math.Atan2(point.Y, point.X);
            var angleDegrees = CoordinateHelpers.ToDegree(angle);
            var radius       = (point.X.Squared() + point.Y.Squared()).Root();

            return(new PolarPoint(angleDegrees, radius));
        }
Exemple #7
0
 void DrawLine(GameObject ourHitObject)
 {
     if (meshLine == null)
     {
         meshLine = new List <MeshRenderer>();
     }
     if (hoverHex == null)
     {
         hoverHexMesh = ourHitObject.GetComponentInChildren <MeshRenderer>();
         hoverHexMesh.material.color = Color.blue;
         hoverHex = ourHitObject.GetComponentInChildren <Hex>();
     }
     else if (ourHitObject != originHex)
     {
         //Uncolour non selection
         hoverHexMesh.material.color = Color.white;
         //Uncolour old lines
         foreach (MeshRenderer hex in meshLine)
         {
             hex.material.color = Color.white;
         }
         //Colour lines
         List <int[]> line = CoordinateHelpers.CalculateLine(originHex, hoverHex);
         foreach (int[] coordTri in line)
         {
             try {
                 MeshRenderer hexInLine = GameObject.Find("Hex_" + coordTri[0] + "_" + coordTri[1] + "_" + coordTri[2]).GetComponentInChildren <MeshRenderer>();
                 if (hexInLine != hoverHex && hexInLine != hexMesh)
                 {
                     if (CoordinateHelpers.CubeDistance(originHex, hoverHex) <= selectedUnit.movementThisTurn)
                     {
                         hexInLine.material.color = new Color(.35f, .44f, 1f, 1);
                         meshLine.Add(hexInLine);
                     }
                 }
             }
             catch {
                 Debug.Log("Error: " + coordTri[0] + "_" + coordTri[1] + "_" + coordTri[2]);
             }
         }
         hoverHexMesh = ourHitObject.GetComponentInChildren <MeshRenderer>();
         if (CoordinateHelpers.CubeDistance(originHex, hoverHex) <= selectedUnit.movementThisTurn)
         {
             hoverHexMesh.material.color = Color.blue;
         }
         else
         {
             hoverHexMesh.material.color = Color.red;
         }
         hexMesh.material.color = Color.blue;
         hoverHex = ourHitObject.GetComponentInChildren <Hex>();
     }
 }
            /// <summary>
            /// Calculate the 2d distance traveled in the pie tier times the multiplier
            /// </summary>
            /// <param name="track">the track to be used</param>
            /// <param name="useGPSAltitude">true: use GPS altitude;false: use barometric altitude</param>
            /// <param name="result">the 2D distance in the pie tier times the multiplier</param>
            /// <returns>true:success;false:error</returns>
            public bool CalculateTierResult(Track track, bool useGPSAltitude, out double result)
            {
                string functionErrorMessage = $"Failed to calculate result for {this} and Pilot '#{track.Pilot.PilotNumber}{(!string.IsNullOrWhiteSpace(track.Pilot.FirstName) ? $"({track.Pilot.FirstName},{track.Pilot.LastName})" : "")}': ";

                result = 0.0;
                List <(int, Coordinate)> trackPointsInDonut = new List <(int trackPointNumber, Coordinate coordinate)>();

                DeclaredGoal targetGoal = ValidationHelper.GetValidGoal(track, GoalNumber, DeclarationValidationRules);

                if (targetGoal == null)
                {
                    //Debug.WriteLine("No valid goal found");
                    Log(LogSeverityType.Error, functionErrorMessage + $"No valid goal found for goal '#{GoalNumber}'");
                    return(false);
                }
                List <Coordinate> coordinates = track.TrackPoints;

                if (!double.IsNaN(LowerBoundary))
                {
                    if (useGPSAltitude)
                    {
                        coordinates = coordinates.Where(x => x.AltitudeGPS >= LowerBoundary).ToList();//take all point above lower boundary
                    }
                    else
                    {
                        coordinates = coordinates.Where(x => x.AltitudeBarometric >= LowerBoundary).ToList();//take all point above lower boundary
                    }
                }
                if (!double.IsNaN(UpperBoundary))
                {
                    if (useGPSAltitude)
                    {
                        coordinates = coordinates.Where(x => x.AltitudeGPS <= UpperBoundary).ToList();//take all points below upper boundary
                    }
                    else
                    {
                        coordinates = coordinates.Where(x => x.AltitudeBarometric <= UpperBoundary).ToList();//take all points below upper boundary
                    }
                }

                for (int index = 0; index < coordinates.Count; index++)
                {
                    double distanceToGoal = CoordinateHelpers.Calculate2DDistance(coordinates[index], targetGoal.GoalDeclared); //calculate distance to goal
                    if (distanceToGoal <= Radius)                                                                               //save all trackpoints within the radius
                    {
                        trackPointsInDonut.Add((index, coordinates[index]));
Exemple #9
0
    void OnHexClick(GameObject ourHitObject)
    {
        // if (Input.GetMouseButtonDown(0)) {

        //  //ColorHex(ourHitObject);
        //  SetLineOrigin(ourHitObject);

        // }
        if (Input.GetMouseButtonDown(1))
        {
            if (selectedUnit != null)
            {
                if (CoordinateHelpers.CubeDistance(originHex, hoverHex) <= selectedUnit.movementThisTurn && gamecontroller.playersTurn == selectedUnit.playerOwned.playerNumber)
                {
                    selectedUnit.MoveToHex(ourHitObject.GetComponent <Hex>(), CoordinateHelpers.CubeDistance(originHex, hoverHex));
                    SetLineOrigin(selectedUnit.currentHex.gameObject);
                }
            }
        }
    }
Exemple #10
0
        /// <summary>
        /// Check if the declared goal is conform to the distance rules
        /// </summary>
        /// <param name="declaredGoal">the declared goal to be checked</param>
        /// <returns>true: is conform; false: is not conform</returns>
        public bool CheckConformance(DeclaredGoal declaredGoal)
        {
            bool   isConform = true;
            double distanceBetweenPositionOfDeclarationAndDeclaredGoal = CoordinateHelpers.Calculate2DDistance(declaredGoal.PositionAtDeclaration, declaredGoal.GoalDeclared);

            if (!double.IsNaN(MinimumDistance))
            {
                if (distanceBetweenPositionOfDeclarationAndDeclaredGoal < MinimumDistance)
                {
                    isConform = false;
                }
            }
            if (!double.IsNaN(MaximumDistance))
            {
                if (distanceBetweenPositionOfDeclarationAndDeclaredGoal > MaximumDistance)
                {
                    isConform = false;
                }
            }
            return(isConform);
        }
        /// <summary>
        /// Check if the marker is conform to the distance rules to the declared goal
        /// </summary>
        /// <param name="marker">the marker to be checked</param>
        /// <returns>true: is conform; false: is not conform</returns>
        public bool CheckConformance(MarkerDrop marker)
        {
            bool   isConform      = true;
            double distanceToGoal = CoordinateHelpers.Calculate2DDistance(marker.MarkerLocation, Goal.GoalDeclared);

            if (!double.IsNaN(MinimumDistance))
            {
                if (distanceToGoal < MinimumDistance)
                {
                    isConform = false;
                }
            }
            if (!double.IsNaN(MaximumDistance))
            {
                if (distanceToGoal > MaximumDistance)
                {
                    isConform = false;
                }
            }
            return(isConform);
        }
        /// <summary>
        /// Validates the user input and creates new / modifies exsiting declaration to goal distance rule
        /// </summary>
        /// <param name="sender">sender of the event</param>
        /// <param name="e">event arguments</param>
        private void btCreate_Click(object sender, EventArgs e)
        {
            bool   isDataValid          = true;
            string functionErrorMessage = "Failed to create/modify declaration to goal distance rule: ";
            double minimumDistance      = double.NaN;

            if (!string.IsNullOrWhiteSpace(tbMinimumDistance.Text))
            {
                if (!double.TryParse(tbMinimumDistance.Text, out minimumDistance))
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Failed to parse Min. Distance '{tbMinimumDistance.Text}' as double");
                    isDataValid = false;
                }
                if (minimumDistance < 0)
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Min. Distance '{minimumDistance}' must be greater than zero");
                    isDataValid = false;
                }

                if (rbMinimumDistanceFeet.Checked)
                {
                    minimumDistance = CoordinateHelpers.ConvertToMeter(minimumDistance);
                }
            }
            double maximumDistance = double.NaN;

            if (!string.IsNullOrWhiteSpace(tbMaximumDistance.Text))
            {
                if (!double.TryParse(tbMaximumDistance.Text, out maximumDistance))
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Failed to parse Max. Distance '{tbMinimumDistance.Text}' as double");
                    isDataValid = false;
                }
                if (maximumDistance < 0)
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Max. Distance '{maximumDistance}' must be greater than zero");
                    isDataValid = false;
                }

                if (rbMaximumDistanceFeet.Checked)
                {
                    maximumDistance = CoordinateHelpers.ConvertToMeter(maximumDistance);
                }
            }
            if (!double.IsNaN(minimumDistance) && !double.IsNaN(maximumDistance))
            {
                if (minimumDistance >= maximumDistance)
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Min. Distance '{minimumDistance}[m]' must be smaller than Max. Distance '{maximumDistance}[m]'");
                    isDataValid = false;
                }
            }

            if (isDataValid)
            {
                DeclarationToGoalDistanceRule ??= new DeclarationToGoalDistanceRule();
                DeclarationToGoalDistanceRule.SetupRule(minimumDistance, maximumDistance);
                tbMaximumDistance.Text = "";
                tbMinimumDistance.Text = "";
                OnDataValid();
            }
        }
        /// <summary>
        /// Validates the user input and creates new / modifies exsiting goal to other goals distance rule
        /// </summary>
        /// <param name="sender">sender of the event</param>
        /// <param name="e">event arguments</param>
        private void btCreate_Click(object sender, EventArgs e)
        {
            bool   isDataValid          = true;
            string functionErrorMessage = "Failed to create/modify goal to other goals distance rule: ";
            double minimumDistance      = double.NaN;

            if (!string.IsNullOrWhiteSpace(tbMinimumDistance.Text))
            {
                if (!double.TryParse(tbMinimumDistance.Text, out minimumDistance))
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Failed to parse Min. Distance '{tbMinimumDistance.Text}' as double");
                    isDataValid = false;
                }
                if (minimumDistance < 0)
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Min. Distance '{minimumDistance}' must be greater than zero");
                    isDataValid = false;
                }

                if (rbMinimumDistanceFeet.Checked)
                {
                    minimumDistance = CoordinateHelpers.ConvertToMeter(minimumDistance);
                }
            }
            double maximumDistance = double.NaN;

            if (!string.IsNullOrWhiteSpace(tbMaximumDistance.Text))
            {
                if (!double.TryParse(tbMaximumDistance.Text, out maximumDistance))
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Failed to parse Max. Distance '{tbMinimumDistance.Text}' as double");
                    isDataValid = false;
                }
                if (maximumDistance < 0)
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Max. Distance '{maximumDistance}' must be greater than zero");
                    isDataValid = false;
                }

                if (rbMaximumDistanceFeet.Checked)
                {
                    maximumDistance = CoordinateHelpers.ConvertToMeter(maximumDistance);
                }
            }
            if (!double.IsNaN(minimumDistance) && !double.IsNaN(maximumDistance))
            {
                if (minimumDistance >= maximumDistance)
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Min. Distance '{minimumDistance}[m]' must be smaller than Max. Distance '{maximumDistance}[m]'");
                    isDataValid = false;
                }
            }

            List <int> goalNumbers = new List <int>();

            if (!string.IsNullOrWhiteSpace(tbGoalNumbers.Text))
            {
                if (tbGoalNumbers.Text.ToLowerInvariant() != "all")
                {
                    goalNumbers = Array.ConvertAll(tbGoalNumbers.Text.Split(','), int.Parse).ToList();
                }
            }



            if (isDataValid)
            {
                GoalToOtherGoalsDistanceRule ??= new GoalToOtherGoalsDistanceRule();
                GoalToOtherGoalsDistanceRule.SetupRule(minimumDistance, maximumDistance, goalNumbers);
                tbMinimumDistance.Text = "";
                tbMaximumDistance.Text = "";
                tbGoalNumbers.Text     = "";
                OnDataValid();
            }
        }
Exemple #14
0
 internal void UpdatePosition()
 {
     MapCoords          = new MapCoordinates(data.latitude, data.longitude);
     UnityCoords        = CoordinateHelpers.MapCoordinatesToUnity(MapCoords);
     transform.position = new Vector3(UnityCoords.X, 1f, UnityCoords.Y);
 }
        /// <summary>
        /// Calculate the area of the triangle specified by the three markers in square meter
        /// </summary>
        /// <param name="track">the track to be used</param>
        /// <param name="useGPSAltitude">true: use GPS altitude;false: use barometric altitude</param>
        /// <param name="result">the area of the triangle in square meter</param>
        /// <returns>true:success;false:error</returns>
        public bool CalculateResults(Track track, bool useGPSAltitude, out double result)
        {
            string functionErrorMessage = $"Failed to calculate result for {this} and Pilot '#{track.Pilot.PilotNumber}{(!string.IsNullOrWhiteSpace(track.Pilot.FirstName)?$"({track.Pilot.FirstName},{track.Pilot.LastName})":"")}': ";

            result = 0.0;
            //MarkerDrop firstMarker = track.MarkerDrops.FirstOrDefault(x => x.MarkerNumber == FirstMarkerNumber);
            //if (firstMarker == null)
            //{
            //    //Console.WriteLine($"No Marker '{FirstMarkerNumber}' found");
            //    Log(LogSeverityType.Error, functionErrorMessage + $"No Marker '{FirstMarkerNumber}' found");
            //    return false;
            //}
            //if (!ValidationHelper.IsMarkerValid(firstMarker, MarkerValidationRules))
            //{
            //    //Console.WriteLine($"Marker '{FirstMarkerNumber}' is not valid");
            //    Log(LogSeverityType.Error, functionErrorMessage + $"Marker '{FirstMarkerNumber}' is invalid");
            //    return false;
            //}
            if (!ValidationHelper.IsMarkerValid(track, FirstMarkerNumber, MarkerValidationRules))
            {
                //Console.WriteLine($"Marker '{FirstMarkerNumber}' is not valid");
                Log(LogSeverityType.Error, functionErrorMessage + $"Marker '{FirstMarkerNumber}' is invalid or doesn't exists");
                return(false);
            }
            //MarkerDrop secondMarker = track.MarkerDrops.FirstOrDefault(x => x.MarkerNumber == SecondMarkerNumber);
            //if (secondMarker == null)
            //{
            //    //Console.WriteLine($"No Marker '{SecondMarkerNumber}' found");
            //    Log(LogSeverityType.Error, functionErrorMessage + $"No Marker '{SecondMarkerNumber}' found");
            //    return false;
            //}
            //if (!ValidationHelper.IsMarkerValid(secondMarker, MarkerValidationRules))
            //{
            //    //Console.WriteLine($"Marker '{SecondMarkerNumber}' is not valid");
            //    Log(LogSeverityType.Error, functionErrorMessage + $"Marker '{SecondMarkerNumber}' is invalid");
            //    return false;
            //}
            if (!ValidationHelper.IsMarkerValid(track, SecondMarkerNumber, MarkerValidationRules))
            {
                //Console.WriteLine($"Marker '{SecondMarkerNumber}' is not valid");
                Log(LogSeverityType.Error, functionErrorMessage + $"Marker '{SecondMarkerNumber}' is invalid or doesn't exists");
                return(false);
            }
            //MarkerDrop thirdMarker = track.MarkerDrops.FirstOrDefault(x => x.MarkerNumber == ThirdMarkerNumber);
            //if (thirdMarker == null)
            //{
            //    //Console.WriteLine($"No Marker '{ThirdMarkerNumber}' found");
            //    Log(LogSeverityType.Error, functionErrorMessage + $"No Marker '{ThirdMarkerNumber}' found");
            //    return false;
            //}
            //if (!ValidationHelper.IsMarkerValid(thirdMarker, MarkerValidationRules))
            //{
            //    //Console.WriteLine($"Marker '{ThirdMarkerNumber}' is not valid");
            //    Log(LogSeverityType.Error, functionErrorMessage + $"Marker '{ThirdMarkerNumber}' is invalid");
            //    return false;
            //}
            if (!ValidationHelper.IsMarkerValid(track, ThirdMarkerNumber, MarkerValidationRules))
            {
                //Console.WriteLine($"Marker '{ThirdMarkerNumber}' is not valid");
                Log(LogSeverityType.Error, functionErrorMessage + $"Marker '{ThirdMarkerNumber}' is invalid or doesn't exists");
                return(false);
            }
            MarkerDrop firstMarker  = track.MarkerDrops.FirstOrDefault(x => x.MarkerNumber == FirstMarkerNumber);
            MarkerDrop secondMarker = track.MarkerDrops.FirstOrDefault(x => x.MarkerNumber == SecondMarkerNumber);
            MarkerDrop thirdMarker  = track.MarkerDrops.FirstOrDefault(x => x.MarkerNumber == ThirdMarkerNumber);

            result = CoordinateHelpers.CalculateArea(firstMarker.MarkerLocation, secondMarker.MarkerLocation, thirdMarker.MarkerLocation);
            return(true);
        }
Exemple #16
0
        /// <summary>
        /// Validates user input and creates a new pie tier / modifies the existing pie tier
        /// </summary>
        /// <param name="sender">sender of the event</param>
        /// <param name="e">event arguments</param>
        private void btCreate_Click(object sender, EventArgs e)
        {
            bool   isDataValid          = true;
            string functionErrorMessage = "Failed to create/modify pie tier: ";
            int    goalNumber;

            if (!int.TryParse(tbGoalNumber.Text, out goalNumber))
            {
                Log(LogSeverityType.Error, functionErrorMessage + $"Failed to parse Goal No. '{tbGoalNumber.Text}' as integer");
                isDataValid = false;
            }
            if (goalNumber <= 0)
            {
                Log(LogSeverityType.Error, functionErrorMessage + $"Goal No. must be greater than 0");
                isDataValid = false;
            }
            double radius;

            if (!double.TryParse(tbRadius.Text, out radius))
            {
                Log(LogSeverityType.Error, functionErrorMessage + $"Failed to parse Radius '{tbRadius.Text}' as double");
                isDataValid = false;
            }
            if (rbRadiusFeet.Checked)
            {
                radius = CoordinateHelpers.ConvertToMeter(radius);
            }
            bool   isReentranceAllowed = cbIsReetranceAllowed.Checked;
            double multiplier;

            if (!double.TryParse(tbMultiplier.Text, out multiplier))
            {
                Log(LogSeverityType.Error, functionErrorMessage + $"Failed to parse Multiplier '{tbMultiplier.Text}' as double");
                isDataValid = false;
            }

            double lowerBoundary = double.NaN;

            if (!string.IsNullOrWhiteSpace(tbLowerBoundary.Text))
            {
                if (!double.TryParse(tbLowerBoundary.Text, out lowerBoundary))
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Failed to parse Lower Boundary '{tbLowerBoundary.Text}' as double");
                    isDataValid = false;
                }
                if (!double.IsNaN(lowerBoundary))
                {
                    if (rbLowerBoundaryFeet.Checked)
                    {
                        lowerBoundary = CoordinateHelpers.ConvertToMeter(lowerBoundary);
                    }
                }
            }
            double upperBoundary = double.NaN;

            if (!string.IsNullOrWhiteSpace(tbUpperBoundary.Text))
            {
                if (!double.TryParse(tbUpperBoundary.Text, out upperBoundary))
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Failed to parse Upper Boundary '{tbUpperBoundary.Text}' as double");
                    isDataValid = false;
                }
                if (!double.IsNaN(upperBoundary))
                {
                    if (rbUpperBoundaryFeet.Checked)
                    {
                        upperBoundary = CoordinateHelpers.ConvertToMeter(upperBoundary);
                    }
                }
            }
            if (!double.IsNaN(lowerBoundary) && double.IsNaN(upperBoundary))
            {
                if (lowerBoundary >= upperBoundary)
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Lower Boundary '{lowerBoundary}[m]' must be smaller than Upper Boundary '{upperBoundary}[m]'");
                    isDataValid = false;
                }
            }
            //TODO add goal validations;
            if (isDataValid)
            {
                if (!IsExisting)
                {
                    Tier = new PieTask.PieTier();
                }
                List <IDeclarationValidationRules> declarationValidationRules = new List <IDeclarationValidationRules>();
                foreach (object item in lbRules.Items)
                {
                    if (item is IDeclarationValidationRules)
                    {
                        if (!Tier.DeclarationValidationRules.Contains(item as IDeclarationValidationRules))
                        {
                            declarationValidationRules.Add(item as IDeclarationValidationRules);
                        }
                    }
                }
                Tier.SetupPieTier(goalNumber, radius, isReentranceAllowed, multiplier, lowerBoundary, upperBoundary, declarationValidationRules);
                IsExisting           = false;
                tbGoalNumber.Text    = "";
                tbRadius.Text        = "";
                tbMultiplier.Text    = "";
                tbLowerBoundary.Text = "";
                tbUpperBoundary.Text = "";
                lbRules.Items.Clear();
                OnDataValid();
            }
        }
        /// <summary>
        /// Validates user input and creates new donut task / modifies the existing donut task
        /// </summary>
        /// <param name="sender">sender of the event</param>
        /// <param name="e">event arguments</param>
        private void btCreate_Click(object sender, EventArgs e)
        {
            bool   isDataValid          = true;
            string functionErrorMessage = "Failed to create/modify donut task: ";
            int    taskNumber;

            if (!int.TryParse(tbTaskNumber.Text, out taskNumber))
            {
                Log(LogSeverityType.Error, functionErrorMessage + $"Failed to parse Task No. '{tbTaskNumber.Text}' as integer");
                isDataValid = false;
            }
            if (taskNumber <= 0)
            {
                Log(LogSeverityType.Error, functionErrorMessage + $"Task No. must be greater than 0");
                isDataValid = false;
            }
            int goalNumber;

            if (!int.TryParse(tbGoalNumber.Text, out goalNumber))
            {
                Log(LogSeverityType.Error, functionErrorMessage + $"Failed to parse Goal No. '{tbGoalNumber.Text}' as integer");
                isDataValid = false;
            }
            if (goalNumber <= 0)
            {
                Log(LogSeverityType.Error, functionErrorMessage + $"Goal No. must be greater than 0");
                isDataValid = false;
            }
            double innerRadius;

            if (!double.TryParse(tbInnerRadius.Text, out innerRadius))
            {
                Log(LogSeverityType.Error, functionErrorMessage + $"Failed to parse Inner Radius '{tbInnerRadius.Text}' as double");
                isDataValid = false;
            }
            if (rbInnerRadiusFeet.Checked)
            {
                innerRadius = CoordinateHelpers.ConvertToMeter(innerRadius);
            }
            double outerRadius;

            if (!double.TryParse(tbOuterRadius.Text, out outerRadius))
            {
                Log(LogSeverityType.Error, functionErrorMessage + $"Failed to parse Outer Radius '{tbOuterRadius.Text}' as double");
                isDataValid = false;
            }
            if (rbOuterRadiusFeet.Checked)
            {
                outerRadius = CoordinateHelpers.ConvertToMeter(outerRadius);
            }

            if (innerRadius >= outerRadius)
            {
                Log(LogSeverityType.Error, functionErrorMessage + $"Inner Radius '{innerRadius}[m]' must be smaller than Outer Radius '{outerRadius}[m]'");
                isDataValid = false;
            }
            bool   isReentranceAllowed = cbIsReetranceAllowed.Checked;
            double lowerBoundary       = double.NaN;

            if (!string.IsNullOrWhiteSpace(tbLowerBoundary.Text))
            {
                if (!double.TryParse(tbLowerBoundary.Text, out lowerBoundary))
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Failed to parse Lower Boundary '{tbLowerBoundary.Text}' as double");
                    isDataValid = false;
                }
                if (!double.IsNaN(lowerBoundary))
                {
                    if (rbLowerBoundaryFeet.Checked)
                    {
                        lowerBoundary = CoordinateHelpers.ConvertToMeter(lowerBoundary);
                    }
                }
            }
            double upperBoundary = double.NaN;

            if (!string.IsNullOrWhiteSpace(tbUpperBoundary.Text))
            {
                if (!double.TryParse(tbUpperBoundary.Text, out upperBoundary))
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Failed to parse Upper Boundary '{tbUpperBoundary.Text}' as double");
                    isDataValid = false;
                }
                if (!double.IsNaN(upperBoundary))
                {
                    if (rbUpperBoundaryFeet.Checked)
                    {
                        upperBoundary = CoordinateHelpers.ConvertToMeter(upperBoundary);
                    }
                }
            }
            if (!double.IsNaN(lowerBoundary) && double.IsNaN(upperBoundary))
            {
                if (lowerBoundary >= upperBoundary)
                {
                    Log(LogSeverityType.Error, functionErrorMessage + $"Lower Boundary '{lowerBoundary}[m]' must be smaller than Upper Boundary '{upperBoundary}[m]'");
                    isDataValid = false;
                }
            }
            //TODO add goal validations;
            if (isDataValid)
            {
                Donut ??= new DonutTask();
                List <IDeclarationValidationRules> declarationValidationRules = new List <IDeclarationValidationRules>();
                foreach (object item in lbRules.Items)
                {
                    if (item is IDeclarationValidationRules)
                    {
                        if (!Donut.DeclarationValidationRules.Contains(item as IDeclarationValidationRules))
                        {
                            declarationValidationRules.Add(item as IDeclarationValidationRules);
                        }
                    }
                }

                Donut.SetupDonut(taskNumber, goalNumber, 1, innerRadius, outerRadius, lowerBoundary, upperBoundary, isReentranceAllowed, declarationValidationRules);

                tbTaskNumber.Text    = "";
                tbGoalNumber.Text    = "";
                tbInnerRadius.Text   = "";
                tbOuterRadius.Text   = "";
                tbLowerBoundary.Text = "";
                tbUpperBoundary.Text = "";
                lbRules.Items.Clear();
                OnDataValid();
            }
        }