/// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            Microsoft.ApplicationInsights.WindowsAppInitializer.InitializeAsync(
                Microsoft.ApplicationInsights.WindowsCollectors.Metadata |
                Microsoft.ApplicationInsights.WindowsCollectors.Session);
            this.InitializeComponent();
            this.Suspending += OnSuspending;
            FicsClient = new FicsClient();
            isFicsClientReady = false;
            Task.Run(async () =>
            {
                await FicsClient.LoginGuest();
                FicsClient.ServerVariables.ShowPromptTime = false;
                FicsClient.ServerVariables.Seek = false;
                FicsClient.ServerVariables.MoveBell = false;
                FicsClient.ServerVariables.Style = 12;
                FicsClient.ServerVariables.ShowProvisionalRatings = true;
                FicsClient.ServerVariables.Interface = "TestAppUniversal";
                FicsClient.ServerInterfaceVariables.PreciseTimes = true;
                FicsClient.ServerInterfaceVariables.DetailedGameInfo = true;
                FicsClient.ServerInterfaceVariables.PreMove = true;
                FicsClient.ServerInterfaceVariables.SmartMove = false;
                FicsClient.UnknownMessageReceived += (message) =>
                {
                    Debug.Assert(false, message);
                };

                isFicsClientReady = true;
                if (ficsClientReady != null)
                {
                    ficsClientReady(FicsClient);
                }
            });
        }
        public void FicsFollowingObservingGame()
        {
            string FollowingObservingGame = FixNewLines(@"
            Nopawn, whom you are following, has started a game with Boran.
            You are now observing game 66.
            Game 66: Boran (1880) Nopawn (1994) rated lightning 1 0

            <g1> 66 p=0 t=lightning r=1 u=0,0 it=60,0 i=60,0 pt=0 rt=1880,1994 ts=1,1 m=2 n=1

            <12> rnbqkbnr pppppppp -------- -------- -------- -------- PPPPPPPP RNBQKBNR W -1 1 1 1 1 0 66 Boran Nopawn 0 1 0 39 39 60000 60000 1 none (0:00.000) none 0 0 0");
            FicsClient client = new FicsClient();
            ObserveGameResult game = null;

            client.variables.Initialize(new Dictionary<string, string>() { { "provshow", "1" } });
            client.ivariables.Initialize(new Dictionary<string, string>() { { "gameinfo", "1" } });
            client.FollowedPlayerStartedGame += (g) =>
            {
                game = g;
            };
            TestIsKnownMessage(client, ref FollowingObservingGame);
            Assert.IsNotNull(game);
        }
        public void FicsFollowingObservingGame2()
        {
            string FollowingObservingGame = FixNewLines(@"
            Voittamaton, whom you are following, has started a game with zitterbart.
            You are now observing game 183.
            Game 183: zitterbart (1768) Voittamaton (1770) rated crazyhouse 1 0

            <g1> 183 p=0 t=crazyhouse r=1 u=0,0 it=60,0 i=60,0 pt=0 rt=1768,1770 ts=1,1 m=2 n=1

            <12> rnbqkbnr pppppppp -------- -------- -------- -------- PPPPPPPP RNBQKBNR W -1 1 1 1 1 0 183 zitterbart Voittamaton 0 1 0 39 39 60000 60000 1 none (0:00.000) none 0 0 0
            <b1> game 183 white [] black []");
            FicsClient client = new FicsClient();
            ObserveGameResult game = null;

            client.variables.Initialize(new Dictionary<string, string>() { { "provshow", "1" } });
            client.ivariables.Initialize(new Dictionary<string, string>() { { "gameinfo", "1" } });
            client.FollowedPlayerStartedGame += (g) =>
            {
                game = g;
            };
            TestIsKnownMessage(client, ref FollowingObservingGame);
            Assert.IsNotNull(game);
        }
        private static async Task CrawlGames(ILogger logger, GamesListingOptions gameListingOptions)
        {
            using (FicsClient client = new FicsClient())
            {
                await client.Login(configuration.FicsUsername, configuration.FicsPassword);
                client.ServerVariables.ShowPromptTime = false;
                client.ServerVariables.Seek = false;
                client.ServerVariables.MoveBell = false;
                client.ServerVariables.Style = 12;
                client.ServerVariables.ShowProvisionalRatings = true;
                client.ServerVariables.Interface = "GameCrawler";
                client.ServerInterfaceVariables.PreciseTimes = true;
                client.ServerInterfaceVariables.DetailedGameInfo = true;
                client.ServerInterfaceVariables.PreMove = true;
                client.ServerInterfaceVariables.SmartMove = false;

                client.UnknownMessageReceived += (message) =>
                {
                    logger.LogUnknownMessage(message);
                };

                client.GameStateChange += (state) =>
                {
                    ObservingGame game;

                    lock (observingGames)
                    {
                        if (!observingGames.TryGetValue(state.GameId, out game))
                            return;
                    }

                    if (state.LastMove != null && state.LastMove != "none")
                    {
                        var move = new ChessMove()
                        {
                            Move = state.LastMove,
                            Time = state.LastMoveTime,
                        };

                        List<ChessMove> movesList = state.WhiteMove ? game.BlackMovesList : game.WhiteMovesList;
                        int moveNumber = !state.WhiteMove ? state.Move : state.Move - 1;

                        lock (movesList)
                        {
                            while (movesList.Count < moveNumber)
                            {
                                movesList.Add(null);
                            }

                            movesList[moveNumber - 1] = move;
                        }
                    }
                };

                client.GameEnded += (result) =>
                {
                    ObservingGame game;

                    lock (observingGames)
                    {
                        if (observingGames.TryGetValue(result.GameId, out game))
                        {
                            game.Result = result;
                            Log("Game ended {0}\nWhite moves: {1}\nBlack moves: {2}", game.Game, game.WhiteMovesList.Count, game.BlackMovesList.Count);
                            observingGames.Remove(result.GameId);
                        }
                    }

                    // Check if game was aborted and save otherwise
                    if (game != null && result.WhitePlayerPoints + result.BlackPlayerPoints > 0)
                    {
                        bool save = true;

                        if (game.PartnersGame != null)
                        {
                            if (game.Game.WhitePlayer.Username.CompareTo(game.PartnersGame.Game.WhitePlayer.Username) < 0)
                            {
                                lock (game)
                                lock (game.PartnersGame)
                                    {
                                        game.Finished = true;
                                        if (!game.PartnersGame.Finished)
                                            save = false;
                                    }
                            }
                            else
                            {
                                lock (game.PartnersGame)
                                lock (game)
                                    {
                                        game.Finished = true;
                                        if (!game.PartnersGame.Finished)
                                            save = false;
                                    }
                            }
                        }

                        if (save)
                            logger.SaveGame(game);
                    }
                };

                while (client.ConnectionWorking)
                {
                    var games = await client.ListGames(gameListingOptions);

                    Log("Active games: {0}", games.Count);
                    foreach (var game in games)
                    {
                        if (game.Examined || game.InSetup)
                            continue;

                        bool containsKey;

                        lock (observingGames)
                        {
                            containsKey = observingGames.ContainsKey(game.Id);
                        }

                        if (!containsKey)
                        {
                            try
                            {
                                // Add game to the list
                                var observingGame = new ObservingGame();
                                observingGame.BlackMovesList = new List<ChessMove>();
                                observingGame.WhiteMovesList = new List<ChessMove>();
                                observingGame.Game = game;
                                lock (observingGames)
                                {
                                    observingGames.Add(game.Id, observingGame);
                                }

                                // Start observing game
                                var result = await client.StartObservingGame(game);

                                // If we started observing different game, stop observing it
                                if (!result.GameInfo.WhitePlayer.Username.StartsWith(game.WhitePlayer.Username)
                                    || !result.GameInfo.BlackPlayer.Username.StartsWith(game.BlackPlayer.Username))
                                {
                                    Log("Canceling game {0}", game);
                                    await client.StopObservingGame(game);
                                }


                                Log("Starting game {0}", game);

                                // Collect and update moves list
                                var moveList = await client.GetMoveList(game);

                                observingGame.GameStarted = moveList.GameStarted;
                                lock (observingGame.WhiteMovesList)
                                {
                                    while (observingGame.WhiteMovesList.Count < moveList.WhiteMoves.Count)
                                        observingGame.WhiteMovesList.Add(null);
                                    for (int i = 0; i < moveList.WhiteMoves.Count; i++)
                                        observingGame.WhiteMovesList[i] = moveList.WhiteMoves[i];
                                }

                                lock (observingGame.BlackMovesList)
                                {
                                    while (observingGame.BlackMovesList.Count < moveList.BlackMoves.Count)
                                        observingGame.BlackMovesList.Add(null);
                                    for (int i = 0; i < moveList.BlackMoves.Count; i++)
                                        observingGame.BlackMovesList[i] = moveList.BlackMoves[i];
                                }

                                // Connect partners game
                                if (result.GameInfo.PartnersGameId > 0)
                                {
                                    ObservingGame partnersGame;

                                    lock (observingGames)
                                    {
                                        if (observingGames.TryGetValue(result.GameInfo.PartnersGameId, out partnersGame))
                                        {
                                            partnersGame.PartnersGame = observingGame;
                                            observingGame.PartnersGame = partnersGame;
                                        }
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                logger.LogException(ex);
                                lock (observingGames)
                                {
                                    observingGames.Remove(game.Id);
                                }

                                try
                                {
                                    await client.StopObservingGame(game.Id);
                                }
                                catch (Exception)
                                {
                                    // We want to swallow this exception
                                }
                            }
                        }
                    }

                    await Task.Delay(TimeSpan.FromSeconds(10));
                }
            }
        }
 public static void ClassInitialize(TestContext context)
 {
     client = SetupGuestClient();
     FicsClientTests.context = context;
 }
        private static FicsClient SetupClient(Action<FicsClient> loginAction)
        {
            FicsClient client = new FicsClient();

            client.UnknownMessageReceived += (message) =>
            {
                Debug.WriteLine(message);
            };

            loginAction(client);
            client.ServerVariables.ShowPromptTime = false;
            client.ServerVariables.Seek = false;
            client.ServerVariables.MoveBell = false;
            client.ServerVariables.Style = 12;
            client.ServerVariables.ShowProvisionalRatings = true;
            client.ServerVariables.Interface = "FicsClientLibraryTests";
            client.ServerInterfaceVariables.PreciseTimes = true;
            client.ServerInterfaceVariables.DetailedGameInfo = true;
            client.ServerInterfaceVariables.PreMove = true;
            client.ServerInterfaceVariables.SmartMove = false;
            return client;
        }
 private void OnFicsClientReady(FicsClient client)
 {
     App.Current.FicsClientReady -= OnFicsClientReady;
     fics = client;
     Task.Run(() => { RefreshGames(); });
 }
 public AutoFicsServerVariablesBase(FicsClient client, ServerVariablesBase variables, FicsCommand command)
 {
     this.client = client;
     this.variables = variables;
     this.command = command;
 }
        public void FicsParseAnnouncement()
        {
            string Announcement = FixNewLines(@"

            **ANNOUNCEMENT** from relay: FICS is relaying the Russian Championship
            \   Superfinal Men 2015 - Round 1, the Russian Championship Superfinal Women
            \   2015 - Round 1 and the SS Manhem Chess Week IM/GM 2015 - Round 2. To find
            \   more about Relay type ""tell relay help""
            ");
            FicsClient client = new FicsClient();
            string announcement = null;

            client.Announcement += (message) =>
            {
                announcement = message;
            };
            TestIsKnownMessage(client, ref Announcement);
            Assert.AreEqual(announcement, @"**ANNOUNCEMENT** from relay: FICS is relaying the Russian Championship Superfinal Men 2015 - Round 1, the Russian Championship Superfinal Women 2015 - Round 1 and the SS Manhem Chess Week IM/GM 2015 - Round 2. To find more about Relay type ""tell relay help""");
        }
        public void FicsParseSeeking()
        {
            string Seeking = FixNewLines(@"
            GuestDJXR (++++) seeking 15 5 unrated standard (""play 34"" to respond)");
            FicsClient client = new FicsClient();
            SeekInfo info = null;

            client.Seeking += (i) =>
            {
                info = i;
            };
            TestIsKnownMessage(client, ref Seeking);
            Assert.IsNotNull(info);
            Assert.AreEqual(info.Id, 34);
            Assert.AreEqual(info.Player.Username, "GuestDJXR");
            Assert.AreEqual(info.Player.AccountStatus, AccountStatus.RegularAccount);
            Assert.AreEqual(info.Player.Rating, -2);
            Assert.AreEqual(info.ClockStart, TimeSpan.FromMinutes(15));
            Assert.AreEqual(info.TimeIncrement, TimeSpan.FromSeconds(5));
            Assert.AreEqual(info.GameType, GameType.Standard);
            Assert.AreEqual(info.Rated, false);
        }
        public void FicsParseKibitz()
        {
            string Kibitz = FixNewLines(@"
            INDIANREAPER(2215)[459] kibitzes: slip
            ");
            FicsClient client = new FicsClient();
            string message = null;
            Player player = null;
            int gameId = 0;

            client.Kibitz += (p, g, m) =>
            {
                player = p;
                gameId = g;
                message = m;
            };
            TestIsKnownMessage(client, ref Kibitz);
            Assert.AreEqual(message, "slip\n");
            Assert.AreEqual(player.Username, "INDIANREAPER");
            Assert.AreEqual(player.AccountStatus, AccountStatus.RegularAccount);
            Assert.AreEqual(player.Rating, 2215);
            Assert.AreEqual(gameId, 459);
        }
        public void FicsParseGameEnded()
        {
            string GameEndedMessage = "\n{Game 457 (szesze vs. aldobaral) aldobaral forfeits on time} 1-0";
            FicsClient client = new FicsClient();
            GameEndedInfo gameEndedInfo = null;

            client.GameEnded += (info) =>
            {
                gameEndedInfo = info;
            };
            TestIsKnownMessage(client, ref GameEndedMessage);
            Assert.IsNotNull(gameEndedInfo);
            Assert.AreEqual(gameEndedInfo.GameId, 457);
            Assert.AreEqual(gameEndedInfo.WhitePlayerUsername, "szesze");
            Assert.AreEqual(gameEndedInfo.BlackPlayerUsername, "aldobaral");
            Assert.AreEqual(gameEndedInfo.Message, "aldobaral forfeits on time");
            Assert.AreEqual(gameEndedInfo.WhitePlayerPoints, 1);
            Assert.AreEqual(gameEndedInfo.BlackPlayerPoints, 0);
        }
        public void FicsParseGameAborted()
        {
            const string GameAborted = "\n{Game 215 (MeleeStorm vs. Krepkiy) Game aborted on move 1} *";
            FicsClient client = new FicsClient();
            GameEndedInfo gameEndedInfo = null;

            client.GameEnded += (info) =>
            {
                gameEndedInfo = info;
            };
            TestIsKnownMessage(client, GameAborted);
            Assert.IsNotNull(gameEndedInfo);
            Assert.AreEqual(gameEndedInfo.GameId, 215);
            Assert.AreEqual(gameEndedInfo.WhitePlayerUsername, "MeleeStorm");
            Assert.AreEqual(gameEndedInfo.BlackPlayerUsername, "Krepkiy");
            Assert.AreEqual(gameEndedInfo.Message, "Game aborted on move 1");
            Assert.AreEqual(gameEndedInfo.WhitePlayerPoints, 0);
            Assert.AreEqual(gameEndedInfo.BlackPlayerPoints, 0);
        }
        private static void TestIsKnownMessage(FicsClient client, ref string message)
        {
            ManualResetEventSlim messageWaiting = new ManualResetEventSlim();

            client.Kibitz += (a, b, c) => { messageWaiting.Set(); };
            client.Announcement += (m) => { messageWaiting.Set(); };
            client.ChannelMessageReceived += (a, b, c) => { messageWaiting.Set(); };
            client.ChessShoutMessageReceived += (a, b) => { messageWaiting.Set(); };
            client.FollowedPlayerStartedGame += (a) => { messageWaiting.Set(); };
            client.GameEnded += (a) => { messageWaiting.Set(); };
            client.GameStateChange += (a) => { messageWaiting.Set(); };
            client.GameStoppedObserving += (a) => { messageWaiting.Set(); };
            client.MessageReceived += (a, b) => { messageWaiting.Set(); };
            client.Seeking += (a) => { messageWaiting.Set(); };
            client.ShoutMessageReceived += (a, b) => { messageWaiting.Set(); };
            client.Whisper += (a, b, c) => { messageWaiting.Set(); };

            bool result = client.IsKnownMessage(ref message);

            Assert.IsTrue(result);
            messageWaiting.Wait();
        }
 private static void TestIsKnownMessage(FicsClient client, string message)
 {
     TestIsKnownMessage(client, ref message);
 }
        public void FicsParseWhisper()
        {
            string Whisper = FixNewLines(@"
            LurKing(C)(2442)[327] whispers: ply=19; eval=+0.20; nps=7.1M; time=8.53;
            \   egtb=0");
            FicsClient client = new FicsClient();
            string message = null;
            Player player = null;
            int gameId = 0;

            client.Whisper += (p, g, m) =>
            {
                player = p;
                gameId = g;
                message = m;
            };
            TestIsKnownMessage(client, ref Whisper);
            Assert.AreEqual(message, "ply=19; eval=+0.20; nps=7.1M; time=8.53; egtb=0");
            Assert.AreEqual(player.Username, "LurKing");
            Assert.AreEqual(player.AccountStatus, AccountStatus.ComputerAccount);
            Assert.AreEqual(player.Rating, 2442);
            Assert.AreEqual(gameId, 327);
        }
 public AutoFicsServerInterfaceVariables(FicsClient client, ServerVariablesBase variables, FicsCommand command)
     : base(client, variables, command)
 {
 }
        public void FicsParseGameStoppedObserving2()
        {
            string RemovingGameMessage = "\nRemoving game 129 from observation list.";
            FicsClient client = new FicsClient();
            int gameId = 0;

            client.GameStoppedObserving += (id) =>
            {
                gameId = id;
            };
            TestIsKnownMessage(client, ref RemovingGameMessage);
            Assert.AreEqual(gameId, 129);
        }
        public void FicsParseCShout()
        {
            string CShout = FixNewLines(@"
            LectureNova(TD) c-shouts: I am a new lecture program accepting lecture
            \   submissions! For more information, please 'finger LectureNova'");
            FicsClient client = new FicsClient();
            string message = null;
            string user = null;

            client.ChessShoutMessageReceived += (u, m) =>
            {
                user = u;
                message = m;
            };
            TestIsKnownMessage(client, CShout);
            Assert.IsNotNull(user);
            Assert.IsNotNull(message);
            Assert.AreEqual(user, "LectureNova");
            Assert.AreEqual(message, "I am a new lecture program accepting lecture submissions! For more information, please 'finger LectureNova'");
        }