/// <summary> /// Adds a server's posted snapshot into the Snapshot Processing Queue, which /// will process the snapshot as soon as possible. This method is Non-Blocking. /// </summary> /// <remarks> /// Any errors that occur during the actual import of the data will be /// logged inside the StatsDebug log /// </remarks> /// <param name="Data">The snapshot data provided by the server.</param> /// <param name="ServerAddress">The IP address of the server.</param> /// <exception cref="UnauthorizedAccessException"> /// Thrown if the Server IP is not authorized to post game data to this server /// </exception> /// <exception cref="InvalidDataException"> /// Thrown if the provided Snapshot data is not valid, and cannot be processed /// </exception> public static void QueueServerSnapshot(string Data, IPAddress ServerAddress) { // Make sure the server is authorized if (!IsAuthorizedGameServer(ServerAddress)) throw new UnauthorizedAccessException("Un-Authorised Gameserver (Ip: " + ServerAddress + ")"); // Create the Snapshot Object Snapshot Snap = new Snapshot(Data, ServerAddress); // Update this server in the Database using (StatsDatabase Database = new StatsDatabase()) { // Try and grab the ID of this server int id = Database.ExecuteScalar<int>( "SELECT COALESCE(id, -1), COUNT(id) FROM servers WHERE ip=@P0 AND port=@P1", ServerAddress, Snap.ServerPort ); // New server? if (id < 0) { InsertQueryBuilder builder = new InsertQueryBuilder(Database); builder.SetTable("servers"); builder.SetField("ip", ServerAddress); builder.SetField("port", Snap.ServerPort); builder.SetField("prefix", Snap.ServerPrefix); builder.SetField("name", Snap.ServerName); builder.SetField("queryport", Snap.QueryPort); builder.SetField("lastupdate", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")); builder.Execute(); } else // existing { UpdateQueryBuilder builder = new UpdateQueryBuilder(Database); builder.SetTable("servers"); builder.SetField("prefix", Snap.ServerPrefix); builder.SetField("name", Snap.ServerName); builder.SetField("queryport", Snap.QueryPort); builder.SetField("lastupdate", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")); builder.AddWhere("id", Comparison.Equals, id); builder.Execute(); } } // Add snapshot to Queue SnapshotQueue.Enqueue(Snap); }
/// <summary> /// Updates an Account's information by ID /// </summary> /// <param name="Id">The Current Account ID</param> /// <param name="NewPid">New Account ID</param> /// <param name="NewNick">New Account Name</param> /// <param name="NewPassword">New Account Password, UN HASHED. Leave empty to not set a new password</param> /// <param name="NewEmail">New Account Email Address</param> public void UpdateUser(int Id, int NewPid, string NewNick, string NewPassword, string NewEmail) { UpdateQueryBuilder Query = new UpdateQueryBuilder("accounts", this); Query.SetField("id", NewPid); Query.SetField("name", NewNick); Query.SetField("email", NewEmail.ToLowerInvariant()); Query.AddWhere("id", Comparison.Equals, Id); // Set new password if not empty if (!String.IsNullOrWhiteSpace(NewPassword)) Query.SetField("password", NewPassword.GetMD5Hash(false)); Query.Execute(); }
/// <summary> /// Processes the snapshot data, inserted and updating player data. /// </summary> /// <exception cref="InvalidDataException">Thrown if the snapshot data is invalid</exception> public void Process() { // Make sure we are valid, or throw exception! if (!IsValidSnapshot) throw new InvalidDataException("Invalid Snapshot data!"); // Begin Logging Log(String.Format("Begin Processing ({0})...", MapName), LogLevel.Notice); if (IsCustomMap) Log(String.Format("Custom Map ({0})...", MapId), LogLevel.Notice); else Log(String.Format("Standard Map ({0})...", MapId), LogLevel.Notice); Log("Found " + PlayerData.Count + " Player(s)...", LogLevel.Notice); // Make sure we meet the minimum player requirement if (PlayerData.Count < MainForm.Config.ASP_MinRoundPlayers) { Log("Minimum round Player count does not meet the ASP requirement... Aborting", LogLevel.Warning); return; } // Start a timer! Stopwatch Clock = new Stopwatch(); Clock.Start(); // Setup some variables List<Dictionary<string, object>> Rows; InsertQueryBuilder InsertQuery; UpdateQueryBuilder UpdateQuery; WhereClause Where; // Temporary Map Data (For Round history and Map info tables) int MapScore = 0; int MapKills = 0; int MapDeaths = 0; int Team1Players = 0; int Team2Players = 0; int Team1PlayersEnd = 0; int Team2PlayersEnd = 0; // MySQL could throw a packet size error here, so we need will increase it! if (Driver.DatabaseEngine == DatabaseEngine.Mysql) Driver.Execute("SET GLOBAL max_allowed_packet=51200"); // Begin Transaction 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 int PlayerPosition = 0; foreach (Dictionary<string, string> Player in PlayerData) { // Parse some player data int Pid = Int32.Parse(Player["pID"]); int Time = Int32.Parse(Player["ctime"]); int SqlTime = Int32.Parse(Player["tsl"]); int SqmTime = Int32.Parse(Player["tsm"]); int LwTime = Int32.Parse(Player["tlw"]); int Army = Int32.Parse(Player["a"]); int RoundScore = Int32.Parse(Player["rs"]); int CurRank = Int32.Parse(Player["rank"]); int Kills = Int32.Parse(Player["kills"]); int Deaths = Int32.Parse(Player["deaths"]); int Ks = Int32.Parse(Player["ks"]); int Ds = Int32.Parse(Player["ds"]); bool IsAi = (Int32.Parse(Player["ai"]) != 0); bool CompletedRound = (Int32.Parse(Player["c"]) == 1); bool OnWinningTeam = (Int32.Parse(Player["t"]) == WinningTeam); IPAddress PlayerIp = IPAddress.Loopback; // Player meets min round time or are we ignoring AI? if ((Time < MainForm.Config.ASP_MinRoundTime) || (MainForm.Config.ASP_IgnoreAI && IsAi)) continue; // Add map data MapScore += RoundScore; MapKills += Kills; MapDeaths += Deaths; // Fix N/A Ip address if (Player["ip"] == "N/A") Player["ip"] = "127.0.0.1"; // Sometimes Squad times are negative.. idk why, but we need to fix that here if (SqlTime < 0) SqlTime = 0; if (SqmTime < 0) SqmTime = 0; if (LwTime < 0) LwTime = 0; // Log Log(String.Format("Processing Player ({0})", Pid), LogLevel.Notice); // Fetch the player string Query; Rows = Driver.Query("SELECT COUNT(id) AS count FROM player WHERE id=@P0", Pid); if (int.Parse(Rows[0]["count"].ToString()) == 0) { // === New Player === // // Log Log(String.Format("Adding NEW Player ({0})", Pid), LogLevel.Notice); // Get playres country code IPAddress.TryParse(Player["ip"], out PlayerIp); string CC = GetCountryCode(PlayerIp); // Build insert data InsertQuery = new InsertQueryBuilder("player", Driver); InsertQuery.SetField("id", Pid); InsertQuery.SetField("name", Player["name"]); InsertQuery.SetField("country", CC); InsertQuery.SetField("time", Time); InsertQuery.SetField("rounds", Player["c"]); InsertQuery.SetField("ip", Player["ip"]); InsertQuery.SetField("score", Player["rs"]); InsertQuery.SetField("cmdscore", Player["cs"]); InsertQuery.SetField("skillscore", Player["ss"]); InsertQuery.SetField("teamscore", Player["ts"]); InsertQuery.SetField("kills", Player["kills"]); InsertQuery.SetField("deaths", Player["deaths"]); InsertQuery.SetField("captures", Player["cpc"]); InsertQuery.SetField("captureassists", Player["cpa"]); InsertQuery.SetField("defends", Player["cpd"]); InsertQuery.SetField("damageassists", Player["ka"]); InsertQuery.SetField("heals", Player["he"]); InsertQuery.SetField("revives", Player["rev"]); InsertQuery.SetField("ammos", Player["rsp"]); InsertQuery.SetField("repairs", Player["rep"]); InsertQuery.SetField("targetassists", Player["tre"]); InsertQuery.SetField("driverspecials", Player["drs"]); InsertQuery.SetField("teamkills", Player["tmkl"]); InsertQuery.SetField("teamdamage", Player["tmdg"]); InsertQuery.SetField("teamvehicledamage", Player["tmvd"]); InsertQuery.SetField("suicides", Player["su"]); InsertQuery.SetField("killstreak", Player["ks"]); InsertQuery.SetField("deathstreak", Player["ds"]); InsertQuery.SetField("rank", Player["rank"]); InsertQuery.SetField("banned", Player["ban"]); InsertQuery.SetField("kicked", Player["kck"]); InsertQuery.SetField("cmdtime", Player["tco"]); InsertQuery.SetField("sqltime", SqlTime); InsertQuery.SetField("sqmtime", SqmTime); InsertQuery.SetField("lwtime", LwTime); InsertQuery.SetField("wins", OnWinningTeam); InsertQuery.SetField("losses", !OnWinningTeam); InsertQuery.SetField("availunlocks", 0); InsertQuery.SetField("usedunlocks", 0); InsertQuery.SetField("joined", TimeStamp); InsertQuery.SetField("rndscore", Player["rs"]); InsertQuery.SetField("lastonline", MapEnd); InsertQuery.SetField("mode0", ((GameMode == 0) ? 1 : 0)); InsertQuery.SetField("mode1", ((GameMode == 1) ? 1 : 0)); InsertQuery.SetField("mode2", ((GameMode == 2) ? 1 : 0)); InsertQuery.SetField("isbot", Player["ai"]); // Insert Player Data InsertQuery.Execute(); // Create Player Unlock Data Query = "INSERT INTO unlocks VALUES "; for (int i = 11; i < 100; i += 11) Query += String.Format("({0}, {1}, 'n'), ", Pid, i); for (int i = 111; i < 556; i += 111) Query += String.Format("({0}, {1}, 'n'), ", Pid, i); Driver.Execute(Query.TrimEnd(new char[] { ',', ' ' })); } else { // Existing Player // Log Log(String.Format("Updating EXISTING Player ({0})", Pid), LogLevel.Notice); // Fetch Player Rows = Driver.Query("SELECT ip, country, rank, killstreak, deathstreak, rndscore FROM player WHERE id=@P0", Pid); Dictionary<string, object> DataRow = Rows[0]; // Setup vars string CC = DataRow["country"].ToString(); int DbRank = Int32.Parse(DataRow["rank"].ToString()); // Update country if the ip has changed IPAddress.TryParse(Player["ip"], out PlayerIp); if (DataRow["ip"].ToString() != Player["ip"]) CC = GetCountryCode(PlayerIp); // Verify/Correct Rank if (MainForm.Config.ASP_StatsRankCheck) { // Fail-safe in-case rank data was not obtained and reset to '0' in-game. if (DbRank > CurRank) { Player["rank"] = DbRank.ToString(); DebugLog.Write("Rank Correction ({0}), Using database rank ({1})", Pid, DbRank); } } // Calcuate best killstreak/deathstreak int KillStreak = Int32.Parse(DataRow["killstreak"].ToString()); int DeathStreak = Int32.Parse(DataRow["deathstreak"].ToString()); if (Ks > KillStreak) KillStreak = Ks; if (Ds > DeathStreak) DeathStreak = Ds; // Calculate Best Round Score int Brs = Int32.Parse(DataRow["rndscore"].ToString()); if (RoundScore > Brs) Brs = RoundScore; // Calculate rank change int chng = 0; int decr = 0; if (DbRank != CurRank) { if (CurRank > DbRank) chng = 1; else decr = 1; } // Update Player Data UpdateQuery = new UpdateQueryBuilder("player", Driver); UpdateQuery.SetField("country", CC); UpdateQuery.SetField("time", Time, ValueMode.Add); UpdateQuery.SetField("rounds", Player["c"], ValueMode.Add); UpdateQuery.SetField("ip", Player["ip"]); UpdateQuery.SetField("score", Player["rs"], ValueMode.Add); UpdateQuery.SetField("cmdscore", Player["cs"], ValueMode.Add); UpdateQuery.SetField("skillscore", Player["ss"], ValueMode.Add); UpdateQuery.SetField("teamscore", Player["ts"], ValueMode.Add); UpdateQuery.SetField("kills", Player["kills"], ValueMode.Add); UpdateQuery.SetField("deaths", Player["deaths"], ValueMode.Add); UpdateQuery.SetField("captures", Player["cpc"], ValueMode.Add); UpdateQuery.SetField("captureassists", Player["cpa"], ValueMode.Add); UpdateQuery.SetField("defends", Player["cpd"], ValueMode.Add); UpdateQuery.SetField("damageassists", Player["ks"], ValueMode.Add); UpdateQuery.SetField("heals", Player["he"], ValueMode.Add); UpdateQuery.SetField("revives", Player["rev"], ValueMode.Add); UpdateQuery.SetField("ammos", Player["rsp"], ValueMode.Add); UpdateQuery.SetField("repairs", Player["rep"], ValueMode.Add); UpdateQuery.SetField("targetassists", Player["tre"], ValueMode.Add); UpdateQuery.SetField("driverspecials", Player["drs"], ValueMode.Add); UpdateQuery.SetField("teamkills", Player["tmkl"], ValueMode.Add); UpdateQuery.SetField("teamdamage", Player["tmdg"], ValueMode.Add); UpdateQuery.SetField("teamvehicledamage", Player["tmvd"], ValueMode.Add); UpdateQuery.SetField("suicides", Player["su"], ValueMode.Add); UpdateQuery.SetField("Killstreak", KillStreak, ValueMode.Set); UpdateQuery.SetField("deathstreak", DeathStreak, ValueMode.Set); UpdateQuery.SetField("rank", CurRank, ValueMode.Set); UpdateQuery.SetField("banned", Player["ban"], ValueMode.Add); UpdateQuery.SetField("kicked", Player["kck"], ValueMode.Add); UpdateQuery.SetField("cmdtime", Player["tco"], ValueMode.Add); UpdateQuery.SetField("sqltime", SqlTime, ValueMode.Add); UpdateQuery.SetField("sqmtime", SqmTime, ValueMode.Add); UpdateQuery.SetField("lwtime", LwTime, ValueMode.Add); UpdateQuery.SetField("wins", ((OnWinningTeam) ? 1 : 0), ValueMode.Add); UpdateQuery.SetField("losses", ((!OnWinningTeam) ? 1 : 0), ValueMode.Add); UpdateQuery.SetField("rndscore", Brs, ValueMode.Set); UpdateQuery.SetField("lastonline", TimeStamp, ValueMode.Set); UpdateQuery.SetField("mode0", ((GameMode == 0) ? 1 : 0), ValueMode.Add); UpdateQuery.SetField("mode1", ((GameMode == 1) ? 1 : 0), ValueMode.Add); UpdateQuery.SetField("mode2", ((GameMode == 2) ? 1 : 0), ValueMode.Add); UpdateQuery.SetField("chng", chng, ValueMode.Set); UpdateQuery.SetField("decr", decr, ValueMode.Set); UpdateQuery.SetField("isbot", Player["ai"], ValueMode.Set); UpdateQuery.AddWhere("id", Comparison.Equals, Pid); UpdateQuery.Execute(); } // ******************************** // Insert Player history. // ******************************** Driver.Execute( "INSERT INTO player_history VALUES(@P0, @P1, @P2, @P3, @P4, @P5, @P6, @P7, @P8, @P9)", Pid, TimeStamp, Time, RoundScore, Player["cs"], Player["ss"], Player["ts"], Kills, Deaths, CurRank ); // ******************************** // Process Player Army Data // ******************************** Log(String.Format("Processing Army Data ({0})", Pid), LogLevel.Notice); // DO team counts if(Army == Team1Army) { Team1Players++; if (CompletedRound) // Completed round? Team1PlayersEnd++; } else { Team2Players++; if (CompletedRound) // Completed round? Team2PlayersEnd++; } // Update player army times Rows = Driver.Query("SELECT * FROM army WHERE id=" + Pid); if (Rows.Count == 0) { InsertQuery = new InsertQueryBuilder("army", Driver); InsertQuery.SetField("id", Pid); InsertQuery.SetField("time0", Player["ta0"]); InsertQuery.SetField("time1", Player["ta1"]); InsertQuery.SetField("time2", Player["ta2"]); InsertQuery.SetField("time3", Player["ta3"]); InsertQuery.SetField("time4", Player["ta4"]); InsertQuery.SetField("time5", Player["ta5"]); InsertQuery.SetField("time6", Player["ta6"]); InsertQuery.SetField("time7", Player["ta7"]); InsertQuery.SetField("time8", Player["ta8"]); InsertQuery.SetField("time9", Player["ta9"]); InsertQuery.SetField("time10", Player["ta10"]); InsertQuery.SetField("time11", Player["ta11"]); InsertQuery.SetField("time12", Player["ta12"]); InsertQuery.SetField("time13", Player["ta13"]); // Make sure we arent playing an unsupported army if (Army < 14) { InsertQuery.SetField("win" + Army, ((OnWinningTeam) ? 1 : 0)); InsertQuery.SetField("loss" + Army, ((!OnWinningTeam) ? 1 : 0)); InsertQuery.SetField("score" + Army, Player["rs"]); InsertQuery.SetField("best" + Army, Player["rs"]); InsertQuery.SetField("worst" + Army, Player["rs"]); } InsertQuery.Execute(); } else { UpdateQuery = new UpdateQueryBuilder("army", Driver); UpdateQuery.AddWhere("id", Comparison.Equals, Pid); UpdateQuery.SetField("time0", Player["ta0"], ValueMode.Add); UpdateQuery.SetField("time1", Player["ta1"], ValueMode.Add); UpdateQuery.SetField("time2", Player["ta2"], ValueMode.Add); UpdateQuery.SetField("time3", Player["ta3"], ValueMode.Add); UpdateQuery.SetField("time4", Player["ta4"], ValueMode.Add); UpdateQuery.SetField("time5", Player["ta5"], ValueMode.Add); UpdateQuery.SetField("time6", Player["ta6"], ValueMode.Add); UpdateQuery.SetField("time7", Player["ta7"], ValueMode.Add); UpdateQuery.SetField("time8", Player["ta8"], ValueMode.Add); UpdateQuery.SetField("time9", Player["ta9"], ValueMode.Add); UpdateQuery.SetField("time10", Player["ta10"], ValueMode.Add); UpdateQuery.SetField("time11", Player["ta11"], ValueMode.Add); UpdateQuery.SetField("time12", Player["ta12"], ValueMode.Add); UpdateQuery.SetField("time13", Player["ta13"], ValueMode.Add); // Prevent database errors with custom army IDs if (Army < 14) { string Best = (Int32.Parse(Rows[0]["best" + Army].ToString()) > RoundScore) ? Rows[0]["best" + Army].ToString() : Player["rs"]; string Worst = (Int32.Parse(Rows[0]["worst" + Army].ToString()) > RoundScore) ? Rows[0]["worst" + Army].ToString() : Player["rs"]; UpdateQuery.SetField("win" + Army, OnWinningTeam, ValueMode.Add); UpdateQuery.SetField("loss" + Army, !OnWinningTeam, ValueMode.Add); UpdateQuery.SetField("score" + Army, Player["rs"], ValueMode.Add); UpdateQuery.SetField("best" + Army, Best, ValueMode.Set); UpdateQuery.SetField("worst" + Army, Worst, ValueMode.Set); } UpdateQuery.Execute(); } // ******************************** // Process Player Kills // ******************************** Log(String.Format("Processing Kills Data ({0})", Pid), LogLevel.Notice); foreach (KeyValuePair<string, string> Kill in KillData[PlayerPosition]) { string Victim = Kill.Key; int KillCount = Int32.Parse(Kill.Value); Rows = Driver.Query("SELECT count FROM kills WHERE attacker=@P0 AND victim=@P1", Pid, Victim); if (Rows.Count == 0) { InsertQuery = new InsertQueryBuilder("kills", Driver); InsertQuery.SetField("attacker", Pid); InsertQuery.SetField("victim", Victim); InsertQuery.SetField("count", KillCount); InsertQuery.Execute(); } else { UpdateQuery = new UpdateQueryBuilder("kills", Driver); UpdateQuery.SetField("count", KillCount, ValueMode.Add); Where = UpdateQuery.AddWhere("attacker", Comparison.Equals, Pid); Where.AddClause(LogicOperator.And, "victim", Comparison.Equals, Victim); UpdateQuery.Execute(); } } // ******************************** // Process Player Kit Data // ******************************** Log(String.Format("Processing Kit Data ({0})", Pid), LogLevel.Notice); Rows = Driver.Query("SELECT time0 FROM kits WHERE id=" + Pid); if (Rows.Count == 0) { InsertQuery = new InsertQueryBuilder("kits", Driver); InsertQuery.SetField("id", Pid); for (int i = 0; i < 7; i++) { InsertQuery.SetField("time" + i, Player["tk" + i]); InsertQuery.SetField("kills" + i, Player["kk" + i]); InsertQuery.SetField("deaths" + i, Player["dk" + i]); } InsertQuery.Execute(); } else { UpdateQuery = new UpdateQueryBuilder("kits", Driver); UpdateQuery.AddWhere("id", Comparison.Equals, Pid); for (int i = 0; i < 7; i++) { UpdateQuery.SetField("time" + i, Player["tk" + i], ValueMode.Add); UpdateQuery.SetField("kills" + i, Player["kk" + i], ValueMode.Add); UpdateQuery.SetField("deaths" + i, Player["dk" + i], ValueMode.Add); } UpdateQuery.Execute(); } // ******************************** // Process Player Vehicle Data // ******************************** Log(String.Format("Processing Vehicle Data ({0})", Pid), LogLevel.Notice); Rows = Driver.Query("SELECT time0 FROM vehicles WHERE id=" + Pid); if (Rows.Count == 0) { InsertQuery = new InsertQueryBuilder("vehicles", Driver); InsertQuery.SetField("id", Pid); for (int i = 0; i < 7; i++) { InsertQuery.SetField("time" + i, Player["tv" + i]); InsertQuery.SetField("kills" + i, Player["kv" + i]); InsertQuery.SetField("deaths" + i, Player["bv" + i]); InsertQuery.SetField("rk" + i, Player["kvr" + i]); } InsertQuery.SetField("timepara", Player["tvp"]); InsertQuery.Execute(); } else { UpdateQuery = new UpdateQueryBuilder("vehicles", Driver); UpdateQuery.AddWhere("id", Comparison.Equals, Pid); for (int i = 0; i < 7; i++) { UpdateQuery.SetField("time" + i, Player["tv" + i], ValueMode.Add); UpdateQuery.SetField("kills" + i, Player["kv" + i], ValueMode.Add); UpdateQuery.SetField("deaths" + i, Player["bv" + i], ValueMode.Add); UpdateQuery.SetField("rk" + i, Player["kvr" + i], ValueMode.Add); } UpdateQuery.SetField("timepara", Player["tvp"], ValueMode.Add); UpdateQuery.Execute(); } // ******************************** // Process Player Weapon Data // ******************************** Log(String.Format("Processing Weapon Data ({0})", Pid), LogLevel.Notice); Rows = Driver.Query("SELECT time0 FROM weapons WHERE id=" + Pid); if (Rows.Count == 0) { // Prepare Query InsertQuery = new InsertQueryBuilder("weapons", Driver); InsertQuery.SetField("id", Pid); // Basic Weapon Data for (int i = 0; i < 9; i++) { InsertQuery.SetField("time" + i, Player["tw" + i]); InsertQuery.SetField("kills" + i, Player["kw" + i]); InsertQuery.SetField("deaths" + i, Player["bw" + i]); InsertQuery.SetField("fired" + i, Player["sw" + i]); InsertQuery.SetField("hit" + i, Player["hw" + i]); } // Knife Data InsertQuery.SetField("knifetime", Player["te0"]); InsertQuery.SetField("knifekills", Player["ke0"]); InsertQuery.SetField("knifedeaths", Player["be0"]); InsertQuery.SetField("knifefired", Player["se0"]); InsertQuery.SetField("knifehit", Player["he0"]); // C4 Data InsertQuery.SetField("c4time", Player["te1"]); InsertQuery.SetField("c4kills", Player["ke1"]); InsertQuery.SetField("c4deaths", Player["be1"]); InsertQuery.SetField("c4fired", Player["se1"]); InsertQuery.SetField("c4hit", Player["he1"]); // Handgrenade InsertQuery.SetField("handgrenadetime", Player["te3"]); InsertQuery.SetField("handgrenadekills", Player["ke3"]); InsertQuery.SetField("handgrenadedeaths", Player["be3"]); InsertQuery.SetField("handgrenadefired", Player["se3"]); InsertQuery.SetField("handgrenadehit", Player["he3"]); // Claymore InsertQuery.SetField("claymoretime", Player["te2"]); InsertQuery.SetField("claymorekills", Player["ke2"]); InsertQuery.SetField("claymoredeaths", Player["be2"]); InsertQuery.SetField("claymorefired", Player["se2"]); InsertQuery.SetField("claymorehit", Player["he2"]); // Shockpad InsertQuery.SetField("shockpadtime", Player["te4"]); InsertQuery.SetField("shockpadkills", Player["ke4"]); InsertQuery.SetField("shockpaddeaths", Player["be4"]); InsertQuery.SetField("shockpadfired", Player["se4"]); InsertQuery.SetField("shockpadhit", Player["he4"]); // At Mine InsertQuery.SetField("atminetime", Player["te5"]); InsertQuery.SetField("atminekills", Player["ke5"]); InsertQuery.SetField("atminedeaths", Player["be5"]); InsertQuery.SetField("atminefired", Player["se5"]); InsertQuery.SetField("atminehit", Player["he5"]); // Tactical InsertQuery.SetField("tacticaltime", Player["te6"]); InsertQuery.SetField("tacticaldeployed", Player["de6"]); // Grappling Hook InsertQuery.SetField("grapplinghooktime", Player["te7"]); InsertQuery.SetField("grapplinghookdeployed", Player["de7"]); InsertQuery.SetField("grapplinghookdeaths", Player["be9"]); // Zipline InsertQuery.SetField("ziplinetime", Player["te8"]); InsertQuery.SetField("ziplinedeployed", Player["de8"]); InsertQuery.SetField("ziplinedeaths", Player["be8"]); // Do Query InsertQuery.Execute(); } else { // Prepare Query UpdateQuery = new UpdateQueryBuilder("weapons", Driver); UpdateQuery.AddWhere("id", Comparison.Equals, Pid); // Basic Weapon Data for (int i = 0; i < 9; i++) { UpdateQuery.SetField("time" + i, Player["tw" + i], ValueMode.Add); UpdateQuery.SetField("kills" + i, Player["kw" + i], ValueMode.Add); UpdateQuery.SetField("deaths" + i, Player["bw" + i], ValueMode.Add); UpdateQuery.SetField("fired" + i, Player["sw" + i], ValueMode.Add); UpdateQuery.SetField("hit" + i, Player["hw" + i], ValueMode.Add); } // Knife Data UpdateQuery.SetField("knifetime", Player["te0"], ValueMode.Add); UpdateQuery.SetField("knifekills", Player["ke0"], ValueMode.Add); UpdateQuery.SetField("knifedeaths", Player["be0"], ValueMode.Add); UpdateQuery.SetField("knifefired", Player["se0"], ValueMode.Add); UpdateQuery.SetField("knifehit", Player["he0"], ValueMode.Add); // C4 Data UpdateQuery.SetField("c4time", Player["te1"], ValueMode.Add); UpdateQuery.SetField("c4kills", Player["ke1"], ValueMode.Add); UpdateQuery.SetField("c4deaths", Player["be1"], ValueMode.Add); UpdateQuery.SetField("c4fired", Player["se1"], ValueMode.Add); UpdateQuery.SetField("c4hit", Player["he1"], ValueMode.Add); // Handgrenade UpdateQuery.SetField("handgrenadetime", Player["te3"], ValueMode.Add); UpdateQuery.SetField("handgrenadekills", Player["ke3"], ValueMode.Add); UpdateQuery.SetField("handgrenadedeaths", Player["be3"], ValueMode.Add); UpdateQuery.SetField("handgrenadefired", Player["se3"], ValueMode.Add); UpdateQuery.SetField("handgrenadehit", Player["he3"], ValueMode.Add); // Claymore UpdateQuery.SetField("claymoretime", Player["te2"], ValueMode.Add); UpdateQuery.SetField("claymorekills", Player["ke2"], ValueMode.Add); UpdateQuery.SetField("claymoredeaths", Player["be2"], ValueMode.Add); UpdateQuery.SetField("claymorefired", Player["se2"], ValueMode.Add); UpdateQuery.SetField("claymorehit", Player["he2"], ValueMode.Add); // Shockpad UpdateQuery.SetField("shockpadtime", Player["te4"], ValueMode.Add); UpdateQuery.SetField("shockpadkills", Player["ke4"], ValueMode.Add); UpdateQuery.SetField("shockpaddeaths", Player["be4"], ValueMode.Add); UpdateQuery.SetField("shockpadfired", Player["se4"], ValueMode.Add); UpdateQuery.SetField("shockpadhit", Player["he4"], ValueMode.Add); // At Mine UpdateQuery.SetField("atminetime", Player["te5"], ValueMode.Add); UpdateQuery.SetField("atminekills", Player["ke5"], ValueMode.Add); UpdateQuery.SetField("atminedeaths", Player["be5"], ValueMode.Add); UpdateQuery.SetField("atminefired", Player["se5"], ValueMode.Add); UpdateQuery.SetField("atminehit", Player["he5"], ValueMode.Add); // Tactical UpdateQuery.SetField("tacticaltime", Player["te6"], ValueMode.Add); UpdateQuery.SetField("tacticaldeployed", Player["de6"], ValueMode.Add); // Grappling Hook UpdateQuery.SetField("grapplinghooktime", Player["te7"], ValueMode.Add); UpdateQuery.SetField("grapplinghookdeployed", Player["de7"], ValueMode.Add); UpdateQuery.SetField("grapplinghookdeaths", Player["be9"], ValueMode.Add); // Zipline UpdateQuery.SetField("ziplinetime", Player["te8"], ValueMode.Add); UpdateQuery.SetField("ziplinedeployed", Player["de8"], ValueMode.Add); UpdateQuery.SetField("ziplinedeaths", Player["be8"], ValueMode.Add); // Do Query UpdateQuery.Execute(); } // ******************************** // Process Player Map Data // ******************************** Log(String.Format("Processing Map Data ({0})", Pid), LogLevel.Notice); Rows = Driver.Query("SELECT best, worst FROM maps WHERE id=@P0 AND mapid=@P1", Pid, MapId); if (Rows.Count == 0) { // Prepare Query InsertQuery = new InsertQueryBuilder("maps", Driver); InsertQuery.SetField("id", Pid); InsertQuery.SetField("mapid", MapId); InsertQuery.SetField("time", Time); InsertQuery.SetField("win", ((OnWinningTeam) ? 1 : 0)); InsertQuery.SetField("loss", ((!OnWinningTeam) ? 1 : 0)); InsertQuery.SetField("best", RoundScore); InsertQuery.SetField("worst", RoundScore); InsertQuery.Execute(); } else { // Get best and worst round scores string Best = ((Int32.Parse(Rows[0]["best"].ToString()) > RoundScore) ? Rows[0]["best"].ToString() : RoundScore.ToString()); string Worst = ((Int32.Parse(Rows[0]["worst"].ToString()) > RoundScore) ? Rows[0]["worst"].ToString() : RoundScore.ToString()); // Prepare Query UpdateQuery = new UpdateQueryBuilder("maps", Driver); Where = UpdateQuery.AddWhere("id", Comparison.Equals, Pid); Where.AddClause(LogicOperator.And, "mapid", Comparison.Equals, MapId); UpdateQuery.SetField("time", Time, ValueMode.Add); UpdateQuery.SetField("win", ((OnWinningTeam) ? 1 : 0), ValueMode.Add); UpdateQuery.SetField("loss", ((!OnWinningTeam) ? 1 : 0), ValueMode.Add); UpdateQuery.SetField("best", Best, ValueMode.Add); UpdateQuery.SetField("worst", Worst, ValueMode.Add); UpdateQuery.Execute(); } // ******************************** // Process Player Awards Data // ******************************** Log(String.Format("Processing Award Data ({0})", Pid), LogLevel.Notice); // Do we require round completion for award processing? if (CompletedRound || !MainForm.Config.ASP_AwardsReqComplete) { // Get our list of awards we earned in the round Dictionary<int, int> Awards = GetRoundAwards(Pid, Player); foreach (KeyValuePair<int, int> Award in Awards) { int First = 0; int AwardId = Award.Key; int Level = Award.Value; // If isMedal if (AwardId > 2000000 && AwardId < 3000000) Query = String.Format("SELECT level FROM awards WHERE id={0} AND awd={1}", Pid, AwardId); else Query = String.Format("SELECT level FROM awards WHERE id={0} AND awd={1} AND level={2}", Pid, AwardId, Level); // Check for prior awarding of award Rows = Driver.Query(Query); if (Rows.Count == 0) { // Medals if (AwardId > 2000000 && AwardId < 3000000) First = TimeStamp; // Badges else if(AwardId < 2000000) { // Need to do extra work for Badges as more than one badge per round may have been awarded for (int j = 1; j < Level; j++) { Rows = Driver.Query("SELECT level FROM awards WHERE id=@P0 AND awd=@P1 AND level=@P2", Pid, AwardId, j); if (Rows.Count == 0) { // Prepare Query InsertQuery = new InsertQueryBuilder("awards", Driver); InsertQuery.SetField("id", Pid); InsertQuery.SetField("awd", AwardId); InsertQuery.SetField("level", j); InsertQuery.SetField("earned", (TimeStamp - 5) + j); InsertQuery.SetField("first", First); InsertQuery.Execute(); } } } // Add the players award InsertQuery = new InsertQueryBuilder("awards", Driver); InsertQuery.SetField("id", Pid); InsertQuery.SetField("awd", AwardId); InsertQuery.SetField("level", Level); InsertQuery.SetField("earned", TimeStamp); InsertQuery.SetField("first", First); InsertQuery.Execute(); } else { // Player has recived this award prior // // If award if a medal (Because ribbons and badges are only awarded once ever!) if (AwardId > 2000000 && AwardId < 3000000) { // Prepare Query UpdateQuery = new UpdateQueryBuilder("awards", Driver); Where = UpdateQuery.AddWhere("id", Comparison.Equals, Pid); Where.AddClause(LogicOperator.And, "awd", Comparison.Equals, AwardId); UpdateQuery.SetField("level", 1, ValueMode.Add); UpdateQuery.SetField("earned", TimeStamp, ValueMode.Set); UpdateQuery.Execute(); } } // Add best round count if player earned best round medal if (OnWinningTeam && AwardId == 2051907) { // Prepare Query UpdateQuery = new UpdateQueryBuilder("army", Driver); UpdateQuery.AddWhere("id", Comparison.Equals, Pid); UpdateQuery.SetField("brnd" + Army, 1, ValueMode.Add); UpdateQuery.Execute(); } } // End Foreach Award } // Increment player position PlayerPosition++; } // End Foreach Player // Commit the transaction try { Transaction.Commit(); } catch (Exception E) { try { Transaction.Rollback(); } catch { } // Log error Log("An error occured while commiting player changes: " + E.Message, LogLevel.Error); return; } } catch(Exception E) { Log("An error occured while updating player stats: " + E.Message, LogLevel.Error); Transaction.Rollback(); } // ******************************** // Process ServerInfo // ******************************** //Log("Processing Game Server", LogLevel.Notice); // ******************************** // Process MapInfo // ******************************** Log(String.Format("Processing Map Info ({0}:{1})", MapName, MapId), LogLevel.Notice); TimeSpan Timer = new TimeSpan(Convert.ToInt64(MapEnd - MapStart)); Rows = Driver.Query("SELECT COUNT(id) AS count FROM mapinfo WHERE id=" + MapId); if(Int32.Parse(Rows[0]["count"].ToString()) == 0) { // Prepare Query InsertQuery = new InsertQueryBuilder("mapinfo", Driver); InsertQuery.SetField("id", MapId); InsertQuery.SetField("name", MapName); InsertQuery.SetField("score", MapScore); InsertQuery.SetField("time", Timer.Seconds); InsertQuery.SetField("times", 1); InsertQuery.SetField("kills", MapKills); InsertQuery.SetField("deaths", MapDeaths); InsertQuery.SetField("custom", (IsCustomMap) ? 1 : 0); InsertQuery.Execute(); } else { UpdateQuery = new UpdateQueryBuilder("mapinfo", Driver); UpdateQuery.AddWhere("id", Comparison.Equals, MapId); UpdateQuery.SetField("score", MapScore, ValueMode.Add); UpdateQuery.SetField("time", Timer.Seconds, ValueMode.Add); UpdateQuery.SetField("times", 1, ValueMode.Add); UpdateQuery.SetField("kills", MapKills, ValueMode.Add); UpdateQuery.SetField("deaths", MapDeaths, ValueMode.Add); UpdateQuery.Execute(); } // ******************************** // Process RoundInfo // ******************************** Log("Processing Round Info", LogLevel.Notice); InsertQuery = new InsertQueryBuilder("round_history", Driver); InsertQuery.SetField("timestamp", MapStart); InsertQuery.SetField("mapid", MapId); InsertQuery.SetField("time", Timer.Seconds); InsertQuery.SetField("team1", Team1Army); InsertQuery.SetField("team2", Team2Army); InsertQuery.SetField("tickets1", Team1Tickets); InsertQuery.SetField("tickets2", Team2Tickets); InsertQuery.SetField("pids1", Team1Players); InsertQuery.SetField("pids1_end", Team1PlayersEnd); InsertQuery.SetField("pids2", Team2Players); InsertQuery.SetField("pids2_end", Team2PlayersEnd); InsertQuery.Execute(); // ******************************** // Process Smoc And General Ranks // ******************************** if (MainForm.Config.ASP_SmocCheck) SmocCheck(); if (MainForm.Config.ASP_GeneralCheck) GenCheck(); // Call our Finished Event Timer = new TimeSpan(Clock.ElapsedTicks); Log(String.Format("Snapshot ({0}) processed in {1} milliseconds", MapName, Timer.Milliseconds), LogLevel.Info); SnapshotProccessed(); }
/// <summary> /// Save Button Click Event /// </summary> private void SaveBtn_Click(object sender, EventArgs e) { try { using (StatsDatabase Driver = new StatsDatabase()) { bool Changes = false; UpdateQueryBuilder Query = new UpdateQueryBuilder("player", Driver); int Rank = Int32.Parse(Player["rank"].ToString()); // Update clantag if (Player["clantag"].ToString() != ClanTagBox.Text.Trim()) { Player["clantag"] = ClanTagBox.Text.Trim(); Query.SetField("clantag", ClanTagBox.Text.Trim()); Changes = true; } // Update Rank if (Rank != RankSelect.SelectedIndex) { if (Rank > RankSelect.SelectedIndex) { Query.SetField("decr", 1); Query.SetField("chng", 0); } else { Query.SetField("decr", 0); Query.SetField("chng", 1); } Player["rank"] = RankSelect.SelectedIndex; Query.SetField("rank", RankSelect.SelectedIndex); Changes = true; } // update perm ban status if (Int32.Parse(Player["permban"].ToString()) != PermBanSelect.SelectedIndex) { Player["permban"] = PermBanSelect.SelectedIndex; Query.SetField("permban", PermBanSelect.SelectedIndex); Changes = true; } // If no changes made, just return if (!Changes) { MessageBox.Show("Unable to save player because no changes were made.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } // Preform Query Query.AddWhere("id", Comparison.Equals, Pid); Query.Execute(); this.Close(); } } catch (DbConnectException Ex) { HttpServer.Stop(); ExceptionForm.ShowDbConnectError(Ex); return; } }
/// <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; } } }