/// <summary> /// Creates the connection to the database, and handles /// the excpetion (if any) that are thrown /// </summary> public void CheckConnection() { if(Driver == null || !Driver.IsConnected) { try { // First time connection if (Driver == null) { Driver = new DatabaseDriver( MainForm.Config.GamespyDBEngine, MainForm.Config.GamespyDBHost, MainForm.Config.GamespyDBPort, MainForm.Config.GamespyDBName, MainForm.Config.GamespyDBUser, MainForm.Config.GamespyDBPass ); // Create SQL tables on new SQLite DB's if (Driver.IsNewDatabase) { // Connect to DB Driver.Connect(); string SQL = Utils.GetResourceAsString("BF2Statistics.SQL.SQLite.Gamespy.sql"); Driver.Execute(SQL); return; } else { // Connect to DB Driver.Connect(); CheckDatabase(); return; } } // Connect to DB Driver.Connect(); } catch (Exception E) { string Message = "Database Connect Error: " + Environment.NewLine + E.Message + Environment.NewLine + "Forcing Server Shutdown..."; throw new Exception(Message); } } }
/// <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) { // Load out database connection this.Driver = ASPServer.Database.Driver; this.Date = Date; this.TimeStamp = Date.ToUnixTimestamp(); // Get our snapshot key value pairs string[] Data = Snapshot.Split('\\'); Snapshot = null; // Check for invalid snapshot string if (Data.Length < 36 || Data.Length % 2 != 0) { IsValidSnapshot = false; return; } // Make sure we have an End of file if (Data[Data.Length - 2] != "EOF" && Data[Data.Length - 4] != "EOF") { IsValidSnapshot = false; return; } // Define if we are central update this.IsCentralUpdate = (Data[Data.Length - 2] == "cdb_update"); // 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)Math.Round(float.Parse(Data[11]), 0); this.MapEnd = (int)Math.Round(float.Parse(Data[13]), 0); // 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 List<Dictionary<string, string>>(); KillData = new List<Dictionary<string, string>>(); // Check for custom map, with no ID if (MapId == 99) { IsCustomMap = true; // Check for existing data List<Dictionary<string, object>> Rows = Driver.Query("SELECT id FROM mapinfo WHERE name=@P0", MapName); if (Rows.Count == 0) { // Create new MapId Rows = Driver.Query("SELECT MAX(id) AS id FROM mapinfo WHERE id >= " + MainForm.Config.ASP_CustomMapID); MapId = (Rows.Count == 0 || String.IsNullOrWhiteSpace(Rows[0]["id"].ToString())) ? MainForm.Config.ASP_CustomMapID : (Int32.Parse(Rows[0]["id"].ToString()) + 1); // make sure the mapid is at least the min custom map id if (MapId < MainForm.Config.ASP_CustomMapID) MapId = MainForm.Config.ASP_CustomMapID; // Insert map data, so we dont lose this mapid we generated if (Rows.Count == 0 || MapId == MainForm.Config.ASP_CustomMapID) Driver.Execute("INSERT INTO mapinfo(id, name) VALUES (@P0, @P1)", MapId, MapName); } else MapId = Int32.Parse(Rows[0]["id"].ToString()); } else IsCustomMap = (MapId > MainForm.Config.ASP_CustomMapID); // Do player snapshots, 36 is first player for (int i = 36; i < Data.Length; i += 2) { string[] Parts = Data[i].Split('_'); // Ignore uncomplete snapshots if (Parts.Length == 1) { if (Parts[0] == "EOF") break; else IsValidSnapshot = false; return; } int id = int.Parse(Parts[1]); if (Parts[0] == "pID") { PlayerData.Add(new Dictionary<string, string>()); KillData.Add(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 IsValidSnapshot = true; }
/// <summary> /// On a new Sqlite database, this method will create the default tables /// </summary> /// <param name="Driver"></param> private void CreateSqliteTables(DatabaseDriver Driver) { // Show Progress Form MainForm.Disable(); bool TaskFormWasOpen = TaskForm.IsOpen; if(!TaskFormWasOpen) TaskForm.Show(MainForm.Instance, "Create Database", "Creating Bf2Stats SQLite Database...", false); // Create Tables TaskForm.UpdateStatus("Creating Stats Tables"); string SQL = Utils.GetResourceAsString("BF2Statistics.SQL.SQLite.Stats.sql"); Driver.Execute(SQL); // Insert Ip2Nation data TaskForm.UpdateStatus("Inserting Ip2Nation Data"); SQL = Utils.GetResourceAsString("BF2Statistics.SQL.Ip2nation.sql"); DbTransaction Transaction = Driver.BeginTransaction(); Driver.Execute(SQL); // Attempt to do the transaction try { Transaction.Commit(); } catch (Exception E) { Transaction.Rollback(); if(!TaskFormWasOpen) TaskForm.CloseForm(); MainForm.Enable(); throw E; } // Close update progress form if(!TaskFormWasOpen) TaskForm.CloseForm(); MainForm.Enable(); }
/// <summary> /// This request provides details of the players unlocked weapons /// </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 GetUnlocksInfo(HttpClient Client, StatsDatabase Database) { // Load class Variables this.Response = Client.Response; this.Driver = Database; // Earned and Available Unlocks int HasUsed = 0; int Earned = 0; int Available = 0; // Get player ID if (Client.Request.QueryString.ContainsKey("pid")) Int32.TryParse(Client.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(MainForm.Config.ASP_UnlocksMode) { // Player Based - Unlocks are earned case 0: // Make sure the player exists Rows = Driver.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()); HasUsed = Int32.Parse(Rows[0]["usedunlocks"].ToString()); Available = Int32.Parse(Rows[0]["availunlocks"].ToString()); Earned = GetBonusUnlocks(); // Determine total unlocks available, based on what he has earned, minus what he has used already Rows = Driver.Query("SELECT COUNT(id) AS count FROM unlocks WHERE id = @P0 AND state = 's'", Pid); int Used = Int32.Parse(Rows[0]["count"].ToString()); Earned -= Used; // Update database if the database is off if (Earned != Available || HasUsed != Used) Driver.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 Dictionary<string, bool> Unlocks = new Dictionary<string, bool>(); Rows = Driver.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 "); // 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 Driver.Execute(Query.ToString()); } else { 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> /// On a new Mysql database, this method will create the default tables /// </summary> /// <param name="Driver"></param> private void CreateMysqlTables(DatabaseDriver Driver) { // Show Progress Form MainForm.Disable(); bool TaskFormWasOpen = TaskForm.IsOpen; if (!TaskFormWasOpen) TaskForm.Show(MainForm.Instance, "Create Database", "Creating Bf2Stats Mysql Tables...", false); // To prevent packet size errors Driver.Execute("SET GLOBAL max_allowed_packet=51200"); // Start Transaction DbTransaction Transaction = Driver.BeginTransaction(); TaskForm.UpdateStatus("Creating Stats Tables"); // Gets Table Queries string[] SQL = Utils.GetResourceFileLines("BF2Statistics.SQL.MySQL.Stats.sql"); List<string> Queries = Utilities.Sql.ExtractQueries(SQL); // Attempt to do the transaction try { // Create Tables foreach (string Query in Queries) Driver.Execute(Query); // Commit Transaction.Commit(); } catch (Exception E) { Transaction.Rollback(); if (!TaskFormWasOpen) TaskForm.CloseForm(); MainForm.Enable(); throw E; } // Insert Ip2Nation data Transaction = Driver.BeginTransaction(); TaskForm.UpdateStatus("Inserting Ip2Nation Data"); SQL = Utils.GetResourceFileLines("BF2Statistics.SQL.Ip2nation.sql"); Queries = Utilities.Sql.ExtractQueries(SQL); // Attempt to do the transaction try { // Insert rows foreach (string Query in Queries) Driver.Execute(Query); // Commit Transaction.Commit(); } catch (Exception E) { Transaction.Rollback(); if(!TaskFormWasOpen) TaskForm.CloseForm(); MainForm.Enable(); throw E; } // Close update progress form if (!TaskFormWasOpen) TaskForm.CloseForm(); MainForm.Enable(); }