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 void Initialize()
        {
            strikePlayer = new StrikePlayer(GameObjects);

            currentGame = GameObjects["currentGame"] as Game;

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

            currentStrike = currentGame.Strikes[0];

            strikeRepeatTime = 0;

            strikesRepeatTime = 0;

            if (currentGame.StrikesRepeatTimes < 1) throw new ArgumentException(string.Format("Параметр \"StrikesRepeatTimes\" игры меньше 1, игра \"{0}\"", currentGame.Title));

            if (currentStrike.RepeatTimes < 1) throw new ArgumentException(string.Format("Параметр \"RepeatTimes\" меньше 1, игра \"{0}\"", currentGame.Title));

            GameObjects["currentStrikeInfo"] = currentStrike;

            strikePlayer.Initialize();
        }
        public bool Loop()
        {
            var looping = false;

            looping = strikePlayer.Play();

            if (!looping)
            {
                var nextStrike = GetNextStrike();

                if (nextStrike != null)
                {
                    currentStrike = nextStrike;

                    GameObjects["currentStrikeInfo"] = currentStrike;

                    strikePlayer.Initialize();

                    looping = true;
                }
            }

            return looping;
        }
        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;
        }
        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;
        }
        public static Strike CreateStrike(Ball ball, Hole hole, StrikeInfo currentKick, KickResult kickResult,
            TimeSpan timeBeforeSpaceDown = new TimeSpan())
        {
            var kickedBall = new Ball()
            {
                Size = ball.Size,
                Position = ComputeBallPosition(ball, kickResult)
            };

            var miss = GetMiss(hole, kickedBall);

            var strikeTimeSpan = TimeSpan.FromSeconds(kickResult.ElapsedTime);

            var strike = new Strike
            {
                Number = currentKick.RepeatTimes,
                StrikeInfo = currentKick,
                DateTime = System.DateTime.Now,
                ErrorDistance = kickedBall.Position.X - hole.Position.X,
                IsHit = Math.Abs(miss - 0.0) < 0.001,
                MissDistance = Math.Round(miss, 3),
                MissTime = Math.Round(miss / currentKick.Model.Velocity, 3),
                BeforeStrikeTimeSpan = timeBeforeSpaceDown,
                StrikeTimeSpan = strikeTimeSpan,
                TotalTimeSpan = timeBeforeSpaceDown + strikeTimeSpan,
                StartBallPosition = ball.Position.Copy(),
                StartHolePosition = hole.Position.Copy()
            };

            return strike;
        }