public FieldingResult GetFieldingResult(FieldingStint fielder, PositionType positionType, InfieldShiftType infieldShiftType, OutfieldShiftType outfieldShiftType)
        {
            // update these for shifts
            // add metrics for range and hits
            var random       = new Random();
            var randomResult = random.Next(0, 1001);

            if (fielder == null)
            {
                fielder = FieldingStintHelperFunctions.CreateFieldingStintForPlayerOutOfPosition(positionType);
            }

            var successThreshold = ((double)fielder.Errors / (fielder.Putouts + fielder.Errors + fielder.Assists)) * 1000;

            if (randomResult <= successThreshold)
            {
                randomResult = random.Next(0, 100);
                if (randomResult < 90)
                {
                    return(FieldingResult.OneBaseError);
                }
                else if (randomResult < 98)
                {
                    return(FieldingResult.TwoBaseError);
                }
                return(FieldingResult.ThreeBaseError);
            }
            randomResult = random.Next(0, 100);
            if (randomResult < 65)
            {
                if (positionType == PositionType.CenterFielder || positionType == PositionType.LeftFielder ||
                    positionType == PositionType.RightFielder || positionType == PositionType.OutFielder)
                {
                    return(GetFlyoutResult(random, outfieldShiftType));
                }
                return(GetGroundoutResult(random, infieldShiftType));
            }
            if (randomResult < 80)
            {
                if (positionType == PositionType.CenterFielder || positionType == PositionType.LeftFielder ||
                    positionType == PositionType.RightFielder || positionType == PositionType.OutFielder)
                {
                    return(GetFlyoutResult(random, outfieldShiftType));
                }
                if (infieldShiftType == InfieldShiftType.InfieldIn)
                {
                    randomResult = random.Next(0, 5);
                    if (randomResult < 2)
                    {
                        return(FieldingResult.Single);
                    }
                }
                return(FieldingResult.Popout);
            }
            if (randomResult < 95)
            {
                return(GetLineoutResult(random, positionType, infieldShiftType));
            }
            return(FieldingResult.Foulout);
        }
        public bool GetIsPassedBallResult(FieldingStint catcher)
        {
            var random       = new Random();
            var randomResult = random.Next(0, 1001);

            if (catcher == null)
            {
                catcher = FieldingStintHelperFunctions.CreateFieldingStintForPlayerOutOfPosition(PositionType.Catcher);
            }

            if (catcher.InningsPlayedOuts == 0)
            {
                catcher.InningsPlayedOuts = (short)(catcher.Games * 8 * 3);
            }

            var successThreshold = ((double)catcher.PassedBalls / (catcher.InningsPlayedOuts * 2)) * 1000;

            return(randomResult <= successThreshold);
        }
        public bool GetStealResult(BattingStint runner, FieldingStint catcher, BaseballBase baseballBase)
        {
            // only handles lead runner steals
            // todo add complex steals/errors/balks/rundowns2
            var random       = new Random();
            var randomResult = random.Next(0, 1001);

            if (catcher == null)
            {
                catcher = FieldingStintHelperFunctions.CreateFieldingStintForPlayerOutOfPosition(PositionType.Catcher);
            }

            if (runner == null)
            {
                runner = BattingStintHelperFunctions.CreateBattingStintForNonBatter();
            }

            double baseFactor = 1;

            if (baseballBase == BaseballBase.Third)
            {
                baseFactor = .75;
            }
            else if (baseballBase == BaseballBase.Home)
            {
                baseFactor = .5;
            }

            double catcherArmFactor = 1;

            if (catcher.StolenBases < 20 || runner.StolenBases < 20)
            {
                catcherArmFactor = .9;
            }
            else
            {
                var csRatio = (double)catcher.CaughtStealing / (catcher.CaughtStealing + catcher.StolenBases);
                if (csRatio >= .6)
                {
                    catcherArmFactor = .6;
                }
                else if (csRatio >= .5)
                {
                    catcherArmFactor = .7;
                }

                else if (catcher.StolenBases >= .4)
                {
                    catcherArmFactor = .8;
                }
                else if (catcher.StolenBases >= .3)
                {
                    catcherArmFactor = .9;
                }
                else if (catcher.StolenBases >= .2)
                {
                    catcherArmFactor = .95;
                }
            }

            double stealingFrequencyFactor = 1;

            if (runner.StolenBases >= 100)
            {
                stealingFrequencyFactor = .97;
            }
            else if (runner.StolenBases >= 70)
            {
                stealingFrequencyFactor = .92;
            }
            else if (runner.StolenBases >= 50)
            {
                stealingFrequencyFactor = .87;
            }
            else if (runner.StolenBases >= 40)
            {
                stealingFrequencyFactor = .82;
            }
            else if (runner.StolenBases >= 30)
            {
                stealingFrequencyFactor = .75;
            }
            else if (runner.StolenBases >= 20)
            {
                stealingFrequencyFactor = .7;
            }
            else if (runner.StolenBases >= 10)
            {
                stealingFrequencyFactor = .6;
            }
            else
            {
                stealingFrequencyFactor = .5;
            }

            var successThreshold = stealingFrequencyFactor * catcherArmFactor * baseFactor * 1000;

            return(randomResult <= successThreshold);
        }