/// <summary>
        /// Creates a new Gamespy Account
        /// </summary>
        /// <remarks>Used by the login server when a create account request is made</remarks>
        /// <param name="Nick">The Account Name</param>
        /// <param name="Pass">The UN-HASHED Account Password</param>
        /// <param name="Email">The Account Email Address</param>
        /// <param name="Country">The Country Code for this Account</param>
        /// <returns>Returns the Player ID if sucessful, 0 otherwise</returns>
        public int CreateUser(string Nick, string Pass, string Email, string Country)
        {
            int Pid = 0;

            // Attempt to connect to stats database, and get a PID from there
            try
            {
                // try see if the player ID exists in the stats database
                using (StatsDatabase Db = new StatsDatabase())
                {
                    // NOTE: online account names in the stats DB start with a single space!
                    var Row = Db.Query("SELECT id FROM player WHERE upper(name) = upper(@P0)", " " + Nick);
                    Pid = (Row.Count == 0) ? StatsManager.GenerateNewPlayerPid() : Int32.Parse(Row[0]["id"].ToString());
                }
            }
            catch
            {
                Pid = StatsManager.GenerateNewPlayerPid();
            }

            // Create the user in the database
            int Rows = base.Execute("INSERT INTO accounts(id, name, password, email, country) VALUES(@P0, @P1, @P2, @P3, @P4)",
                                    Pid, Nick, Pass.GetMD5Hash(false), Email.ToLowerInvariant(), Country
                                    );

            return((Rows != 0) ? Pid : 0);
        }
Esempio n. 2
0
        /// <summary>
        /// This request provides details on a particular players rank, and
        /// whether or not to show the user a promotion/demotion announcement
        /// </summary>
        /// <queryParam name="pid" type="int">The unique player ID</queryParam>
        /// <param name="Client">The HttpClient who made the request</param>
        /// <param name="Driver">The Stats Database Driver. Connection errors are handled in the calling object</param>
        public GetRankInfo(HttpClient Client, StatsDatabase Driver)
        {
            int Pid = 0;
            List<Dictionary<string, object>> Rows;

            // Setup Params
            if (Client.Request.QueryString.ContainsKey("pid"))
                Int32.TryParse(Client.Request.QueryString["pid"], out Pid);

            // Fetch Player
            Rows = Driver.Query("SELECT rank, chng, decr FROM player WHERE id=@P0", Pid);
            if (Rows.Count == 0)
            {
                Client.Response.WriteResponseStart(false);
                Client.Response.WriteHeaderLine("asof", "err");
                Client.Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Player Doesnt Exist");
                Client.Response.Send();
                return;
            }

            // Output status... chng set to 1 shows the Promotion Announcement, whereas decr shows the Demotion Announcement
            Client.Response.WriteResponseStart();
            Client.Response.WriteHeaderLine("rank", "chng", "decr");
            Client.Response.WriteDataLine(Rows[0]["rank"], Rows[0]["chng"], Rows[0]["decr"]);
            Client.Response.Send();

            // Reset
            Driver.Execute("UPDATE player SET chng=0, decr=0 WHERE id=@P0", Pid);
        }
        public override void HandleRequest()
        {
            // NOTE: The HttpServer will handle the DbConnectException
            using (Database = new StatsDatabase())
            {
                int Pid = 0;
                List<Dictionary<string, object>> Rows;

                // Setup Params
                if (Client.Request.QueryString.ContainsKey("pid"))
                    Int32.TryParse(Client.Request.QueryString["pid"], out Pid);

                // Fetch Player
                Rows = Database.Query("SELECT rank FROM player WHERE id=@P0", Pid);
                if (Rows.Count == 0)
                {
                    Response.WriteResponseStart(false);
                    Response.WriteFreeformLine("Player Doesnt Exist!");
                    Client.Response.Send();
                    return;
                }

                // Reset
                Database.Execute("UPDATE player SET chng=0, decr=0 WHERE id=@P0", Pid);
                Response.WriteResponseStart();
                Response.WriteFreeformLine(String.Format("Cleared rank notification {0}", Pid));
                Response.Send();
            }
        }
        public SearchForPlayers(HttpClient Client, StatsDatabase Driver)
        {
            string Nick;
            List<Dictionary<string, object>> Rows;

            // Setup Params
            if (!Client.Request.QueryString.ContainsKey("nick"))
            {
                Client.Response.WriteResponseStart(false);
                Client.Response.WriteHeaderLine("asof", "err");
                Client.Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!");
                Client.Response.Send();
                return;
            }
            else
                Nick = Client.Request.QueryString["nick"];

            // Timestamp Header
            Client.Response.WriteResponseStart();
            Client.Response.WriteHeaderLine("asof");
            Client.Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp());

            // Output status
            int i = 0;
            Client.Response.WriteHeaderLine("n", "pid", "nick", "score");
            Rows = Driver.Query("SELECT id, name, score FROM player WHERE name LIKE @P0 LIMIT 20", "%" + Nick + "%");
            foreach (Dictionary<string, object> Player in Rows)
            {
                Client.Response.WriteDataLine(i + 1, Rows[i]["id"], Rows[i]["name"].ToString().Trim(), Rows[i]["score"]);
                i++;
            }

            // Send Response
            Client.Response.Send();
        }
Esempio n. 5
0
        public override void HandleRequest()
        {
            // NOTE: The HttpServer will handle the DbConnectException
            using (Database = new StatsDatabase())
            {
                int Pid = 0;

                // Setup Params
                if (Client.Request.QueryString.ContainsKey("pid"))
                    Int32.TryParse(Client.Request.QueryString["pid"], out Pid);

                // Fetch Player
                var Rows = Database.Query("SELECT rank, chng, decr FROM player WHERE id=@P0", Pid);
                if (Rows.Count == 0)
                {
                    Response.WriteResponseStart(false);
                    Response.WriteHeaderLine("asof", "err");
                    Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Player Doesnt Exist");
                    Response.Send();
                    return;
                }

                // Output status... chng set to 1 shows the Promotion Announcement, whereas decr shows the Demotion Announcement
                Response.WriteResponseStart();
                Response.WriteHeaderLine("rank", "chng", "decr");
                Response.WriteDataLine(Rows[0]["rank"], Rows[0]["chng"], Rows[0]["decr"]);
                Response.Send();

                // Reset
                Database.Execute("UPDATE player SET chng=0, decr=0 WHERE id=@P0", Pid);
            }
        }
        /// <summary>
        /// This request clears all rank announcements for a specific player
        /// </summary>
        /// <queryParam name="pid" type="int">The unique player ID</queryParam>
        /// <param name="Client">The HttpClient who made the request</param>
        /// <param name="Driver">The Stats Database Driver. Connection errors are handled in the calling object</param>
        public RankNotification(HttpClient Client, StatsDatabase Driver)
        {
            int Pid = 0;
            List<Dictionary<string, object>> Rows;

            // Setup Params
            if (Client.Request.QueryString.ContainsKey("pid"))
                Int32.TryParse(Client.Request.QueryString["pid"], out Pid);

            // Fetch Player
            Rows = Driver.Query("SELECT rank FROM player WHERE id=@P0", Pid);
            if (Rows.Count == 0)
            {
                Client.Response.WriteResponseStart(false);
                Client.Response.WriteFreeformLine("Player Doesnt Exist!");
                Client.Response.Send();
                return;
            }

            // Reset
            Driver.Execute("UPDATE player SET chng=0, decr=0 WHERE id=@P0", Pid);
            Client.Response.WriteResponseStart();
            Client.Response.WriteFreeformLine(String.Format("Cleared rank notification {0}", Pid));
            Client.Response.Send();
        }
        public override void HandleRequest(MvcRoute Route)
        {
            // Try and Fetch Player ID
            Int32.TryParse(Route.Action, out Pid);

            // NOTE: The HttpServer will handle the DbConnectException
            using (Database = new StatsDatabase())
            {
                // Fetch Player
                Rows = Database.Query("SELECT * FROM player WHERE id=@P0", Pid);
                if (Rows.Count == 0)
                {
                    Client.Response.Redirect("/bf2stats/search");
                    return;
                }

                // Load our page based on the param passed
                if (Route.Params.Length > 0)
                {
                    if (Route.Params[0] == "rankings")
                        ShowRankings();
                    else if (Route.Params[0] == "history")
                        ShowHistory();
                    else
                        Client.Response.StatusCode = 404;
                }
                else
                {
                    ShowStats();
                }
            }
        }
Esempio n. 8
0
 /// <summary>
 /// Grab lowest PID on startup
 /// </summary>
 static GetPlayerID()
 {
     // Get the lowest Offline PID from the database
     using (StatsDatabase Driver = new StatsDatabase())
     {
         int DefaultPid = MainForm.Config.ASP_DefaultPID;
         var Rows = Driver.Query(String.Format("SELECT COALESCE(MIN(id), {0}) AS min FROM player", DefaultPid));
         int Lowest = Int32.Parse(Rows[0]["min"].ToString());
         LowestPid = (Lowest > DefaultPid) ? DefaultPid : Lowest -1;
     }
 }
        public override void HandleRequest()
        {
            int Pid = 0;
            int Unlock = 0;
            List<Dictionary<string, object>> Rows;

            // Setup Params
            if (Request.QueryString.ContainsKey("pid"))
                Int32.TryParse(Request.QueryString["pid"], out Pid);
            if (Request.QueryString.ContainsKey("id"))
                Int32.TryParse(Request.QueryString["id"], out Unlock);

            // Make sure we have valid parameters
            if (Pid == 0 || Unlock == 0)
            {
                Response.WriteResponseStart(false);
                Response.WriteHeaderLine("asof", "err");
                Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!");
                Response.Send();
                return;
            }

            // NOTE: The HttpServer will handle the DbConnectException
            using (Database = new StatsDatabase())
            {
                // Fetch Player
                Rows = Database.Query("SELECT availunlocks, usedunlocks FROM player WHERE id=@P0", Pid);
                if (Rows.Count == 0)
                {
                    Response.WriteResponseStart(false);
                    Response.WriteHeaderLine("asof", "err");
                    Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Player Doesnt Exist");
                    Response.Send();
                    return;
                }

                // Update Unlock, setting its state to 's' (unlocked)
                Database.Execute("UPDATE unlocks SET state = 's' WHERE id = @P0 AND kit = @P1", Pid, Unlock);

                // Update players used and avail unlock counts
                Database.Execute("UPDATE player SET availunlocks = @P0, usedunlocks = @P1 WHERE id = @P2",
                    int.Parse(Rows[0]["availunlocks"].ToString()) - 1,
                    int.Parse(Rows[0]["usedunlocks"].ToString()) + 1,
                    Pid
                );

                // Send Response
                Response.WriteResponseStart();
                Response.WriteHeaderLine("response");
                Response.WriteDataLine("OK");
                Response.Send();
            }
        }
Esempio n. 10
0
        /// <summary>
        /// This request creates a player with the specified Pid when called
        /// </summary>
        /// <queryParam name="pid" type="int">The unique player ID</queryParam>
        /// <queryParam name ="nick" type="string">Unique player nickname</queryParam>
        /// <param name="Client">The HttpClient who made the request</param>
        /// <param name="Driver">The Stats Database Driver. Connection errors are handled in the calling object</param>
        public CreatePlayer(HttpClient Client, StatsDatabase Driver)
        {
            int Pid;

            // make sure we have a valid player ID
            if (!Client.Request.QueryString.ContainsKey("pid")
                || !Int32.TryParse(Client.Request.QueryString["pid"], out Pid)
                || !Client.Request.QueryString.ContainsKey("nick"))
            {
                Client.Response.WriteResponseStart(false);
                Client.Response.WriteHeaderLine("asof", "err");
                Client.Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!");
                Client.Response.Send();
                return;
            }

            // Fetch Player
            string PlayerNick = Client.Request.QueryString["nick"].Replace("%20", " ");
            string CC = (Client.Request.QueryString.ContainsKey("cid")) ? Client.Request.QueryString["cid"] : "";
            var Rows = Driver.Query("SELECT name FROM player WHERE id=@P0 OR name=@P1", Pid, PlayerNick);
            if (Rows.Count > 0)
            {
                Client.Response.WriteResponseStart(false);
                Client.Response.WriteFreeformLine("Player already Exists!");
                Client.Response.Send();
                return;
            }

            // Create Player
            Driver.Execute(
                "INSERT INTO player(id, name, country, joined, isbot) VALUES(@P0, @P1, @P2, @P3, 0)",
                Pid, PlayerNick, CC, DateTime.UtcNow.ToUnixTimestamp()
            );

            // Confirm
            Client.Response.WriteResponseStart();
            Client.Response.WriteFreeformLine("Player Created Successfully!");
            Client.Response.Send();
        }
Esempio n. 11
0
        public override void HandleRequest()
        {
            // Setup Variables
            List<Dictionary<string, object>> Rows;
            Dictionary<string, string> QueryString = Request.QueryString;

            // Querystring vars
            int IsAI = 0;
            int ListPlayers = 0;
            string PlayerNick = "";

            // Setup Params
            if (QueryString.ContainsKey("nick"))
                PlayerNick = Uri.UnescapeDataString(QueryString["nick"].Replace("%20", " "));
            if (QueryString.ContainsKey("ai"))
                Int32.TryParse(QueryString["ai"], out IsAI);
            if (QueryString.ContainsKey("playerlist"))
                Int32.TryParse(QueryString["playerlist"], out ListPlayers);

            // NOTE: The HttpServer will handle the DbConnectException
            using (Database = new StatsDatabase())
            {
                // Handle Request
                if (!String.IsNullOrWhiteSpace(PlayerNick))
                {
                    int Pid;

                    // Create player if they donot exist
                    Rows = Database.Query("SELECT id FROM player WHERE name = @P0 LIMIT 1", PlayerNick);
                    if (Rows.Count == 0)
                    {
                        // Grab new Player ID using thread safe methods
                        Pid = (IsAI > 0) ? StatsManager.GenerateNewAIPid() : StatsManager.GenerateNewPlayerPid();

                        // Create Player
                        Database.Execute(
                            "INSERT INTO player(id, name, joined, isbot) VALUES(@P0, @P1, @P2, @P3)",
                            Pid, PlayerNick, DateTime.UtcNow.ToUnixTimestamp(), IsAI
                        );
                    }
                    else
                        Pid = Int32.Parse(Rows[0]["id"].ToString());

                    // Send Response
                    Response.WriteResponseStart();
                    Response.WriteHeaderLine("pid");
                    Response.WriteDataLine(Pid);
                }
                else if (ListPlayers != 0)
                {
                    // Prepare Response
                    Response.WriteResponseStart();
                    Response.WriteHeaderLine("pid");

                    // Fetch Players
                    Rows = Database.Query("SELECT id FROM player WHERE isbot=0 LIMIT 1000");
                    foreach (Dictionary<string, object> Player in Rows)
                        Response.WriteDataLine(Player["id"]);
                }
                else
                {
                    Response.WriteResponseStart(false);
                    Response.WriteHeaderLine("asof", "err");
                    Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!");
                }

                // Send Response
                Response.Send();
            }
        }
        /// <summary>
        /// Creates a new Gamespy Account
        /// </summary>
        /// <remarks>Used by the login server when a create account request is made</remarks>
        /// <param name="Nick">The Account Name</param>
        /// <param name="Pass">The UN-HASHED Account Password</param>
        /// <param name="Email">The Account Email Address</param>
        /// <param name="Country">The Country Code for this Account</param>
        /// <returns>Returns the Player ID if sucessful, 0 otherwise</returns>
        public int CreateUser(string Nick, string Pass, string Email, string Country)
        {
            int Pid = 0;

            // Attempt to connect to stats database, and get a PID from there
            try
            {
                // try see if the player ID exists in the stats database
                using (StatsDatabase Db = new StatsDatabase())
                {
                    // NOTE: online account names in the stats DB start with a single space!
                    var Row = Db.Query("SELECT id FROM player WHERE upper(name) = upper(@P0)", " " + Nick);
                    Pid = (Row.Count == 0) ? StatsManager.GenerateNewPlayerPid() : Int32.Parse(Row[0]["id"].ToString());
                }
            }
            catch
            {
                Pid = StatsManager.GenerateNewPlayerPid();
            }

            // Create the user in the database
            int Rows = base.Execute("INSERT INTO accounts(id, name, password, email, country) VALUES(@P0, @P1, @P2, @P3, @P4)",
                Pid, Nick, Pass.GetMD5Hash(false), Email.ToLowerInvariant(), Country
            );

            return (Rows != 0) ? Pid : 0;
        }
        /// <summary>
        /// Loads the players stats from the database, and fills out the forms
        /// labels with the current information
        /// </summary>
        private void LoadPlayer()
        {
            StatsDatabase Driver;

            // Establish DB connection
            try
            {
                Driver = new StatsDatabase();
            }
            catch (DbConnectException Ex)
            {
                ExceptionForm.ShowDbConnectError(Ex);
                HttpServer.Stop();
                Load += (s, e) => Close(); // Close form
                return;
            }

            // Fetch Player from database
            SelectQueryBuilder Builder = new SelectQueryBuilder(Driver);
            Builder.SelectFromTable("player");
            Builder.SelectColumns(
                "name", "score", "cmdscore", "skillscore", "teamscore", "joined",
                "country", "rank", "wins", "losses", "permban", "clantag", "isbot");
            Builder.AddWhere("id", Comparison.Equals, Pid);
            List<Dictionary<string, object>> Rows = Driver.ExecuteReader(Builder.BuildCommand());
            Player = Rows[0];

            // Set window title
            this.Text = String.Concat(Player["name"].ToString().Trim(), " (", Pid, ")");

            // Set country flag
            try
            {
                string Country = String.IsNullOrEmpty(Player["country"].ToString()) ? "XX" : Player["country"].ToString();
                CountryPicture.Image = Image.FromStream(Program.GetResource("BF2Statistics.Resources." + Country.ToUpper() + ".png"));
            }
            catch { }

            // Joined Label
            int Joind = Int32.Parse(Player["joined"].ToString());
            DateTime D = DateTime.UtcNow.FromUnixTimestamp(Joind);
            LabelJoined.Text = String.Concat(D.ToString("yyyy-MM-dd HH:mm"), " GMT");
            Tipsy.SetToolTip(LabelJoined, String.Concat(D.ToLocalTime().ToString("yyyy-MM-dd HH:mm"), " Local Time."));

            // Fill out the rest of the labels
            LabelNick.Text = Player["name"].ToString().Trim();
            ClanTagBox.Text = Player["clantag"].ToString();
            RankSelect.SelectedIndex = Int32.Parse(Player["rank"].ToString());
            PermBanSelect.SelectedIndex = Int32.Parse(Player["permban"].ToString());
            LabelGlobalScore.Text = Player["score"].ToString();
            LabelWinLoss.Text = String.Concat(Player["wins"], " / ", Player["losses"]);
            LabelTeamScore.Text = Player["teamscore"].ToString();
            LabelCombatScore.Text = Player["skillscore"].ToString();
            LabelCommandScore.Text = Player["cmdscore"].ToString();

            // Get Leaderboard Position
            Rows = Driver.Query("SELECT COUNT(id) as count FROM player WHERE score > @P0", Int32.Parse(Player["score"].ToString()));
            int Position = Int32.Parse(Rows[0]["count"].ToString()) + 1;
            LabelPosition.Text = Position.ToString();
            SaveBtn.Enabled = false;

            // Lock unlocks button if player is Bot
            if (Int32.Parse(Player["isbot"].ToString()) > 0)
                ResetUnlocksBtn.Enabled = false;

            // Close Connection
            Driver.Dispose();
        }
Esempio n. 14
0
        /// <summary>
        /// Checks the rank tenure, and assigns a new General
        /// </summary>
        private void GenCheck(StatsDatabase Driver)
        {
            Log("Processing GENERAL Rank", LogLevel.Notice);

            // Vars
            List<Dictionary<string, object>> Rows;
            List<Dictionary<string, object>> Players;

            // Fetch all Sergeant Major's, Order by Score
            Players = Driver.Query("SELECT id, score FROM player WHERE rank=20 OR rank=21 ORDER BY score DESC LIMIT 1");
            if (Players.Count == 1)
            {
                int Id = Int32.Parse(Players[0]["id"].ToString());

                // Check for currently awarded Smoc
                Rows = Driver.Query("SELECT id, earned FROM awards WHERE awd=6666667 LIMIT 1");
                if (Rows.Count > 0)
                {
                    // Check for same and determine if minimum tenure servred
                    int MinTenure = Program.Config.ASP_SpecialRankTenure * 86400;
                    int Sid = Int32.Parse(Rows[0]["id"].ToString());
                    int Earned = Int32.Parse(Rows[0]["earned"].ToString());

                    // Assign new Smoc If the old SMOC's tenure is up, and the current SMOC is not the highest scoring SGM
                    if (Id != Sid && (Earned + MinTenure) < this.RoundEndTime)
                    {
                        // Delete the GENERAL award
                        Driver.Execute("DELETE FROM awards WHERE id=@P0 AND awd=6666667", Sid);

                        // Change current GENERAL rank back to 3 Star Gen
                        Driver.Execute("UPDATE player SET rank=20, chng=0, decr=1 WHERE id =" + Sid);

                        // Award new GENERAL award
                        Driver.Execute("INSERT INTO awards(id,awd,earned) VALUES(@P0,@P1,@P2)", Id, 6666667, this.RoundEndTime);

                        // Update new GENERAL's rank
                        Driver.Execute("UPDATE player SET rank=21, chng=1, decr=0 WHERE id =" + Id);
                    }
                }
                else
                {
                    // Award GENERAL award
                    Driver.Execute("INSERT INTO awards(id,awd,earned) VALUES(@P0,@P1,@P2)", Id, 6666667, this.RoundEndTime);

                    // Update GENERAL rank
                    Driver.Execute("UPDATE player SET rank=21, chng=1, decr=0 WHERE id =" + Id);
                }
            }
        }
        public override void HandleRequest(MvcRoute Route)
        {
            // Get our POST variables
            HttpRequest Request = Client.Request;
            Dictionary<string, string> postParams = Request.GetFormUrlEncodedPostVars();
            int[] pids = new int[0];

            // Fetch our cookie, which contains our PiD's
            Cookie C = Request.Request.Cookies["leaderboard"] ?? new Cookie("leaderboard", "");

            // Convert cookie format into a readable one, and make sure we end with a comma!
            Model.CookieValue = C.Value.Trim().Replace('|', ',');
            if (!Model.CookieValue.EndsWith(","))
                Model.CookieValue += ",";

            // Save Leaderboard
            if (postParams.ContainsKey("set") && postParams.ContainsKey("leaderboard")) // Save cookie
            {
                Model.CookieValue = postParams["leaderboard"];
            }
            else if (Route.Action != "index" && Route.Params.Length != 0)
            {
                switch (Route.Action)
                {
                    case "add":
                        if (Validator.IsValidPID(Route.Params[0]))
                            Model.CookieValue += $"{Route.Params[0]},";
                        break;
                    case "remove":
                        if (Validator.IsValidPID(Route.Params[0]))
                            Model.CookieValue = Model.CookieValue.Replace($"{Route.Params[0]},", "");
                        break;
                    case "list":
                        Model.CookieValue = Route.Params[0];
                        break;
                }
            }

            // Read pids from the cookie
            try
            {
                // Pids are stored as xxxx,yyyyy,zzzz in the cookie
                if (Model.CookieValue.Length > 0)
                {
                    string[] players = Model.CookieValue.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    if (players.Length > 0)
                    {
                        pids = Array.ConvertAll(players, Int32.Parse).Distinct().ToArray();
                    }
                }
            }
            catch
            {
                // Bad Cookie value, so flush it!
                Model.CookieValue = "";
                C.Value = String.Empty;
                Client.Response.SetCookie(C);
            }

            // if "get" is POSTED, that means we are generated a URL instead of a cookie
            if (postParams.ContainsKey("get"))
            {
                Client.Response.Redirect(Model.Root + "/myleaderboard/list/" + String.Join(",", pids));
                return;
            }

            // If we have some player ID's, then the leaderboard is not empty
            if (pids.Length > 0)
            {
                // NOTE: The HttpServer will handle the DbConnectException
                using (StatsDatabase Database = new StatsDatabase())
                {
                    var Rows = Database.Query(
                        String.Format("SELECT id, name, score, time, country, rank, lastonline, kills, deaths FROM player WHERE id IN ({0})", String.Join(",", pids)
                    ));

                    // Loop through each result, and process
                    foreach (Dictionary<string, object> Row in Rows)
                    {
                        // DO Kill Death Ratio
                        double Kills = Int32.Parse(Row["kills"].ToString());
                        double Deaths = Int32.Parse(Row["deaths"].ToString());
                        double Kdr = (Deaths > 0) ? Math.Round(Kills / Deaths, 3) : Kills;

                        // Get Score Per Min
                        double Score = Int32.Parse(Row["score"].ToString());
                        double Mins = Int32.Parse(Row["time"].ToString()) / 60;
                        double SPM = (Mins > 0) ? Math.Round(Score / Mins, 4) : Score;

                        int Pid = Int32.Parse(Row["id"].ToString());

                        // Add Result
                        Model.Players.Add(new PlayerResult
                        {
                            Pid = Pid,
                            Name = Row["name"].ToString(),
                            Score = (int)Score,
                            Rank = Int32.Parse(Row["rank"].ToString()),
                            TimePlayed = FormatTime(Int32.Parse(Row["time"].ToString())),
                            LastOnline = FormatDate(Int32.Parse(Row["lastonline"].ToString())),
                            Country = Row["country"].ToString().ToUpperInvariant(),
                            Kdr = Kdr,
                            Spm = SPM,
                            Status = GetOnlineStatus(Pid)
                        });
                    }
                }
            }

            // Finally, set the cookie if we arent viewing from a List
            if (Route.Action != "list")
            {
                Model.CookieValue = String.Join(",", pids);
                C.Value = String.Join("|", pids);
                C.Expires = DateTime.Now.AddYears(1);
                C.Path = "/";
                Client.Response.SetCookie(C);
            }

            // TO prevent null expception in the template
            if (Model.CookieValue == null)
                Model.CookieValue = String.Empty;

            // Set content type
            base.SendTemplateResponse("myleaderboard", typeof(LeaderboardModel), Model);
        }
        public override void HandleRequest()
        {
            // Get player ID
            if (Request.QueryString.ContainsKey("pid"))
                Int32.TryParse(Request.QueryString["pid"], out Pid);

            // Prepare Output
            Response.WriteResponseStart();
            Response.WriteHeaderLine("pid", "nick", "asof");

            // Our ourput changes based on the selected Unlocks config setting
            switch (Program.Config.ASP_UnlocksMode)
            {
                // Player Based - Unlocks are earned
                case 0:
                    // NOTE: The HttpServer will handle the DbConnectException
                    using (Database = new StatsDatabase())
                    {
                        // Make sure the player exists
                        Rows = Database.Query("SELECT name, score, rank, availunlocks, usedunlocks FROM player WHERE id=@P0", Pid);
                        if (Rows.Count == 0)
                            goto case 2; // No Unlocks

                        // Start Output
                        Response.WriteDataLine(Pid, Rows[0]["name"].ToString().Trim(), DateTime.UtcNow.ToUnixTimestamp());

                        // Get total number of unlocks player is allowed to have givin his rank, and bonus unlocks
                        Rank = Int32.Parse(Rows[0]["rank"].ToString());
                        int HasUsed = Int32.Parse(Rows[0]["usedunlocks"].ToString());
                        int Available = Int32.Parse(Rows[0]["availunlocks"].ToString());
                        int Earned = GetBonusUnlocks();

                        // Determine total unlocks available, based on what he has earned, minus what he has used already
                        int Used = Database.ExecuteScalar<int>("SELECT COUNT(*) FROM unlocks WHERE id=@P0 AND state='s'", Pid);
                        Earned -= Used;

                        // Update database if the database is off
                        if (Earned != Available || HasUsed != Used)
                            Database.Execute("UPDATE player SET availunlocks=@P0, usedunlocks=@P1 WHERE id=@P2", Earned, Used, Pid);

                        // Output more
                        Response.WriteHeaderLine("enlisted", "officer");
                        Response.WriteDataLine(Earned, 0);
                        Response.WriteHeaderLine("id", "state");

                        // Add each unlock's state
                        Rows = Database.Query("SELECT kit, state FROM unlocks WHERE id=@P0 ORDER BY kit ASC", Pid);
                        if (Rows.Count == 0)
                        {
                            // Create Player Unlock Data
                            StringBuilder Query = new StringBuilder("INSERT INTO unlocks VALUES ", 350);

                            // Normal unlocks
                            for (int i = 11; i < 100; i += 11)
                            {
                                // 88 and above are Special Forces unlocks, and wont display at all if the base unlocks are not earned
                                if (i < 78)
                                    Response.WriteDataLine(i, "n");
                                Query.AppendFormat("({0}, {1}, 'n'), ", Pid, i);
                            }

                            // Sf Unlocks, Dont display these because thats how Gamespy does it
                            for (int i = 111; i < 556; i += 111)
                            {
                                Query.AppendFormat("({0}, {1}, 'n')", Pid, i);
                                if (i != 555)
                                    Query.Append(", ");
                            }

                            // Do Insert
                            Database.Execute(Query.ToString());
                        }
                        else
                        {
                            Dictionary<string, bool> Unlocks = new Dictionary<string, bool>(7);
                            foreach (Dictionary<string, object> Unlock in Rows)
                            {
                                // Add unlock to output if its a base unlock
                                int Id = Int32.Parse(Unlock["kit"].ToString());
                                if (Id < 78)
                                    Response.WriteDataLine(Unlock["kit"], Unlock["state"]);

                                // Add Unlock to list
                                Unlocks.Add(Unlock["kit"].ToString(), (Unlock["state"].ToString() == "s"));
                            }

                            // Add SF Unlocks... We need the base class unlock unlocked first
                            CheckUnlock(88, 22, Unlocks);
                            CheckUnlock(99, 33, Unlocks);
                            CheckUnlock(111, 44, Unlocks);
                            CheckUnlock(222, 55, Unlocks);
                            CheckUnlock(333, 66, Unlocks);
                            CheckUnlock(444, 11, Unlocks);
                            CheckUnlock(555, 77, Unlocks);
                        }
                    }
                    break;

                // All Unlocked
                case 1:
                    Response.WriteDataLine(Pid, "All_Unlocks", DateTime.UtcNow.ToUnixTimestamp());
                    Response.WriteHeaderLine("enlisted", "officer");
                    Response.WriteDataLine(0, 0);
                    Response.WriteHeaderLine("id", "state");
                    for (int i = 11; i < 100; i += 11)
                        Response.WriteDataLine(i, "s");
                    for (int i = 111; i < 556; i += 111)
                        Response.WriteDataLine(i, "s");
                    break;

                // Unlocks Disabled
                case 2:
                default:
                    Response.WriteDataLine(Pid, "No_Unlocks", DateTime.UtcNow.ToUnixTimestamp());
                    Response.WriteHeaderLine("enlisted", "officer");
                    Response.WriteDataLine(0, 0);
                    Response.WriteHeaderLine("id", "state");
                    for (int i = 11; i < 78; i += 11)
                        Response.WriteDataLine(i, "n");
                    break;
            }

            // Send Response
            Response.Send();
        }
        /// <summary>
        /// Processes the query ID and returns the results
        /// </summary>
        /// <param name="id">The Query id</param>
        /// <param name="Database">The stats database connection</param>
        /// <returns></returns>
        protected List<Player> GetTopFromQuery(int id, StatsDatabase Database)
        {
            List<Player> Players = new List<Player>(5);
            var Rows = Database.Query(IndexQueries[id]);
            for (int i = 0; i < 5; i++)
            {
                if (i < Rows.Count)
                {
                    double ds = Double.Parse(Rows[i]["value"].ToString());
                    string Val = ((ds % 1) != 0) ? Math.Round(ds, 4).ToString() : FormatNumber(ds);

                    Players.Add(new Player
                    {
                        Pid = Int32.Parse(Rows[i]["id"].ToString()),
                        Name = Rows[i]["name"].ToString(),
                        Rank = Int32.Parse(Rows[i]["rank"].ToString()),
                        Value = Val
                    });
                }
                else
                {
                    Players.Add(new Player { Name = "" });
                }
            }

            return Players;
        }
Esempio n. 18
0
        /// <summary>
        /// This request provides details on a particular players rank, and
        /// whether or not to show the user a promotion/demotion announcement
        /// </summary>
        /// <queryParam name="nick" type="string">The unique player's Name</queryParam>
        /// <queryParam name="ai" type="int">Defines whether the player is a bot (used by bf2server)</queryParam>
        /// <queryParam name="playerlist" type="int">Defines whether to list the players who's nick is similair to the Nick param</queryParam>
        /// <param name="Client">The HttpClient who made the request</param>
        /// <param name="Driver">The Stats Database Driver. Connection errors are handled in the calling object</param>
        public GetPlayerID(HttpClient Client, StatsDatabase Driver)
        {
            // Setup Variables
            List<Dictionary<string, object>> Rows;
            Dictionary<string, string> QueryString = Client.Request.QueryString;

            // Querystring vars
            int IsAI = 0;
            int ListPlayers = 0;
            string PlayerNick = "";

            // Setup Params
            if (QueryString.ContainsKey("nick"))
                PlayerNick = QueryString["nick"].Replace("%20", " ");
            if (QueryString.ContainsKey("ai"))
                Int32.TryParse(QueryString["ai"], out IsAI);
            if (QueryString.ContainsKey("playerlist"))
                Int32.TryParse(QueryString["playerlist"], out ListPlayers);

            // Handle Request
            if (!String.IsNullOrWhiteSpace(PlayerNick))
            {
                int Pid;

                // Create player if they donot exist
                Rows = Driver.Query("SELECT id FROM player WHERE name = @P0 LIMIT 1", PlayerNick);
                if (Rows.Count == 0)
                {
                    // Grab new Player ID
                    Pid = LowestPid--;

                    // Create New Player Unlock Data
                    StringBuilder Query = new StringBuilder("INSERT INTO unlocks VALUES ");

                    // Normal unlocks
                    for (int i = 11; i < 100; i += 11)
                        Query.AppendFormat("({0}, {1}, 'n'), ", Pid, i);

                    // Sf Unlocks
                    for (int i = 111; i < 556; i += 111)
                    {
                        Query.AppendFormat("({0}, {1}, 'n')", Pid, i);
                        if (i != 555)
                            Query.Append(", ");
                    }

                    // Create Player
                    Driver.Execute(
                        "INSERT INTO player(id, name, joined, isbot) VALUES(@P0, @P1, @P2, @P3)",
                        Pid, PlayerNick, DateTime.UtcNow.ToUnixTimestamp(), IsAI
                    );

                    // Create player unlocks
                    Driver.Execute(Query.ToString());
                }
                else
                    Pid = Int32.Parse(Rows[0]["id"].ToString());

                // Send Response
                Client.Response.WriteResponseStart();
                Client.Response.WriteHeaderLine("pid");
                Client.Response.WriteDataLine(Pid);
            }
            else if (ListPlayers != 0)
            {
                // Prepare Response
                Client.Response.WriteResponseStart();
                Client.Response.WriteHeaderLine("pid");

                // Fetch Players
                Rows = Driver.Query("SELECT id FROM player WHERE ip <> '127.0.0.1'");
                foreach (Dictionary<string, object> Player in Rows)
                    Client.Response.WriteDataLine(Player["id"]);
            }
            else
            {
                Client.Response.WriteResponseStart(false);
                Client.Response.WriteHeaderLine("asof", "err");
                Client.Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!");
            }

            // Send Response
            Client.Response.Send();
        }
Esempio n. 19
0
        /// <summary>
        /// Method to be called everytime the HttpStatsServer is started
        /// </summary>
        public static void Load(StatsDatabase Driver)
        {
            // Get the lowest Offline PID from the database
            var Rows = Driver.Query(
                String.Format(
                    "SELECT COALESCE(MIN(id), {0}) AS min, COALESCE(MAX(id), {0}) AS max FROM player WHERE id < {1}",
                    DEFAULT_PID, MAX_PID
                )
            );

            int Lowest = Int32.Parse(Rows[0]["min"].ToString());
            int Highest = Int32.Parse(Rows[0]["max"].ToString());
            AiPid = (Lowest > DEFAULT_PID) ? DEFAULT_PID : Lowest;
            PlayerPid = (Highest < DEFAULT_PID) ? DEFAULT_PID : Highest;
        }
Esempio n. 20
0
        /// <summary>
        /// Processes the snapshot data, inserted and updating player data in the gamespy database
        /// </summary>
        /// <exception cref="InvalidDataException">Thrown if the snapshot data is invalid</exception>
        public void ProcessData()
        {
            // Make sure we are processing the same data again
            if (this.IsProcessed)
                throw new Exception("Round data has already been processed!");

            // Begin Logging
            Log(String.Format("Begin Processing ({0})...", this.MapName), LogLevel.Notice);
            Log(String.Format((this.IsCustomMap) ? "Custom Map ({0})..." : "Standard Map ({0})...", this.MapId), LogLevel.Notice);
            Log("Found " + this.Players.Count + " Player(s)...", LogLevel.Notice);

            // Make sure we meet the minimum player requirement
            if (this.Players.Count < Program.Config.ASP_MinRoundPlayers)
            {
                Log("Minimum round Player count does not meet the ASP requirement... Aborting", LogLevel.Warning);
                throw new Exception("Minimum round Player count does not meet the ASP requirement");
            }

            // CDB update
            if (this.SnapshotMode == SnapshotMode.Minimal)
                Log("Snapshot mode set to CentralDatabase.Minimal. Rank and Award data will be ingnored", LogLevel.Notice);

            // Setup some variables
            Stopwatch Clock = Stopwatch.StartNew();
            List<Dictionary<string, object>> Rows;
            InsertQueryBuilder InsertQuery;
            UpdateQueryBuilder UpdateQuery;
            WhereClause Where;

            // Start the timer and Begin Transaction
            using (StatsDatabase Driver = new StatsDatabase())
            using (DbTransaction Transaction = Driver.BeginTransaction())
            {
                // To prevent half complete snapshots due to exceptions,
                // Put the whole thing in a try block, and rollback on error
                try
                {
                    // Loop through each player, and process them
                    foreach (Player Player in this.Players)
                    {
                        // Player meets min round time or are we ignoring AI?
                        if ((Player.RoundTime < Program.Config.ASP_MinRoundTime) || (Program.Config.ASP_IgnoreAI && Player.IsAI))
                            continue;

                        // Parse some player data
                        bool OnWinningTeam = (Player.Team == WinningTeam);
                        string CountryCode = Ip2nation.GetCountryCode(Player.IpAddress);
                        int Best, Worst;

                        // Log
                        Log(String.Format("Processing Player ({0})", Player.Pid), LogLevel.Notice);

                        // Fetch the player
                        Rows = Driver.Query("SELECT ip, country, rank, killstreak, deathstreak, rndscore FROM player WHERE id=@P0", Player.Pid);
                        if (Rows.Count == 0)
                        {
                            // === New Player === //
                            Log(String.Format("Adding NEW Player ({0})", Player.Pid), LogLevel.Notice);

                            // We dont save rank data on CentralDatabase.Minimal
                            if (this.SnapshotMode == SnapshotMode.Minimal)
                                Player.SetRank(0);

                            // Build insert data
                            InsertQuery = new InsertQueryBuilder("player", Driver);
                            InsertQuery.SetField("id", Player.Pid);
                            InsertQuery.SetField("name", Player.Name);
                            InsertQuery.SetField("country", CountryCode);
                            InsertQuery.SetField("time", Player.RoundTime);
                            InsertQuery.SetField("rounds", Player.CompletedRound);
                            InsertQuery.SetField("ip", Player.IpAddress);
                            InsertQuery.SetField("score", Player.RoundScore);
                            InsertQuery.SetField("cmdscore", Player.CommandScore);
                            InsertQuery.SetField("skillscore", Player.SkillScore);
                            InsertQuery.SetField("teamscore", Player.TeamScore);
                            InsertQuery.SetField("kills", Player.Stats.Kills);
                            InsertQuery.SetField("deaths", Player.Stats.Deaths);
                            InsertQuery.SetField("captures", Player.Stats.FlagCaptures);
                            InsertQuery.SetField("captureassists", Player.Stats.FlagCaptureAssists);
                            InsertQuery.SetField("defends", Player.Stats.FlagDefends);
                            InsertQuery.SetField("damageassists", Player.Stats.DamageAssists);
                            InsertQuery.SetField("heals", Player.Stats.Heals);
                            InsertQuery.SetField("revives", Player.Stats.Revives);
                            InsertQuery.SetField("ammos", Player.Stats.Ammos);
                            InsertQuery.SetField("repairs", Player.Stats.Repairs);
                            InsertQuery.SetField("targetassists", Player.Stats.TargetAssists);
                            InsertQuery.SetField("driverspecials", Player.Stats.DriverSpecials);
                            InsertQuery.SetField("teamkills", Player.Stats.TeamKills);
                            InsertQuery.SetField("teamdamage", Player.Stats.TeamDamage);
                            InsertQuery.SetField("teamvehicledamage", Player.Stats.TeamVehicleDamage);
                            InsertQuery.SetField("suicides", Player.Stats.Suicides);
                            InsertQuery.SetField("killstreak", Player.Stats.KillStreak);
                            InsertQuery.SetField("deathstreak", Player.Stats.DeathStreak);
                            InsertQuery.SetField("rank", Player.Rank);
                            InsertQuery.SetField("banned", Player.TimesBanned);
                            InsertQuery.SetField("kicked", Player.TimesKicked);
                            InsertQuery.SetField("cmdtime", Player.CmdTime);
                            InsertQuery.SetField("sqltime", Player.SqlTime);
                            InsertQuery.SetField("sqmtime", Player.SqmTime);
                            InsertQuery.SetField("lwtime", Player.LwTime);
                            InsertQuery.SetField("wins", OnWinningTeam);
                            InsertQuery.SetField("losses", !OnWinningTeam);
                            InsertQuery.SetField("availunlocks", 0);
                            InsertQuery.SetField("usedunlocks", 0);
                            InsertQuery.SetField("joined", this.RoundEndTime);
                            InsertQuery.SetField("rndscore", Player.RoundScore);
                            InsertQuery.SetField("lastonline", RoundEndTime);
                            InsertQuery.SetField("mode0", (GameMode == 0));
                            InsertQuery.SetField("mode1", (GameMode == 1));
                            InsertQuery.SetField("mode2", (GameMode == 2));
                            InsertQuery.SetField("isbot", Player.IsAI);

                            // Insert Player Data
                            InsertQuery.Execute();

                            // Double Check Unlocks
                            if (!Player.IsAI && Driver.ExecuteScalar<int>("SELECT COUNT(*) FROM unlocks WHERE id=@P0", Player.Pid) == 0)
                            {
                                // Create New Player Unlock Data
                                StringBuilder Q = new StringBuilder("INSERT INTO unlocks VALUES ", 350);

                                // Normal unlocks
                                for (int i = 11; i < 100; i += 11)
                                    Q.AppendFormat("({0}, {1}, 'n'), ", Player.Pid, i);

                                // Sf Unlocks
                                for (int i = 111; i < 556; i += 111)
                                {
                                    Q.AppendFormat("({0}, {1}, 'n')", Player.Pid, i);
                                    if (i != 555) Q.Append(", ");
                                }

                                // Execute query
                                Driver.Execute(Q.ToString());
                            }
                        }
                        else
                        {
                            // Existing Player
                            Log(String.Format("Updating EXISTING Player ({0})", Player.Pid), LogLevel.Notice);

                            // If rank is lower then the database rank, and the players old rank is not a special rank
                            // then we will be correct the rank here. We do this because sometimes stats are interupted
                            // while being fetched in the python (yay single threading!), and the players stats are reset
                            // during that round.
                            int DbRank = Int32.Parse(Rows[0]["rank"].ToString());
                            if (this.SnapshotMode == SnapshotMode.Minimal)
                            {
                                // On CDB mode, always use database rank
                                Player.SetRank(DbRank);
                            }
                            else if (DbRank > Player.Rank && DbRank != 11 && DbRank != 21)
                            {
                                // Fail-safe in-case rank data was not obtained and reset to '0' in-game.
                                Player.SetRank(DbRank);
                                DebugLog.Write("Rank Correction ({0}), Using database rank ({1})", Player.Pid, DbRank);
                            }

                            // Calcuate best killstreak/deathstreak
                            int KillStreak = Int32.Parse(Rows[0]["killstreak"].ToString());
                            int DeathStreak = Int32.Parse(Rows[0]["deathstreak"].ToString());
                            if (Player.Stats.KillStreak > KillStreak) KillStreak = Player.Stats.KillStreak;
                            if (Player.Stats.DeathStreak > DeathStreak) DeathStreak = Player.Stats.DeathStreak;

                            // Calculate Best Round Score
                            int Brs = Int32.Parse(Rows[0]["rndscore"].ToString());
                            if (Player.RoundScore > Brs) Brs = Player.RoundScore;

                            // Update Player Data
                            UpdateQuery = new UpdateQueryBuilder("player", Driver);
                            UpdateQuery.SetField("country", CountryCode, ValueMode.Set);
                            UpdateQuery.SetField("time", Player.RoundTime, ValueMode.Add);
                            UpdateQuery.SetField("rounds", Player.CompletedRound, ValueMode.Add);
                            UpdateQuery.SetField("ip", Player.IpAddress, ValueMode.Set);
                            UpdateQuery.SetField("score", Player.RoundScore, ValueMode.Add);
                            UpdateQuery.SetField("cmdscore", Player.CommandScore, ValueMode.Add);
                            UpdateQuery.SetField("skillscore", Player.SkillScore, ValueMode.Add);
                            UpdateQuery.SetField("teamscore", Player.TeamScore, ValueMode.Add);
                            UpdateQuery.SetField("kills", Player.Stats.Kills, ValueMode.Add);
                            UpdateQuery.SetField("deaths", Player.Stats.Deaths, ValueMode.Add);
                            UpdateQuery.SetField("captures", Player.Stats.FlagCaptures, ValueMode.Add);
                            UpdateQuery.SetField("captureassists", Player.Stats.FlagCaptureAssists, ValueMode.Add);
                            UpdateQuery.SetField("defends", Player.Stats.FlagDefends, ValueMode.Add);
                            UpdateQuery.SetField("damageassists", Player.Stats.DamageAssists, ValueMode.Add);
                            UpdateQuery.SetField("heals", Player.Stats.Heals, ValueMode.Add);
                            UpdateQuery.SetField("revives", Player.Stats.Revives, ValueMode.Add);
                            UpdateQuery.SetField("ammos", Player.Stats.Ammos, ValueMode.Add);
                            UpdateQuery.SetField("repairs", Player.Stats.Repairs, ValueMode.Add);
                            UpdateQuery.SetField("targetassists", Player.Stats.TargetAssists, ValueMode.Add);
                            UpdateQuery.SetField("driverspecials", Player.Stats.DriverSpecials, ValueMode.Add);
                            UpdateQuery.SetField("teamkills", Player.Stats.TeamKills, ValueMode.Add);
                            UpdateQuery.SetField("teamdamage", Player.Stats.TeamDamage, ValueMode.Add);
                            UpdateQuery.SetField("teamvehicledamage", Player.Stats.TeamVehicleDamage, ValueMode.Add);
                            UpdateQuery.SetField("suicides", Player.Stats.Suicides, ValueMode.Add);
                            UpdateQuery.SetField("Killstreak", KillStreak, ValueMode.Set);
                            UpdateQuery.SetField("deathstreak", DeathStreak, ValueMode.Set);
                            UpdateQuery.SetField("rank", Player.Rank, ValueMode.Set);
                            UpdateQuery.SetField("banned", Player.TimesBanned, ValueMode.Add);
                            UpdateQuery.SetField("kicked", Player.TimesKicked, ValueMode.Add);
                            UpdateQuery.SetField("cmdtime", Player.CmdTime, ValueMode.Add);
                            UpdateQuery.SetField("sqltime", Player.SqlTime, ValueMode.Add);
                            UpdateQuery.SetField("sqmtime", Player.SqmTime, ValueMode.Add);
                            UpdateQuery.SetField("lwtime", Player.LwTime, ValueMode.Add);
                            UpdateQuery.SetField("wins", OnWinningTeam, ValueMode.Add);
                            UpdateQuery.SetField("losses", !OnWinningTeam, ValueMode.Add);
                            UpdateQuery.SetField("rndscore", Brs, ValueMode.Set);
                            UpdateQuery.SetField("lastonline", this.RoundEndTime, ValueMode.Set);
                            UpdateQuery.SetField("mode0", (GameMode == 0), ValueMode.Add);
                            UpdateQuery.SetField("mode1", (GameMode == 1), ValueMode.Add);
                            UpdateQuery.SetField("mode2", (GameMode == 2), ValueMode.Add);
                            UpdateQuery.SetField("chng", (Player.Rank > DbRank), ValueMode.Set);
                            UpdateQuery.SetField("decr", (Player.Rank < DbRank), ValueMode.Set);
                            UpdateQuery.SetField("isbot", Player.IsAI, ValueMode.Set);
                            UpdateQuery.AddWhere("id", Comparison.Equals, Player.Pid);
                            UpdateQuery.Execute();
                        }

                        // ********************************
                        // Insert Player history.
                        // ********************************
                        Driver.Execute(
                            "INSERT INTO player_history VALUES(@P0, @P1, @P2, @P3, @P4, @P5, @P6, @P7, @P8, @P9)",
                            Player.Pid, this.RoundEndTime, Player.RoundTime, Player.RoundScore, Player.CommandScore,
                            Player.SkillScore, Player.TeamScore, Player.Stats.Kills, Player.Stats.Deaths, Player.Rank
                        );

                        // ********************************
                        // Process Player Army Data
                        // ********************************
                        Log(String.Format("Processing Army Data ({0})", Player.Pid), LogLevel.Notice);

                        // Update player army times
                        Rows = Driver.Query("SELECT * FROM army WHERE id=" + Player.Pid);
                        if (Rows.Count == 0)
                        {
                            // Build query
                            InsertQuery = new InsertQueryBuilder("army", Driver);
                            InsertQuery.SetField("id", Player.Pid);
                            for (int i = 0; i < 14; i++)
                                InsertQuery.SetField("time" + i, Player.TimeAsArmy[i]);

                            // Make sure we arent playing an unsupported army
                            if (Player.ArmyId < 14)
                            {
                                InsertQuery.SetField("win" + Player.ArmyId, OnWinningTeam);
                                InsertQuery.SetField("loss" + Player.ArmyId, !OnWinningTeam);
                                InsertQuery.SetField("score" + Player.ArmyId, Player.RoundScore);
                                InsertQuery.SetField("best" + Player.ArmyId, Player.RoundScore);
                                InsertQuery.SetField("worst" + Player.ArmyId, Player.RoundScore);
                            }

                            InsertQuery.Execute();
                        }
                        else
                        {
                            // Build query
                            UpdateQuery = new UpdateQueryBuilder("army", Driver);
                            UpdateQuery.AddWhere("id", Comparison.Equals, Player.Pid);
                            for (int i = 0; i < 14; i++)
                                UpdateQuery.SetField("time" + i, Player.TimeAsArmy[i], ValueMode.Add);

                            // Prevent database errors with custom army IDs
                            if (Player.ArmyId < 14)
                            {
                                Best = Int32.Parse(Rows[0]["best" + Player.ArmyId].ToString());
                                Worst = Int32.Parse(Rows[0]["worst" + Player.ArmyId].ToString());
                                if (Player.RoundScore > Best) Best = Player.RoundScore;
                                if (Player.RoundScore < Worst) Worst = Player.RoundScore;

                                UpdateQuery.SetField("win" + Player.ArmyId, OnWinningTeam, ValueMode.Add);
                                UpdateQuery.SetField("loss" + Player.ArmyId, !OnWinningTeam, ValueMode.Add);
                                UpdateQuery.SetField("score" + Player.ArmyId, Player.RoundScore, ValueMode.Add);
                                UpdateQuery.SetField("best" + Player.ArmyId, Best, ValueMode.Set);
                                UpdateQuery.SetField("worst" + Player.ArmyId, Worst, ValueMode.Set);
                            }

                            UpdateQuery.Execute();
                        }

                        // ********************************
                        // Process Player Kills
                        // ********************************
                        Log(String.Format("Processing Kills Data ({0})", Player.Pid), LogLevel.Notice);
                        foreach (KeyValuePair<int, int> Kill in Player.Victims)
                        {
                            // Kill: VictimPid => KillCount
                            if (Driver.ExecuteScalar<int>("SELECT COUNT(*) FROM kills WHERE attacker=@P0 AND victim=@P1", Player.Pid, Kill.Key) == 0)
                            {
                                InsertQuery = new InsertQueryBuilder("kills", Driver);
                                InsertQuery.SetField("attacker", Player.Pid);
                                InsertQuery.SetField("victim", Kill.Key);
                                InsertQuery.SetField("count", Kill.Value);
                                InsertQuery.Execute();
                            }
                            else
                            {
                                UpdateQuery = new UpdateQueryBuilder("kills", Driver);
                                UpdateQuery.SetField("count", Kill.Value, ValueMode.Add);
                                Where = UpdateQuery.AddWhere("attacker", Comparison.Equals, Player.Pid);
                                Where.AddClause(LogicOperator.And, "victim", Comparison.Equals, Kill.Key);
                                UpdateQuery.Execute();
                            }
                        }

                        // ********************************
                        // Process Player Kit Data
                        // ********************************
                        Log(String.Format("Processing Kit Data ({0})", Player.Pid), LogLevel.Notice);

                        // Check for existing player data
                        if (Driver.ExecuteScalar<int>("SELECT COUNT(*) FROM kits WHERE id=" + Player.Pid) == 0)
                        {
                            InsertQuery = new InsertQueryBuilder("kits", Driver);
                            InsertQuery.SetField("id", Player.Pid);
                            for (int i = 0; i < 7; i++)
                            {
                                InsertQuery.SetField("time" + i, Player.KitData[i].Time);
                                InsertQuery.SetField("kills" + i, Player.KitData[i].Kills);
                                InsertQuery.SetField("deaths" + i, Player.KitData[i].Deaths);
                            }
                            InsertQuery.Execute();
                        }
                        else
                        {
                            UpdateQuery = new UpdateQueryBuilder("kits", Driver);
                            UpdateQuery.AddWhere("id", Comparison.Equals, Player.Pid);
                            for (int i = 0; i < 7; i++)
                            {
                                UpdateQuery.SetField("time" + i, Player.KitData[i].Time, ValueMode.Add);
                                UpdateQuery.SetField("kills" + i, Player.KitData[i].Kills, ValueMode.Add);
                                UpdateQuery.SetField("deaths" + i, Player.KitData[i].Deaths, ValueMode.Add);
                            }
                            UpdateQuery.Execute();
                        }

                        // ********************************
                        // Process Player Vehicle Data
                        // ********************************
                        Log(String.Format("Processing Vehicle Data ({0})", Player.Pid), LogLevel.Notice);

                        // Check for existing player data
                        if (Driver.ExecuteScalar<int>("SELECT COUNT(*) FROM vehicles WHERE id=" + Player.Pid) == 0)
                        {
                            InsertQuery = new InsertQueryBuilder("vehicles", Driver);
                            InsertQuery.SetField("id", Player.Pid);
                            for (int i = 0; i < 7; i++)
                            {
                                InsertQuery.SetField("time" + i, Player.VehicleData[i].Time);
                                InsertQuery.SetField("kills" + i, Player.VehicleData[i].Kills);
                                InsertQuery.SetField("deaths" + i, Player.VehicleData[i].Deaths);
                                InsertQuery.SetField("rk" + i, Player.VehicleData[i].RoadKills);
                            }
                            InsertQuery.SetField("timepara", Player.VehicleData[7].Time);
                            InsertQuery.Execute();
                        }
                        else
                        {
                            UpdateQuery = new UpdateQueryBuilder("vehicles", Driver);
                            UpdateQuery.AddWhere("id", Comparison.Equals, Player.Pid);
                            for (int i = 0; i < 7; i++)
                            {
                                UpdateQuery.SetField("time" + i, Player.VehicleData[i].Time, ValueMode.Add);
                                UpdateQuery.SetField("kills" + i, Player.VehicleData[i].Kills, ValueMode.Add);
                                UpdateQuery.SetField("deaths" + i, Player.VehicleData[i].Deaths, ValueMode.Add);
                                UpdateQuery.SetField("rk" + i, Player.VehicleData[i].RoadKills, ValueMode.Add);
                            }
                            UpdateQuery.SetField("timepara", Player.VehicleData[7].Time, ValueMode.Add);
                            UpdateQuery.Execute();
                        }

                        // ********************************
                        // Process Player Weapon Data
                        // ********************************
                        Log(String.Format("Processing Weapon Data ({0})", Player.Pid), LogLevel.Notice);

                        // Check for existing player data
                        if (Driver.ExecuteScalar<int>("SELECT COUNT(*) FROM weapons WHERE id=" + Player.Pid) == 0)
                        {
                            // Prepare Query
                            InsertQuery = new InsertQueryBuilder("weapons", Driver);
                            InsertQuery.SetField("id", Player.Pid);

                            // Basic Weapon Data
                            for (int i = 0; i < 15; i++)
                            {
                                if (i < 9)
                                {
                                    InsertQuery.SetField("time" + i, Player.WeaponData[i].Time);
                                    InsertQuery.SetField("kills" + i, Player.WeaponData[i].Kills);
                                    InsertQuery.SetField("deaths" + i, Player.WeaponData[i].Deaths);
                                    InsertQuery.SetField("fired" + i, Player.WeaponData[i].Fired);
                                    InsertQuery.SetField("hit" + i, Player.WeaponData[i].Hits);
                                }
                                else
                                {
                                    string Pfx = GetWeaponTblPrefix(i);
                                    InsertQuery.SetField(Pfx + "time", Player.WeaponData[i].Time);
                                    InsertQuery.SetField(Pfx + "kills", Player.WeaponData[i].Kills);
                                    InsertQuery.SetField(Pfx + "deaths", Player.WeaponData[i].Deaths);
                                    InsertQuery.SetField(Pfx + "fired", Player.WeaponData[i].Fired);
                                    InsertQuery.SetField(Pfx + "hit", Player.WeaponData[i].Hits);
                                }
                            }

                            // Tactical
                            InsertQuery.SetField("tacticaltime", Player.WeaponData[15].Time);
                            InsertQuery.SetField("tacticaldeployed", Player.WeaponData[15].Deployed);

                            // Grappling Hook
                            InsertQuery.SetField("grapplinghooktime", Player.WeaponData[16].Time);
                            InsertQuery.SetField("grapplinghookdeployed", Player.WeaponData[16].Deployed);
                            InsertQuery.SetField("grapplinghookdeaths", Player.WeaponData[16].Deaths);

                            // Zipline
                            InsertQuery.SetField("ziplinetime", Player.WeaponData[17].Time);
                            InsertQuery.SetField("ziplinedeployed", Player.WeaponData[17].Deployed);
                            InsertQuery.SetField("ziplinedeaths", Player.WeaponData[17].Deaths);

                            // Do Query
                            InsertQuery.Execute();
                        }
                        else
                        {
                            // Prepare Query
                            UpdateQuery = new UpdateQueryBuilder("weapons", Driver);
                            UpdateQuery.AddWhere("id", Comparison.Equals, Player.Pid);

                            // Basic Weapon Data
                            for (int i = 0; i < 15; i++)
                            {
                                if (i < 9)
                                {
                                    UpdateQuery.SetField("time" + i, Player.WeaponData[i].Time, ValueMode.Add);
                                    UpdateQuery.SetField("kills" + i, Player.WeaponData[i].Kills, ValueMode.Add);
                                    UpdateQuery.SetField("deaths" + i, Player.WeaponData[i].Deaths, ValueMode.Add);
                                    UpdateQuery.SetField("fired" + i, Player.WeaponData[i].Fired, ValueMode.Add);
                                    UpdateQuery.SetField("hit" + i, Player.WeaponData[i].Hits, ValueMode.Add);
                                }
                                else
                                {
                                    string Pfx = GetWeaponTblPrefix(i);
                                    UpdateQuery.SetField(Pfx + "time", Player.WeaponData[i].Time, ValueMode.Add);
                                    UpdateQuery.SetField(Pfx + "kills", Player.WeaponData[i].Kills, ValueMode.Add);
                                    UpdateQuery.SetField(Pfx + "deaths", Player.WeaponData[i].Deaths, ValueMode.Add);
                                    UpdateQuery.SetField(Pfx + "fired", Player.WeaponData[i].Fired, ValueMode.Add);
                                    UpdateQuery.SetField(Pfx + "hit", Player.WeaponData[i].Hits, ValueMode.Add);
                                }
                            }

                            // Tactical
                            UpdateQuery.SetField("tacticaltime", Player.WeaponData[15].Time, ValueMode.Add);
                            UpdateQuery.SetField("tacticaldeployed", Player.WeaponData[15].Deployed, ValueMode.Add);

                            // Grappling Hook
                            UpdateQuery.SetField("grapplinghooktime", Player.WeaponData[16].Time, ValueMode.Add);
                            UpdateQuery.SetField("grapplinghookdeployed", Player.WeaponData[16].Deployed, ValueMode.Add);
                            UpdateQuery.SetField("grapplinghookdeaths", Player.WeaponData[16].Deaths, ValueMode.Add);

                            // Zipline
                            UpdateQuery.SetField("ziplinetime", Player.WeaponData[17].Time, ValueMode.Add);
                            UpdateQuery.SetField("ziplinedeployed", Player.WeaponData[17].Deployed, ValueMode.Add);
                            UpdateQuery.SetField("ziplinedeaths", Player.WeaponData[17].Deaths, ValueMode.Add);

                            // Do Query
                            UpdateQuery.Execute();
                        }

                        // ********************************
                        // Process Player Map Data
                        // ********************************
                        Log(String.Format("Processing Map Data ({0})", Player.Pid), LogLevel.Notice);

                        Rows = Driver.Query("SELECT best, worst FROM maps WHERE id=@P0 AND mapid=@P1", Player.Pid, MapId);
                        if (Rows.Count == 0)
                        {
                            // Prepare Query
                            InsertQuery = new InsertQueryBuilder("maps", Driver);
                            InsertQuery.SetField("id", Player.Pid);
                            InsertQuery.SetField("mapid", this.MapId);
                            InsertQuery.SetField("time", Player.RoundTime);
                            InsertQuery.SetField("win", OnWinningTeam);
                            InsertQuery.SetField("loss", !OnWinningTeam);
                            InsertQuery.SetField("best", Player.RoundScore);
                            InsertQuery.SetField("worst", Player.RoundScore);
                            InsertQuery.Execute();
                        }
                        else
                        {
                            // Get best and worst round scores
                            Best = Int32.Parse(Rows[0]["best"].ToString());
                            Worst = Int32.Parse(Rows[0]["worst"].ToString());
                            if (Player.RoundScore > Best) Best = Player.RoundScore;
                            if (Player.RoundScore < Worst) Worst = Player.RoundScore;

                            // Prepare Query
                            UpdateQuery = new UpdateQueryBuilder("maps", Driver);
                            Where = UpdateQuery.AddWhere("id", Comparison.Equals, Player.Pid);
                            Where.AddClause(LogicOperator.And, "mapid", Comparison.Equals, this.MapId);
                            UpdateQuery.SetField("time", Player.RoundTime, ValueMode.Add);
                            UpdateQuery.SetField("win", OnWinningTeam, ValueMode.Add);
                            UpdateQuery.SetField("loss", !OnWinningTeam, ValueMode.Add);
                            UpdateQuery.SetField("best", Best, ValueMode.Set);
                            UpdateQuery.SetField("worst", Worst, ValueMode.Set);
                            UpdateQuery.Execute();
                        }

                        // Quit here on central database Min mode, since award data isnt allowed
                        if (this.SnapshotMode == SnapshotMode.Minimal) continue;

                        // ********************************
                        // Process Player Awards Data
                        // ********************************
                        Log(String.Format("Processing Award Data ({0})", Player.Pid), LogLevel.Notice);

                        // Do we require round completion for award processing?
                        if (Player.CompletedRound || !Program.Config.ASP_AwardsReqComplete)
                        {
                            // Prepare query
                            InsertQuery = new InsertQueryBuilder("awards", Driver);

                            // Add Backend awards too
                            foreach (BackendAward Award in BackendAwardData.BackendAwards)
                            {
                                int Level = 1;
                                if (Award.CriteriaMet(Player.Pid, Driver, ref Level))
                                    Player.EarnedAwards.Add(Award.AwardId, Level);
                            }

                            // Now we loop though each players earned award, and store them in the database
                            foreach (KeyValuePair<int, int> Award in Player.EarnedAwards)
                            {
                                // Get our award type. Award.Key is the ID, Award.Value is the level (or count)
                                bool IsMedal = Award.Key.InRange(2000000, 3000000);
                                bool IsBadge = (Award.Key < 2000000);

                                // Build our query
                                string Query = "SELECT COUNT(*) FROM awards WHERE id=@P0 AND awd=@P1";
                                if (IsBadge)
                                    Query += " AND level=" + Award.Value.ToString();

                                // Check for prior awarding of award
                                if (Driver.ExecuteScalar<int>(Query, Player.Pid, Award.Key) == 0)
                                {
                                    // Need to do extra work for Badges as more than one badge level may have been awarded.
                                    // The snapshot will only post the highest awarded level of a badge, so here we award
                                    // the lower level badges if the player does not have them.
                                    if (IsBadge)
                                    {
                                        // Check all prior badge levels, and make sure the player has them
                                        for (int j = 1; j < Award.Value; j++)
                                        {
                                            Query = "SELECT COUNT(*) FROM awards WHERE id=@P0 AND awd=@P1 AND level=@P2";
                                            if (Driver.ExecuteScalar<int>(Query, Player.Pid, Award.Key, j) == 0)
                                            {
                                                // Prepare Query
                                                InsertQuery.SetField("id", Player.Pid);
                                                InsertQuery.SetField("awd", Award.Key);
                                                InsertQuery.SetField("level", j);
                                                InsertQuery.SetField("earned", (this.RoundEndTime - 5) + j);
                                                InsertQuery.SetField("first", 0);
                                                InsertQuery.Execute();
                                            }
                                        }
                                    }

                                    // Add the players award
                                    InsertQuery.SetField("id", Player.Pid);
                                    InsertQuery.SetField("awd", Award.Key);
                                    InsertQuery.SetField("level", Award.Value);
                                    InsertQuery.SetField("earned", this.RoundEndTime);
                                    InsertQuery.SetField("first", ((IsMedal) ? this.RoundEndTime : 0));
                                    InsertQuery.Execute();

                                }
                                else // === Player has recived this award prior === //
                                {
                                    // Only update medals because ribbons and badges are only awarded once ever!
                                    if (IsMedal)
                                    {
                                        // Prepare Query
                                        UpdateQuery = new UpdateQueryBuilder("awards", Driver);
                                        Where = UpdateQuery.AddWhere("id", Comparison.Equals, Player.Pid);
                                        Where.AddClause(LogicOperator.And, "awd", Comparison.Equals, Award.Key);
                                        UpdateQuery.SetField("level", 1, ValueMode.Add);
                                        UpdateQuery.SetField("earned", this.RoundEndTime, ValueMode.Set);
                                        UpdateQuery.Execute();
                                    }
                                }

                                // Add best round count if player earned best round medal
                                if (Award.Key == 2051907 && Player.ArmyId < 14)
                                {
                                    // Prepare Query
                                    UpdateQuery = new UpdateQueryBuilder("army", Driver);
                                    UpdateQuery.AddWhere("id", Comparison.Equals, Player.Pid);
                                    UpdateQuery.SetField("brnd" + Player.ArmyId, 1, ValueMode.Add);
                                    UpdateQuery.Execute();
                                }

                            } // End Foreach Award
                        } // End Award Processing
                    } // End Foreach Player

                    // ********************************
                    // Process ServerInfo
                    // ********************************
                    //Log("Processing Game Server", LogLevel.Notice);

                    // ********************************
                    // Process MapInfo
                    // ********************************
                    Log(String.Format("Processing Map Info ({0}:{1})", this.MapName, this.MapId), LogLevel.Notice);
                    if (Driver.ExecuteScalar<int>("SELECT COUNT(*) FROM mapinfo WHERE id=" + this.MapId) == 0)
                    {
                        // Prepare Query
                        InsertQuery = new InsertQueryBuilder("mapinfo", Driver);
                        InsertQuery.SetField("id", this.MapId);
                        InsertQuery.SetField("name", this.MapName);
                        InsertQuery.SetField("score", this.MapScore);
                        InsertQuery.SetField("time", this.RoundTime.Seconds);
                        InsertQuery.SetField("times", 1);
                        InsertQuery.SetField("kills", this.MapKills);
                        InsertQuery.SetField("deaths", this.MapDeaths);
                        InsertQuery.SetField("custom", (this.IsCustomMap) ? 1 : 0);
                        InsertQuery.Execute();
                    }
                    else
                    {
                        UpdateQuery = new UpdateQueryBuilder("mapinfo", Driver);
                        UpdateQuery.AddWhere("id", Comparison.Equals, this.MapId);
                        UpdateQuery.SetField("score", this.MapScore, ValueMode.Add);
                        UpdateQuery.SetField("time", this.RoundTime.Seconds, ValueMode.Add);
                        UpdateQuery.SetField("times", 1, ValueMode.Add);
                        UpdateQuery.SetField("kills", this.MapKills, ValueMode.Add);
                        UpdateQuery.SetField("deaths", this.MapDeaths, ValueMode.Add);
                        UpdateQuery.Execute();
                    }

                    // ********************************
                    // Process RoundInfo
                    // ********************************
                    Log("Processing Round Info", LogLevel.Notice);
                    InsertQuery = new InsertQueryBuilder("round_history", Driver);
                    InsertQuery.SetField("timestamp", this.RoundEndTime);
                    InsertQuery.SetField("mapid", this.MapId);
                    InsertQuery.SetField("time", this.RoundTime.Seconds);
                    InsertQuery.SetField("team1", this.Team1ArmyId);
                    InsertQuery.SetField("team2", this.Team2ArmyId);
                    InsertQuery.SetField("tickets1", this.Team1Tickets);
                    InsertQuery.SetField("tickets2", this.Team2Tickets);
                    InsertQuery.SetField("pids1", this.Team1Players);
                    InsertQuery.SetField("pids1_end", this.Team1PlayersEnd);
                    InsertQuery.SetField("pids2", this.Team2Players);
                    InsertQuery.SetField("pids2_end", this.Team2PlayersEnd);
                    InsertQuery.Execute();

                    // ********************************
                    // Process Smoc And General Ranks
                    // ********************************
                    if (Program.Config.ASP_SmocCheck) SmocCheck(Driver);
                    if (Program.Config.ASP_GeneralCheck) GenCheck(Driver);

                    // ********************************
                    // Commit the Transaction and Log
                    // ********************************
                    Transaction.Commit();
                    Clock.Stop();

                    // Log in the stats debug log, and call it
                    this.IsProcessed = true;
                    string logText = String.Format(
                        "Snapshot ({0}) processed in {1} milliseconds [{2} Queries]",
                        this.MapName, Clock.Elapsed.Milliseconds, Driver.NumQueries
                    );
                    Log(logText, LogLevel.Info);
                }
                catch (Exception E)
                {
                    Log("An error occured while updating player stats: " + E.Message, LogLevel.Error);
                    ExceptionHandler.GenerateExceptionLog(E);
                    Transaction.Rollback();
                    throw;
                }
            }
        }
Esempio n. 21
0
        /// <summary>
        /// Initializes a new Snapshot, with the specified Date it was Posted
        /// </summary>
        /// <param name="Snapshot">The snapshot source</param>
        /// <param name="Date">The original date in which this snapshot was created</param>
        public Snapshot(string Snapshot, DateTime Date, StatsDatabase Database)
        {
            // Load out database connection
            this.Driver = Database;
            this.Date = Date;
            this.TimeStamp = Date.ToUnixTimestamp();

            // Get our snapshot key value pairs
            string[] Data = Snapshot.Split('\\');
            Snapshot = null;

            // Check for invalid snapshot string. All snapshots have at least 36 data pairs,
            // and has an Even number of data sectors. We must also have an "End of File" Sector
            if (Data.Length < 36 || Data.Length % 2 != 0 || !Data.Contains("EOF"))
            {
                IsValid = false;
                return;
            }

            // Define if we are central update. the "cdb_update" variable must be the LAST sector in snapshot
            this.IsCentralUpdate = (Data[Data.Length - 2] == "cdb_update" && Data[Data.Length - 1] == "1");

            // Server data
            this.ServerPrefix = Data[0];
            this.ServerName = Data[1];
            this.ServerPort = int.Parse(Data[3].ToString());
            this.QueryPort = int.Parse(Data[5].ToString());

            // Map Data
            this.MapName = Data[7];
            this.MapId = int.Parse(Data[9]);
            this.MapStart = (int)Convert.ToDouble(Data[11], CultureInfo.InvariantCulture.NumberFormat);
            this.MapEnd = (int)Convert.ToDouble(Data[13], CultureInfo.InvariantCulture.NumberFormat);

            // Misc Data
            this.WinningTeam = int.Parse(Data[15]);
            this.GameMode = int.Parse(Data[17]);
            this.Mod = Data[21];
            this.PlayersConnected = int.Parse(Data[23]);

            // Army Data
            this.WinningArmy = int.Parse(Data[25]);
            this.Team1Army = int.Parse(Data[27]);
            this.Team1Tickets = int.Parse(Data[29]);
            this.Team2Army = int.Parse(Data[31]);
            this.Team2Tickets = int.Parse(Data[33]);

            // Setup snapshot variables
            PlayerData = new Dictionary<int, Dictionary<string, string>>();
            KillData = new Dictionary<int, Dictionary<string, string>>();

            // Check for custom map, with no ID
            if (MapId == 99)
            {
                IsCustomMap = true;

                // Check for existing map data
                List<Dictionary<string, object>> Rows = Driver.Query("SELECT id FROM mapinfo WHERE name=@P0", MapName);
                if (Rows.Count == 0)
                {
                    // Create new MapId. Id's 700 - 1000 are reserved for unknown maps in the Constants.py file
                    // There should never be more then 300 unknown map id's, considering 1001 is the start of KNOWN
                    // Custom mod map id's
                    Rows = Driver.Query("SELECT COALESCE(MAX(id), 699) AS id FROM mapinfo WHERE id BETWEEN 700 AND 1000");
                    MapId = Int32.Parse(Rows[0]["id"].ToString()) + 1;

                    // Insert map data, so we dont lose this mapid we generated
                    Driver.Execute("INSERT INTO mapinfo(id, name) VALUES (@P0, @P1)", MapId, MapName);
                }
                else
                    MapId = Int32.Parse(Rows[0]["id"].ToString());
            }
            else
                IsCustomMap = (MapId >= 700);

            // Do player snapshots, sector 36 is first player
            for (int i = 36; i < Data.Length; i += 2)
            {
                // Format: "DataKey_PlayerId". PlayerId is not the PID, but rather
                // the player INDEX
                string[] Parts = Data[i].Split('_');

                // Ignore uncomplete snapshots
                if (Parts.Length == 1)
                {
                    // Unless we are at the end of file, IF there is no PID
                    // Given for an item, the snapshot is invalid!
                    if (Parts[0] == "EOF")
                        break;
                    else
                        IsValid = false;
                    return;
                }

                // If the item key is "pID", then we have a new player record
                int id = int.Parse(Parts[1]);
                if (Parts[0] == "pID")
                {
                    PlayerData.Add(id, new Dictionary<string, string>());
                    KillData.Add(id, new Dictionary<string, string>());
                }

                // Kill and death data has its own array key
                if (Parts[0] == "mvks")
                    continue;

                if (Parts[0] == "mvns")
                    KillData[id].Add(Data[i + 1], Data[i + 3]);
                else
                    PlayerData[id].Add(Parts[0], Data[i + 1]);
            }

            // Set that we appear to be valid
            IsValid = true;
        }
Esempio n. 22
0
        /// <summary>
        /// Exports a players stats and history into an Xml file
        /// </summary>
        /// <param name="XmlPath">The folder path to where the XML will be saved</param>
        /// <param name="Pid">Player ID</param>
        /// <param name="Name">Player Name</param>
        public static void ExportPlayerXml(string XmlPath, int Pid, string Name)
        {
            //  Create full path
            string sPath = Path.Combine(
                XmlPath,
                String.Format("{0}_{1}_{2}.xml", Name.Trim().MakeFileNameSafe(), Pid, DateTime.Now.ToString("yyyyMMdd_HHmm"))
            );

            // Delete file if it exists already
            if (File.Exists(sPath))
                File.Delete(sPath);

            // Create XML Settings
            XmlWriterSettings Settings = new XmlWriterSettings();
            Settings.Indent = true;
            Settings.IndentChars = "\t";
            Settings.NewLineChars = Environment.NewLine;
            Settings.NewLineHandling = NewLineHandling.Replace;

            // Write XML data
            using (StatsDatabase Driver = new StatsDatabase())
            using (XmlWriter Writer = XmlWriter.Create(sPath, Settings))
            {
                // Player Element
                Writer.WriteStartDocument();
                Writer.WriteStartElement("Player");

                // Manifest
                Writer.WriteStartElement("Info");
                Writer.WriteElementString("Pid", Pid.ToString());
                Writer.WriteElementString("Name", Name.EscapeXML());
                Writer.WriteElementString("BackupDate", DateTime.Now.ToString());
                Writer.WriteEndElement();

                // Start Tables Element
                Writer.WriteStartElement("TableData");

                // Add each tables data
                foreach (string Table in StatsDatabase.PlayerTables)
                {
                    // Open table tag
                    Writer.WriteStartElement(Table);

                    // Fetch row
                    List<Dictionary<string, object>> Rows;
                    if (Table == "kills")
                        Rows = Driver.Query(String.Format("SELECT * FROM {0} WHERE attacker={1} OR victim={1}", Table, Pid));
                    else
                        Rows = Driver.Query(String.Format("SELECT * FROM {0} WHERE id={1}", Table, Pid));

                    // Write each row's columns with its value to the xml file
                    foreach (Dictionary<string, object> Row in Rows)
                    {
                        // Open Row tag
                        Writer.WriteStartElement("Row");
                        foreach (KeyValuePair<string, object> Column in Row)
                        {
                            if (Column.Key == "name")
                                Writer.WriteElementString(Column.Key, Column.Value.ToString().EscapeXML());
                            else
                                Writer.WriteElementString(Column.Key, Column.Value.ToString());
                        }

                        // Close Row tag
                        Writer.WriteEndElement();
                    }

                    // Close table tag
                    Writer.WriteEndElement();
                }

                // Close Tags and File
                Writer.WriteEndElement();  // Close Tables Element
                Writer.WriteEndElement();  // Close Player Element
                Writer.WriteEndDocument(); // End and Save file
            }
        }
        public override void HandleRequest(MvcRoute Route)
        {
            // NOTE: The HttpServer will handle the DbConnectException
            using (StatsDatabase Database = new StatsDatabase())
            {
                if (Program.Config.BF2S_HomePageType == HomePageType.Leaderboard)
                {
                    // Fetch our player list
                    Model.Players = Database.Query(
                        "SELECT id, name, rank, score, kills, country, time FROM player WHERE score > 0 ORDER BY score DESC LIMIT "
                        + Program.Config.BF2S_LeaderCount
                    );

                    // Send response
                    base.SendTemplateResponse("index_leaderboard", typeof(IndexModel), Model);
                }
                else
                {
                    // Fetch our top 10 player list
                    Model.Players = Database.Query("SELECT id, name, score FROM player WHERE score > 0 ORDER BY score DESC LIMIT 10");

                    // Fetch our cookie, which contains our personal leaderboard Pid's
                    int[] pids = new int[0];
                    HttpRequest Request = Client.Request;
                    Cookie C = Request.Request.Cookies["leaderboard"] ?? new Cookie("leaderboard", "");

                    // Read pids from the cookie
                    try
                    {
                        // Pids are stored as xxxx|yyyyy|zzzz in the cookie
                        if (C.Value.Length > 0)
                        {
                            string[] players = C.Value.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                            if (players.Length > 0)
                            {
                                pids = Array.ConvertAll(players, Int32.Parse).Distinct().ToArray();
                            }
                        }
                    }
                    catch
                    {
                        // Bad Cookie value, so flush it!
                        C.Value = String.Empty;
                        C.Path = "/";
                        Client.Response.SetCookie(C);
                    }

                    var Rows = Database.Query(
                        String.Format("SELECT id, name, score, time, country, rank, lastonline, kills, deaths FROM player WHERE id IN ({0})", String.Join(",", pids)
                    ));

                    // Loop through each result, and process
                    foreach (Dictionary<string, object> Row in Rows)
                    {
                        // DO Kill Death Ratio
                        double Kills = Int32.Parse(Row["kills"].ToString());
                        double Deaths = Int32.Parse(Row["deaths"].ToString());
                        double Kdr = (Deaths > 0) ? Math.Round(Kills / Deaths, 3) : Kills;

                        // Get Score Per Min
                        double Score = Int32.Parse(Row["score"].ToString());
                        double Mins = Int32.Parse(Row["time"].ToString()) / 60;
                        double SPM = (Mins > 0) ? Math.Round(Score / Mins, 4) : Score;

                        int Pid = Int32.Parse(Row["id"].ToString());

                        // Add Result
                        Model.MyLeaderboardPlayers.Add(new PlayerResult
                        {
                            Pid = Pid,
                            Name = Row["name"].ToString(),
                            Score = (int)Score,
                            Rank = Int32.Parse(Row["rank"].ToString()),
                            TimePlayed = FormatTime(Int32.Parse(Row["time"].ToString())),
                            LastOnline = FormatDate(Int32.Parse(Row["lastonline"].ToString())),
                            Country = Row["country"].ToString().ToUpperInvariant(),
                            Kdr = Kdr,
                            Spm = SPM,
                            Status = GetOnlineStatus(Pid)
                        });
                    }

                    // Get a list of our online servers
                    if (GamespyEmulator.IsRunning)
                    {
                        // Get our servers next
                        foreach (GameServer server in MasterServer.Servers.Values)
                        {
                            // Add info if its online
                            Model.Servers.Add(new Server()
                            {
                                AddressInfo = new IPEndPoint(server.AddressInfo.Address, server.hostport),
                                Name = server.hostname,
                                ImagePath = base.CorrectUrls(server.bf2_communitylogo_url, Model),
                                MapName = server.mapname,
                                MaxPlayers = server.maxplayers,
                                PlayerCount = server.numplayers,
                                MapSize = server.bf2_mapsize,
                                GameType = BF2Server.GetGametypeString(server.gametype)
                            });
                        }
                    }

                    // Send response
                    base.SendTemplateResponse("index", typeof(IndexModel), Model);
                }
            }
        }
        public override void HandleRequest(MvcRoute Route)
        {
            // Get our POST'ed parameters
            Dictionary<string, string> postParams = Client.Request.GetFormUrlEncodedPostVars();

            // If we have a search value, run it
            if (postParams.ContainsKey("searchvalue"))
            {
                // NOTE: The HttpServer will handle the DbConnectException
                using (StatsDatabase Database = new StatsDatabase())
                {
                    Model.SearchValue = postParams["searchvalue"].Replace("+", " ");
                    List<Dictionary<string, object>> Rows;

                    // Do processing
                    if (Validator.IsNumeric(Model.SearchValue))
                    {
                        if (Validator.IsValidPID(Model.SearchValue))
                        {
                            // If player PID exists, redirect there
                            bool exists = Database.ExecuteScalar<bool>("SELECT COUNT(id) FROM player WHERE id=@P0", Model.SearchValue);
                            if (exists)
                            {
                                Client.Response.Redirect("/bf2stats/player/" + Model.SearchValue);
                                return;
                            }
                        }

                        Rows = Database.Query(
                            "SELECT id, name, score, time, country, rank, lastonline, kills, deaths FROM player WHERE id LIKE @P0 LIMIT 50",
                            "%" + Model.SearchValue + "%"
                        );
                    }
                    else
                    {
                        // Check to see if player with this name exists
                        Rows = Database.Query("SELECT id FROM player WHERE name=@P0 LIMIT 1", Model.SearchValue);
                        if (Rows.Count > 0)
                        {
                            Client.Response.Redirect("/bf2stats/player/" + Rows[0]["id"]);
                            return;
                        }

                        Rows = Database.Query(
                            "SELECT id, name, score, time, country, rank, lastonline, kills, deaths FROM player WHERE name LIKE @P0 LIMIT 50",
                            Model.SearchValue
                        );
                    }

                    // Loop through each result, and process
                    foreach (Dictionary<string, object> Row in Rows)
                    {
                        // DO Kill Death Ratio
                        double Kills = Int32.Parse(Row["kills"].ToString());
                        double Deaths = Int32.Parse(Row["deaths"].ToString());
                        double Kdr = (Deaths > 0) ? Math.Round(Kills / Deaths, 3) : Kills;

                        // Get Score Per Min
                        double Score = Int32.Parse(Row["score"].ToString());
                        double Mins = Int32.Parse(Row["time"].ToString()) / 60;
                        double SPM = (Mins > 0) ? Math.Round(Score / Mins, 4) : Score;

                        // Add Result
                        Model.SearchResults.Add(new PlayerResult
                        {
                            Pid = Int32.Parse(Row["id"].ToString()),
                            Name = Row["name"].ToString(),
                            Score = (int)Score,
                            Rank = Int32.Parse(Row["rank"].ToString()),
                            TimePlayed = FormatTime(Int32.Parse(Row["time"].ToString())),
                            LastOnline = FormatDate(Int32.Parse(Row["lastonline"].ToString())),
                            Country = Row["country"].ToString().ToUpperInvariant(),
                            Kdr = Kdr,
                            Spm = SPM
                        });
                    }
                }
            }

            // Send response
            base.SendTemplateResponse("search", typeof(SearchModel), Model);
        }
Esempio n. 25
0
        /// <summary>
        /// Initializes a new Snapshot, with the specified Date it was Posted
        /// </summary>
        /// <param name="Snapshot">The snapshot source</param>
        public Snapshot(string Snapshot, IPAddress ServerIp = null)
        {
            // Set some internal variables
            this.ServerIp = ServerIp ?? IPAddress.Loopback;
            this.Players = new List<Player>();
            this.DataString = Snapshot.Trim();
            string[] Data = DataString.Split('\\');
            Snapshot = null;

            // Check for invalid snapshot string. All snapshots have at least 36 data pairs,
            // and has an Even number of data sectors.
            if (Data.Length < 36 || Data.Length % 2 != 0)
                throw new InvalidDataException("Snapshot does not contain at least 36 elements, or contains an odd number of elements");

            // Assign server name and prefix
            this.ServerPrefix = Data[0];
            this.ServerName = Data[1];

            // Determine if we are central update. the "cdb_update" variable must be the LAST sector in snapshot
            int Mode;
            if (Data[Data.Length - 2] == "cdb_update" && Int32.TryParse(Data[Data.Length - 1], out Mode) && Mode.InRange(1, 2))
            {
                this.SnapshotMode = (Mode == 2) ? SnapshotMode.Minimal : SnapshotMode.FullSync;
            }

            // Setup our data dictionary's. We use NiceDictionary so we can easily determine missing keys in the log file
            NiceDictionary<string, string> StandardData = new NiceDictionary<string, string>(16);
            NiceDictionary<string, string> PlayerData = new NiceDictionary<string, string>();
            Dictionary<int, int> KillData = new Dictionary<int, int>();

            // Wrap parsing Key/Value snapshot data in a try block!
            try
            {
                // Convert our standard data into key => value pairs
                for (int i = 2; i < Data.Length; i += 2)
                {
                    // Format: "DataKey_PlayerIndex". PlayerIndex is NOT the Player Id
                    string[] Parts = Data[i].Split('_');
                    if (Parts.Length == 1)
                    {
                        // Add to the Standard keys
                        StandardData.Add(Data[i], Data[i + 1]);

                        // Are we at the End of File? If so stop here
                        if (Parts[0] == "EOF")
                        {
                            // Make sure to save that last players stats!!
                            if (PlayerData.Count != 0)
                            {
                                AddPlayer(new Player(PlayerData, KillData));
                                PlayerData = null;
                                KillData = null;
                            }
                            break;
                        }
                    }

                    // If the item key is "pID", then we have a new player record
                    else if (Parts[0] == "pID")
                    {
                        // If we have data, complete this player and start anew
                        if (PlayerData.Count != 0)
                        {
                            AddPlayer(new Player(PlayerData, KillData));
                            PlayerData.Clear();
                            KillData.Clear();
                        }

                        // Add new PID
                        PlayerData.Add(Parts[0], Data[i + 1]);
                    }
                    else if (Parts[0] == "mvks") // Skip mvks... kill data only needs processed once (mvns)
                        continue;
                    else if (Parts[0] == "mvns") // Player kill data
                        KillData.Add(Int32.Parse(Data[i + 1]), Int32.Parse(Data[i + 3]));
                    else
                        PlayerData.Add(Parts[0], Data[i + 1]);
                }
            }
            catch (Exception e)
            {
                throw new InvalidDataException("Error assigning Key => value pairs. See InnerException", e);
            }

            // Make sure we have a completed snapshot
            if (!StandardData.ContainsKey("EOF"))
                throw new InvalidDataException("No End of File element was found, Snapshot assumed to be incomplete.");

            // Try and set internal GameResult variables
            try
            {
                // Server data
                this.ServerPort = Int32.Parse(StandardData["gameport"]);
                this.QueryPort = Int32.Parse(StandardData["queryport"]);

                // Map Data
                this.MapName = StandardData["mapname"];
                this.MapId = Int32.Parse(StandardData["mapid"]);
                this.RoundStartTime = (int)Convert.ToDouble(StandardData["mapstart"], CultureInfo.InvariantCulture.NumberFormat);
                this.RoundEndTime = (int)Convert.ToDouble(StandardData["mapend"], CultureInfo.InvariantCulture.NumberFormat);

                // Misc Data
                this.GameMode = Int32.Parse(StandardData["gm"]);
                this.Mod = StandardData["v"]; // bf2 mod replaced the version key, since we dont care the version anyways
                this.PlayersConnected = Int32.Parse(StandardData["pc"]);

                // Army Data... There is no RWA key if there was no winner...
                this.WinningTeam = Int32.Parse(StandardData["win"]); // Temp
                this.WinningArmyId = (StandardData.ContainsKey("rwa")) ? Int32.Parse(StandardData["rwa"]) : -1;
                this.Team1ArmyId = Int32.Parse(StandardData["ra1"]);
                this.Team1Tickets = Int32.Parse(StandardData["rs1"]);
                this.Team2ArmyId = Int32.Parse(StandardData["ra2"]);
                this.Team2Tickets = Int32.Parse(StandardData["rs2"]);
            }
            catch (Exception e)
            {
                throw new InvalidDataException("Error assigning GameResult variables. See InnerException", e);
            }

            // Wrap this in a try-catch block, because we want to be able to view GameResult
            // data, even if the database is offline
            try
            {
                // Dispose when done!
                using (StatsDatabase Driver = new StatsDatabase())
                {
                    // Check for custom map, with no ID (Not defined in Constants.py)
                    if (this.MapId == 99)
                    {
                        // Check for existing map data
                        var Rows = Driver.Query("SELECT id FROM mapinfo WHERE name=@P0", this.MapName);
                        if (Rows.Count == 0)
                        {
                            // Create new MapId. Id's 700 - 1000 are reserved for unknown maps in the Constants.py file
                            // There should never be more then 300 unknown map id's, considering 1001 is the start of KNOWN
                            // Custom mod map id's. If we are at 1000 now, then we are in trouble :S
                            this.MapId = Driver.ExecuteScalar<int>("SELECT COALESCE(MAX(id), 699) FROM mapinfo WHERE id BETWEEN 700 AND 999") + 1;
                            if (this.MapId == 1000)
                                throw new Exception("Maximum unknown custom mapid has been reached. Please add this map's mapid to the Constants.py");

                            // Insert map data, so we dont lose this mapid we generated
                            Driver.Execute("INSERT INTO mapinfo(id, name, custom) VALUES (@P0, @P1, @P2)", this.MapId, this.MapName, 1);
                        }
                        else
                            this.MapId = Int32.Parse(Rows[0]["id"].ToString());
                    }

                    // Set whether or not this data is already been processed. The OR condition is because i goofed in early updates
                    // and set the timestamp to the RoundStart instead of the RoundEnd like i should have
                    this.IsProcessed = Driver.ExecuteScalar<int>(
                        "SELECT COUNT(*) FROM round_history WHERE mapid=@P0 AND time=@P1 AND (timestamp=@P2 OR timestamp=@P3)",
                        this.MapId, this.RoundTime.Seconds, this.RoundEndTime, this.RoundStartTime
                    ) > 0;
                }
            }
            catch(DbConnectException)
            {
                this.IsProcessed = false;
            }

            // Indicate whether we are a custom map
            this.IsCustomMap = (this.MapId >= 700 || this.MapId == 99);
        }