void aiTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            using(IGameDataService gameDataService = new GameDataService())
            {
                IEnumerable<AIAttentionRequiredResult> aiGames = gameDataService.GetAIGamesRequiringAttention();

                //If we have any Games that the AI needs to play, loop through them all.
                //We will notify the AI to play on seperate threads.
                if (aiGames.Any())
                {
                    foreach(var aiGame in aiGames)
                    {
                        BackgroundWorker aiWorker = new BackgroundWorker();
                        aiWorker.DoWork += aiWorker_DoWork;
                        aiWorker.RunWorkerAsync(aiGame);
                        aiWorker.RunWorkerCompleted += (cs,ce) =>
                            {
                                if (ce.Error != null)
                                {
                                    Exception ex = ce.Error;
                                    while (ex.InnerException != null)
                                    {
                                        ex = ex.InnerException;
                                    }

                                    Logger.Instance.Log("CentralServerCommunicationError", string.Format("GameId:{0}|Error:{1}",aiGame.GameId, ex.Message), ce.Error.StackTrace);
                                    using (IGameDataService dataService = new GameDataService())
                                    {
                                        Match match = dataService.GetMatch(null, aiGame.GameId);
                                        CentralServerSession session = dataService.GetCentralServerSession(null, null, aiGame.GameId);
                                        Player tttdPlayer = dataService.GetPlayer(match.PlayerOneId);
                                        GameConfiguration config = GameConfigCache.Instance.GetConfig(match.MatchId);

                                        dataService.EndGame(aiGame.GameId, match.PlayerOneId == aiGame.PlayerId ? match.PlayerTwoId : match.PlayerOneId);
                                        dataService.Save();

                                        if (config.GameType == GameType.Network)
                                        {
                                            MoveRequest challengeRequest = new MoveRequest();
                                            challengeRequest.GameId = session.CentralServerGameId.Value;
                                            challengeRequest.PlayerName = tttdPlayer.PlayerName;
                                            challengeRequest.X = 0;
                                            challengeRequest.Y = 0;
                                            challengeRequest.Flags = CentralServerCommunicationChannel.GetStatus(StatusFlag.AcceptLoss);

                                            CentralServerCommunicationChannel.Instance.PostMove(challengeRequest, match.CurrentGameId.Value, match.MatchId);
                                        }
                                    }
                                }
                            };
                    }
                }
            }
        }
        static void PostMoveCompleted(string data, int matchId)
        {
            var response = JsonSerializer.DeseriaizeFromJSON<MoveResponse>(data);
            bool newGame = false;
            int gameId;
            int oldGameId;
            Match match;
            Player tttdPlayer;
            CentralServerSession session;
            StatusFlag flag = CentralServerCommunicationChannel.ParseStatus(response.StatusFlag);
            using (IGameDataService dataService = new GameDataService())
            {
                match = dataService.GetMatch(matchId, null);
                session = dataService.GetCentralServerSession(null, null, match.CurrentGameId.Value);
                tttdPlayer = dataService.GetPlayer(match.PlayerOneId);
                oldGameId = match.CurrentGameId.Value;

                if (response.NewGameId != null && response.NewGameId > 0 && response.NewGameId != session.CentralServerGameId)
                {
                    int newGameId = TicTacToeHost.Instance.ConfigureGame(matchId);
                    gameId = newGameId;
                    newGame = true;
                    session = dataService.CreateCentralServerSession(newGameId, response.NewGameId);
                }
                else
                {
                    gameId = match.CurrentGameId.Value;
                }
                dataService.Save();
            }

            if (response.YourTurn
                //|| (newGame && response.X == null && response.Y == null)
                )
            {
                using (IGameDataService dataService = new GameDataService())
                {
                    dataService.SetPlayerTurn(gameId, match.PlayerOneId);
                    dataService.Save();
                }
            }
            else if(flag == StatusFlag.ChallengeMove || flag == StatusFlag.ChallengeWin)
            {
                using (IGameDataService dataService = new GameDataService())
                {
                    dataService.EndGame(oldGameId, null);
                    dataService.Save();
                }
            }
            else if (response.X >= 0 && response.Y >= 0)
            {
                if (flag == StatusFlag.AcceptLoss)
                {
                    using (IGameDataService dataService = new GameDataService())
                    {
                        dataService.EndGame(oldGameId, match.PlayerOneId);
                        dataService.Save();
                    }
                }

                if (newGame)
                {
                    using (IGameDataService dataService = new GameDataService())
                    {
                        dataService.SetPlayerTurn(gameId, match.PlayerTwoId);
                        dataService.Save();
                    }
                }

                Move move = new Move() { GameId = gameId, PlayerId = match.PlayerTwoId };
                GameState state = TicTacToeHost.Instance.GetGameState(gameId, match.PlayerTwoId);
                if (state.Mode == PlayMode.DeathMatch)
                {
                    move.OriginX = response.X;
                    move.OriginY = response.Y;
                    for (int x = 0; x < 3; x++)
                    {
                        for (int y = 0; y < 3; y++)
                        {
                            if (state.GameBoard[x][y] == null || state.GameBoard[x][y] == 0)
                            {
                                move.X = x;
                                move.Y = y;
                            }
                        }
                    }
                }
                else
                {
                    move.X = response.X.Value;
                    move.Y = response.Y.Value;
                }

                MoveResult opponentMoveResult = TicTacToeHost.Instance.Move(move, false);
                GameState postMoveState = TicTacToeHost.Instance.GetGameState(gameId, match.PlayerTwoId);
                if (opponentMoveResult != MoveResult.Valid || flag == StatusFlag.WinningMove || postMoveState.YouWon)
                {
                    MoveRequest challengeRequest = new MoveRequest();
                    challengeRequest.GameId = session.CentralServerGameId.Value;
                    challengeRequest.PlayerName = tttdPlayer.PlayerName;
                    challengeRequest.X = 0;
                    challengeRequest.Y = 0;

                    bool challenging = false;
                    if (opponentMoveResult != MoveResult.Valid)
                    {
                        challengeRequest.Flags = CentralServerCommunicationChannel.GetStatus(StatusFlag.ChallengeMove);
                        challenging = true;
                    }
                    else
                    {
                        if (flag == StatusFlag.WinningMove && !postMoveState.YouWon)
                        {
                            challengeRequest.Flags = CentralServerCommunicationChannel.GetStatus(StatusFlag.ChallengeWin);
                            challenging = true;
                        }
                        else
                        {
                            challengeRequest.Flags = CentralServerCommunicationChannel.GetStatus(StatusFlag.AcceptLoss);
                        }
                    }

                    if (challenging)
                    {
                        using (IGameDataService dataService = new GameDataService())
                        {
                            dataService.EndGame(gameId, null);
                            dataService.Save();
                        }
                    }

                    CentralServerCommunicationChannel.Instance.PostMove(challengeRequest, match.CurrentGameId.Value, match.MatchId);
                }
            }
        }
        private void PerformServerRequest(ServerRequestConfig config)
        {
            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += (sender, args) =>
                {
                    var workerConfig = (ServerRequestConfig)args.Argument;
                    //"http://centralserver.codeketeers.com/ServerPairing.php?challenge=James&from=Anthony"
                    JavaScriptSerializer dataSerailizer = new JavaScriptSerializer();
                    string queryString = string.Join("&", dataSerailizer.Deserialize<Dictionary<string, string>>(config.RequestData).Where(kv => !string.IsNullOrEmpty(kv.Value)).Select(kv => string.Format("{0}={1}", kv.Key, HttpUtility.UrlEncode(kv.Value != null ? kv.Value : string.Empty))));
                    string fullUrl = string.Format("{0}?{1}", config.Url, queryString);
                    Logger.Instance.Log("ServerRequest", string.Format("GameId:{0}|MatchId:{1}|Request:{2}", workerConfig.GameId, workerConfig.MatchId, fullUrl), JsonSerializer.SerializeToJSON(workerConfig));
                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(fullUrl);
                    request.ContentLength = 0;

                    var httpResponse = (HttpWebResponse)request.GetResponse();
                    using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
                    {
                        var result = streamReader.ReadToEnd();
                        Logger.Instance.Log("ServerResponse", string.Format("GameId:{0}|MatchId:{1}|Request:{2}", workerConfig.GameId, workerConfig.MatchId, fullUrl), result);
                        workerConfig.ResponseAction(result, workerConfig.MatchId);
                    }
                };
            worker.RunWorkerAsync(config);
            worker.RunWorkerCompleted += (cs, ce) =>
            {
                if (ce.Error != null)
                {
                    Exception ex = ce.Error;
                    while (ex.InnerException != null)
                    {
                        ex = ex.InnerException;
                    }

                    Logger.Instance.Log("CentralServerCommunicationError", string.Format("GameId:{0}|MatchId:{1}|Error:{2}",config.GameId,config.MatchId, ex.Message), ce.Error.StackTrace);
                    using (IGameDataService dataService = new GameDataService())
                    {
                        dataService.EndGame(config.GameId, null);
                        dataService.Save();

                        Match match = dataService.GetMatch(config.MatchId, null);
                        CentralServerSession session = dataService.GetCentralServerSession(null, null, config.GameId);
                        Player tttdPlayer = dataService.GetPlayer(match.PlayerOneId);

                        MoveRequest challengeRequest = new MoveRequest();
                        challengeRequest.GameId = session.CentralServerGameId.Value;
                        challengeRequest.PlayerName = tttdPlayer.PlayerName;
                        challengeRequest.X = 0;
                        challengeRequest.Y = 0;
                        challengeRequest.Flags = CentralServerCommunicationChannel.GetStatus(StatusFlag.ChallengeMove);

                        CentralServerCommunicationChannel.Instance.PostMove(challengeRequest, match.CurrentGameId.Value, match.MatchId);
                    }
                }
            };
        }
        private void UpdateGame(int gameId)
        {
            using (IGameDataService gameDataService = new GameDataService())
            {
                Game game = gameDataService.GetGame(gameId);
                GameState state = this.GetGameState(gameId, game.PlayerOneId);
                int gameWon = this.IsWon(state.GameBoard);
                if (gameWon == 1 || gameWon == -1)
                {
                    if (gameWon == 1)
                        gameDataService.EndGame(gameId, game.PlayerOneId);
                    else if (gameWon == -1)
                        gameDataService.EndGame(gameId, game.PlayerTwoId);
                }

                if (!game.DeathMatchMode)
                {
                    int ninthCheckPlayer = game.CurrentPlayerId == game.PlayerOneId ? 1 : -1;
                    bool canWinWithNinth = false;
                    for (int x = 0; x < 3; x++)
                    {
                        for (int y = 0; y < 3; y++)
                        {
                            if ((state.GameBoard[x][y] == null || state.GameBoard[x][y] == 0)
                                && this.CanWin(state.GameBoard, ninthCheckPlayer, x, y) == ninthCheckPlayer)
                            {
                                canWinWithNinth = true;
                                goto FoundEmpty;
                            }
                        }
                    }

                FoundEmpty:
                    if (!canWinWithNinth)
                    {
                        gameDataService.setToDeathMatch(game.GameId);
                    }
                }

                gameDataService.Save();
            }
            using (IGameDataService gameDataService = new GameDataService())
            {
                gameDataService.SwapPlayerTurn(gameId);
                gameDataService.Save();
            }
        }