public static IPlayer CreateCompetitor(StrikeInfo strikeModel, Ball ball, Hole hole, User player, ExperimentHistory history, IBallKickPhysics ballKick)
        {
            if (history == null)
                throw new NullReferenceException("history");

            IPlayer competitor;

            var competitorModel = strikeModel.CompetitorModel;

            if (competitorModel == null)
                throw new NullReferenceException("Модель соперника не задана");

            if (competitorModel is UniformCompetitorModel)
            {
                competitor = new UniformCompetitor(ball, hole, strikeModel.CompetitorModel as UniformCompetitorModel, player, ballKick);
            }
            else if (competitorModel is NormalAdaptiveCompetitorModel)
            {
                var errorGenerator = new NormalAdaptiveCompetitorRandom(strikeModel.CompetitorModel as NormalAdaptiveCompetitorModel, history);

                competitor = new Competitor(ball.Position.X, hole.Position.X, errorGenerator, ballKick);
            }
            else if (competitorModel is UniformAdaptiveCompetitorModel)
            {
                var errorGenerator = new UniformAdaptiveCompetitorRandom(strikeModel.CompetitorModel as UniformAdaptiveCompetitorModel, history, strikeModel.Hole.Size, strikeModel.Ball.Size);

                competitor = new Competitor(ball.Position.X, hole.Position.X, errorGenerator, ballKick);
            }
            else
            {
                throw new InvalidOperationException($"Модель соперника \"{competitorModel.GetType().Name}\" не поддерживается");
            }

            return competitor;
        }
        public UniformCompetitor(Ball ball, Hole hole, UniformCompetitorModel competitorModel, User player, IBallKickPhysics ballKick)
        {
            _player = player;
            _ballKick = ballKick;
            _ball = ball;
            _hole = hole;
            _competitorModel = competitorModel;

            if (_competitorModel == null)
                throw new NullReferenceException("Не задана модель соперника");
        }
        private static Tuple<int, int> GetBoundaries(User player, PlayerHistorySample historySample)
        {
            var fromStrikeValue = 0;

            var count = player.Strikes.Count;

            int toStrikeValue;

            if (IsStrikeCountNull(historySample))
            {
                fromStrikeValue = GetFromStrikeValue(historySample.FromStrike, count);

                toStrikeValue = GetToStrikeValue(historySample.ToStrike, count);
            }
            else
            {
                var strikesCount = historySample.StrikesCount;

                if (strikesCount == null)
                    throw new NullReferenceException();

                if (strikesCount.Value > 0)
                {
                    fromStrikeValue = GetFromStrikeValue(historySample.FromStrike, count);

                    toStrikeValue = fromStrikeValue + strikesCount.Value;
                }
                else if (strikesCount.Value < 0)
                {
                    toStrikeValue = GetToStrikeValue(historySample.ToStrike, count);

                    fromStrikeValue = toStrikeValue + strikesCount.Value;
                }
                else
                {
                    if (historySample.ToStrike == null && historySample.FromStrike == null)
                    {
                        throw new ArgumentException(
                            "Количество ударов не может быть равным 0, если явно не задан параметр \"ToStrike\" или \"FromStrike\", ");
                    }
                    else if (historySample.ToStrike != null)
                    {
                        fromStrikeValue = toStrikeValue = GetToStrikeValue(historySample.ToStrike, count);
                    }
                    else
                    {
                        fromStrikeValue = toStrikeValue = GetFromStrikeValue(historySample.FromStrike, count);
                    }
                }
            }
            return new Tuple<int, int>(fromStrikeValue, toStrikeValue);
        }
        public void Initialize()
        {
            _currentStrike = GameObjects["currentStrikeInfo"] as StrikeInfo;

            if (_currentStrike == null)
                throw new NullReferenceException("currentStrikeInfo");

            _ball = GetBall();
            SetupBall(_ball);

            _hole = GetHole();
            SetupHole(_hole);

            #region Задание параметров отображаемой мишени

            var holeInfo = _currentStrike.Hole;

            var holeView = GameObjects["holeView"] as HoleView;

            if (holeView == null)
                throw new NullReferenceException("holeView");

            // если отображаемый размер мишени не задан, используется действительный размер
            holeView.SetSize(holeInfo.VisibleSize == null ? holeInfo.Size : holeInfo.VisibleSize.Value);

            #endregion

            // Текущая игра
            var currentGame = GameObjects["currentGame"] as Game;

            if (currentGame == null)
                throw new NullReferenceException("currentGame");

            // Все игроки
            _users = GameObjects["users"] as Users;

            if (_users == null)
                throw new NullReferenceException("users");

            // Текущий игрок - испытуемый бьет первым
            _currentUser = _users.FirstOrDefault(t => t.UserInfo.UserType == UserTypeEnum.Bot);

            if (_currentUser == null)
                throw new NullReferenceException("currentUser");

            GameObjects["currentUser"] = _currentUser;

            // Снять выделение с имени игрока
            var userScoreView = GameObjects["userScoreView"] as UserScoreView;

            if (userScoreView == null)
                throw new NullReferenceException("userScoreView");

            userScoreView.IsActive = false;

            // Показать баллы соперника
            var botScoreView = GameObjects["botScoreView"] as UserScoreView;

            if (botScoreView == null)
                throw new NullReferenceException("botScoreView");

            botScoreView.Score = _currentUser.TotalScore;
            botScoreView.IsActive = true;

            GameObjects["currentUserScoreView"] = botScoreView;
        }
        private Users CreateUsers(Game currentGame)
        {
            // Испытуемый
            var person = GameObjects["person"] as Person;

            if (person == null) throw new NullReferenceException("person");

            var users = new Users();

            foreach (var userInfo in currentGame.Users)
            {
                var user = new User
                               {
                                   CurrentGame = currentGame.Title,
                                   UserInfo = userInfo,
                                   TotalScore = userInfo.Score
                               };

                if (userInfo.UserType == UserTypeEnum.User)
                {
                    user.Person = person;
                }

                users.Add(user);
            }

            return users;

            //GameObjects["users"] = users;
        }
        public void Initialize()
        {
            _stopwatch.Reset();

            // Таймер
            _timer = _gameObjects["timer"] as Timer;

            if (_timer == null) throw new NullReferenceException("timer");

            _timer.Reset();

            // Таймер время до нажатия пробела
            _timerBeforeSpaceDown = _gameObjects["timerBeforeSpaceDown"] as Timer2;

            if (_timerBeforeSpaceDown == null)
                throw new NullReferenceException("timerBeforeSpaceDown");

            _timerBeforeSpaceDown.Reset();

            _firstLoop = true;

            _currentStrike = _gameObjects["currentStrikeInfo"] as StrikeInfo;

            if (_currentStrike == null)
                throw new NullReferenceException("currentStrikeInfo");

            var ballStartPosition = CreateBallStartPosition();
            StoreBallStartPosition(ballStartPosition);

            _ball = GetBall();
            SetupBall(_ball, ballStartPosition);

            var holeStartPosition = CreateHoleStartPosition();
            StoreHoleStartPosition(holeStartPosition);

            _hole = GetHole();
            SetupHole(_hole, holeStartPosition);

            #region Задание параметров отображаемой мишени

            var holeView = _gameObjects["holeView"] as HoleView;

            if (holeView == null)
                throw new NullReferenceException("holeView");

            var holeInfo = _currentStrike.Hole;
            // если отображаемый размер мишени не задан, используется действительный размер
            holeView.SetSize(holeInfo.VisibleSize == null ? holeInfo.Size : holeInfo.VisibleSize.Value);

            #endregion

            // Текущая игра
            _currentGame = _gameObjects["currentGame"] as Game;

            if (_currentGame == null)
                throw new NullReferenceException("currentGame");

            // Все игроки
            var users = _gameObjects["users"] as Users;

            if (users == null)
                throw new NullReferenceException("users");

            // Текущий игрок - испытуемый бьет первым
            _currentUser = users.FirstOrDefault(t => t.UserInfo.UserType == UserTypeEnum.User);

            if (_currentUser == null) throw new NullReferenceException("currentUser");

            _gameObjects["currentUser"] = _currentUser;

            // Снять выделение с имени игрока
            var botScoreView = GameObjects["botScoreView"] as UserScoreView;

            if (botScoreView != null)
            {
                botScoreView.IsActive = false;
            }

            // Показать очки игрока
            var userScoreView = GameObjects["userScoreView"] as UserScoreView;

            if (userScoreView == null) throw new NullReferenceException("userScoreView");

            userScoreView.Score = _currentUser.TotalScore;
            userScoreView.IsActive = true;

            GameObjects["currentUserScoreView"] = userScoreView;

            // Режим игрока
            var experiment = GameObjects["experiment"] as Experiment;

            if (experiment == null) throw new NullReferenceException("experiment");

            _inTestMode = experiment.Mode != null && experiment.Mode.Value == ExeprimentModeEnum.Test && _currentStrike.InTestMode != null;
        }
        private static string GetText(User bot,
                                      User user)
        {
            var text = "";

            if (user.TotalScore > bot.TotalScore)
            {
                text = "Ура! Вы победили со счетом";
            }
            else if (user.TotalScore < bot.TotalScore)
            {
                text = "Увы, Вы проиграли со счетом";
            }
            else
            {
                text = "Ничья";
            }

            return text;
        }