Skip to content

Commit

Permalink
MVP Stats + MySQL best practices and UTF8 (splewis#608)
Browse files Browse the repository at this point in the history
* utf8 and mysql insert/update logic

* Added MVP stat recording
  • Loading branch information
nickdnk authored Dec 24, 2020
1 parent c92096f commit 4d7a527
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 140 deletions.
175 changes: 68 additions & 107 deletions misc/import_stats.sql
Original file line number Diff line number Diff line change
@@ -1,112 +1,73 @@
--
-- Table structure for table `get5_stats_maps`
--

DROP TABLE IF EXISTS `get5_stats_players`;
DROP TABLE IF EXISTS `get5_stats_maps`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `get5_stats_maps` (
`matchid` int(10) unsigned NOT NULL,
`mapnumber` smallint(5) unsigned NOT NULL,
`start_time` datetime NOT NULL,
`end_time` datetime,
`winner` varchar(16) NOT NULL DEFAULT '',
`mapname` varchar(64) NOT NULL DEFAULT '',
`team1_score` smallint(5) unsigned NOT NULL DEFAULT '0',
`team2_score` smallint(5) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`matchid`,`mapnumber`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `get5_stats_maps`
--

LOCK TABLES `get5_stats_maps` WRITE;
/*!40000 ALTER TABLE `get5_stats_maps` DISABLE KEYS */;
/*!40000 ALTER TABLE `get5_stats_maps` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `get5_stats_matches`
--

DROP TABLE IF EXISTS `get5_stats_matches`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `get5_stats_matches` (
`matchid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`start_time` datetime NOT NULL,
`end_time` datetime,
`winner` varchar(16) NOT NULL DEFAULT '',
`series_type` varchar(64) NOT NULL DEFAULT '',
`team1_name` varchar(64) NOT NULL DEFAULT '',
`team1_score` smallint(5) unsigned NOT NULL DEFAULT '0',
`team2_name` varchar(64) NOT NULL DEFAULT '',
`team2_score` smallint(5) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`matchid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `get5_stats_matches`
--

LOCK TABLES `get5_stats_matches` WRITE;
/*!40000 ALTER TABLE `get5_stats_matches` DISABLE KEYS */;
/*!40000 ALTER TABLE `get5_stats_matches` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `get5_stats_players`
--

DROP TABLE IF EXISTS `get5_stats_players`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `get5_stats_players` (
`matchid` int(10) unsigned NOT NULL,
`mapnumber` smallint(5) unsigned NOT NULL,
`steamid64` varchar(32) NOT NULL,
`team` varchar(16) NOT NULL DEFAULT '',
`rounds_played` smallint(5) unsigned NOT NULL,
`name` varchar(64) NOT NULL,
`kills` smallint(5) unsigned NOT NULL,
`deaths` smallint(5) unsigned NOT NULL,
`assists` smallint(5) unsigned NOT NULL,
`flashbang_assists` smallint(5) unsigned NOT NULL,
`teamkills` smallint(5) unsigned NOT NULL,
`headshot_kills` smallint(5) unsigned NOT NULL,
`damage` int(10) unsigned NOT NULL,
`bomb_plants` smallint(5) unsigned NOT NULL,
`bomb_defuses` smallint(5) unsigned NOT NULL,
`v1` smallint(5) unsigned NOT NULL,
`v2` smallint(5) unsigned NOT NULL,
`v3` smallint(5) unsigned NOT NULL,
`v4` smallint(5) unsigned NOT NULL,
`v5` smallint(5) unsigned NOT NULL,
`2k` smallint(5) unsigned NOT NULL,
`3k` smallint(5) unsigned NOT NULL,
`4k` smallint(5) unsigned NOT NULL,
`5k` smallint(5) unsigned NOT NULL,
`firstkill_t` smallint(5) unsigned NOT NULL,
`firstkill_ct` smallint(5) unsigned NOT NULL,
`firstdeath_t` smallint(5) unsigned NOT NULL,
`firstdeath_ct` smallint(5) unsigned NOT NULL,
`tradekill` smallint(5) unsigned NOT NULL,
`kast` smallint(5) unsigned NOT NULL,
`contribution_score` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`matchid`,`mapnumber`,`steamid64`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `get5_stats_players`
--
CREATE TABLE `get5_stats_matches`
(
`matchid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`start_time` datetime NOT NULL,
`end_time` datetime NULL DEFAULT NULL,
`winner` varchar(16) NOT NULL DEFAULT '',
`series_type` varchar(64) NOT NULL DEFAULT '',
`team1_name` varchar(64) NOT NULL DEFAULT '',
`team1_score` smallint(5) unsigned NOT NULL DEFAULT '0',
`team2_name` varchar(64) NOT NULL DEFAULT '',
`team2_score` smallint(5) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`matchid`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;

LOCK TABLES `get5_stats_players` WRITE;
/*!40000 ALTER TABLE `get5_stats_players` DISABLE KEYS */;
/*!40000 ALTER TABLE `get5_stats_players` ENABLE KEYS */;
UNLOCK TABLES;
CREATE TABLE `get5_stats_maps`
(
`matchid` int(10) unsigned NOT NULL,
`mapnumber` smallint(5) unsigned NOT NULL,
`start_time` datetime NOT NULL,
`end_time` datetime NULL DEFAULT NULL,
`winner` varchar(16) NOT NULL DEFAULT '',
`mapname` varchar(64) NOT NULL DEFAULT '',
`team1_score` smallint(5) unsigned NOT NULL DEFAULT '0',
`team2_score` smallint(5) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`matchid`, `mapnumber`),
CONSTRAINT `get5_stats_maps_matchid` FOREIGN KEY (`matchid`) REFERENCES `get5_stats_matches` (`matchid`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;

-- Dump completed on 2016-07-03 1:10:28
CREATE TABLE `get5_stats_players`
(
`matchid` int(10) unsigned NOT NULL,
`mapnumber` smallint(5) unsigned NOT NULL,
`steamid64` varchar(32) NOT NULL,
`team` varchar(16) NOT NULL DEFAULT '',
`rounds_played` smallint(5) unsigned NOT NULL,
`name` varchar(64) NOT NULL,
`kills` smallint(5) unsigned NOT NULL,
`deaths` smallint(5) unsigned NOT NULL,
`assists` smallint(5) unsigned NOT NULL,
`flashbang_assists` smallint(5) unsigned NOT NULL,
`teamkills` smallint(5) unsigned NOT NULL,
`headshot_kills` smallint(5) unsigned NOT NULL,
`damage` int(10) unsigned NOT NULL,
`bomb_plants` smallint(5) unsigned NOT NULL,
`bomb_defuses` smallint(5) unsigned NOT NULL,
`v1` smallint(5) unsigned NOT NULL,
`v2` smallint(5) unsigned NOT NULL,
`v3` smallint(5) unsigned NOT NULL,
`v4` smallint(5) unsigned NOT NULL,
`v5` smallint(5) unsigned NOT NULL,
`2k` smallint(5) unsigned NOT NULL,
`3k` smallint(5) unsigned NOT NULL,
`4k` smallint(5) unsigned NOT NULL,
`5k` smallint(5) unsigned NOT NULL,
`firstkill_t` smallint(5) unsigned NOT NULL,
`firstkill_ct` smallint(5) unsigned NOT NULL,
`firstdeath_t` smallint(5) unsigned NOT NULL,
`firstdeath_ct` smallint(5) unsigned NOT NULL,
`tradekill` smallint(5) unsigned NOT NULL,
`kast` smallint(5) unsigned NOT NULL,
`contribution_score` smallint(5) unsigned NOT NULL,
`mvp` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`matchid`, `mapnumber`, `steamid64`),
KEY `steamid64` (`steamid64`),
CONSTRAINT `get5_stats_players_matchid` FOREIGN KEY (`matchid`) REFERENCES `get5_stats_matches` (`matchid`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
16 changes: 16 additions & 0 deletions scripting/get5/stats.sp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public void Stats_PluginStart() {
HookEvent("bomb_exploded", Stats_BombExplodedEvent);
HookEvent("flashbang_detonate", Stats_FlashbangDetonateEvent, EventHookMode_Pre);
HookEvent("player_blind", Stats_PlayerBlindEvent);
HookEvent("round_mvp", Stats_RoundMVPEvent);
}

public void Stats_Reset() {
Expand Down Expand Up @@ -392,6 +393,21 @@ public Action Stats_PlayerBlindEvent(Event event, const char[] name, bool dontBr
return Plugin_Continue;
}

public Action Stats_RoundMVPEvent(Event event, const char[] name, bool dontBroadcast) {
if (g_GameState != Get5State_Live) {
return Plugin_Continue;
}

int userid = event.GetInt("userid");
int client = GetClientOfUserId(userid);

if (IsValidClient(client)) {
IncrementPlayerStat(client, STAT_MVP);
}

return Plugin_Continue;
}

public void GetFlashInfo(int serial) {
int client = GetClientFromSerial(serial);
if (IsValidClient(client)) {
Expand Down
85 changes: 52 additions & 33 deletions scripting/get5_mysqlstats.sp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#pragma newdecls required

Database db = null;
char queryBuffer[1024];
char queryBuffer[2048];

int g_MatchID = -1;

Expand Down Expand Up @@ -61,7 +61,7 @@ public void OnPluginStart() {
SetFailState("Could not connect to get5 database: %s", error);
} else {
g_DisableStats = false;
db.SetCharset("utf8");
db.SetCharset("utf8mb4");
}
}

Expand Down Expand Up @@ -112,41 +112,30 @@ public void Get5_OnSeriesInit() {
LogMessage("Starting match id %d", g_MatchID);

} else {
Transaction t = SQL_CreateTransaction();

Format(queryBuffer, sizeof(queryBuffer), "INSERT INTO `get5_stats_matches` \
(series_type, team1_name, team2_name, start_time) VALUES \
('%s', '%s', '%s', NOW())",
seriesTypeSz, team1NameSz, team2NameSz);
LogDebug(queryBuffer);
t.AddQuery(queryBuffer);
db.Query(MatchInitCallback, queryBuffer);

Format(queryBuffer, sizeof(queryBuffer), "SELECT LAST_INSERT_ID()");
LogDebug(queryBuffer);
t.AddQuery(queryBuffer);

db.Execute(t, MatchInitSuccess, MatchInitFailure);
}
}

public void MatchInitSuccess(Database database, any data, int numQueries, Handle[] results,
any[] queryData) {
Handle matchidResult = results[1];
if (SQL_FetchRow(matchidResult)) {
SetMatchID(SQL_FetchInt(matchidResult, 0));
LogMessage("Starting match id %d", g_MatchID);
} else {
public void MatchInitCallback(Database dbObj, DBResultSet results, const char[] error, any data) {

if (results == null) {
LogError("Failed to get matchid from match init query");
g_DisableStats = true;
} else {
if (results.InsertId > 0) {
SetMatchID(results.InsertId);
}
LogMessage("Starting match id %d", g_MatchID);
}
}

public void MatchInitFailure(Database database, any data, int numQueries, const char[] error,
int failIndex, any[] queryData) {
LogError("Failed match creation query, error = %s", error);
g_DisableStats = true;
}

static void SetMatchID(int matchid) {
g_MatchID = matchid;
char idStr[32];
Expand Down Expand Up @@ -270,22 +259,24 @@ public void AddPlayerStats(KeyValues kv, MatchTeam team) {
int tradekill = kv.GetNum(STAT_TRADEKILL);
int kast = kv.GetNum(STAT_KAST);
int contribution_score = kv.GetNum(STAT_CONTRIBUTION_SCORE);
int mvp = kv.GetNum(STAT_MVP);

char teamString[16];
GetTeamString(team, teamString, sizeof(teamString));

// TODO: this should really get split up somehow. Once it hits 32-arguments
// (aka just a few more) it will cause runtime errors and the Format will fail.
// clang-format off
Format(queryBuffer, sizeof(queryBuffer), "REPLACE INTO `get5_stats_players` \
(matchid, mapnumber, steamid64, team, \
rounds_played, name, kills, deaths, flashbang_assists, \
assists, teamkills, headshot_kills, damage, \
bomb_plants, bomb_defuses, \
v1, v2, v3, v4, v5, \
2k, 3k, 4k, 5k, \
firstkill_t, firstkill_ct, firstdeath_t, firstdeath_ct, \
tradekill, kast, contribution_score \
Format(queryBuffer, sizeof(queryBuffer),
"INSERT INTO `get5_stats_players` \
(`matchid`, `mapnumber`, `steamid64`, `team`, \
`rounds_played`, `name`, `kills`, `deaths`, `flashbang_assists`, \
`assists`, `teamkills`, `headshot_kills`, `damage`, \
`bomb_plants`, `bomb_defuses`, \
`v1`, `v2`, `v3`, `v4`, `v5`, \
`2k`, `3k`, `4k`, `5k`, \
`firstkill_t`, `firstkill_ct`, `firstdeath_t`, `firstdeath_ct`, \
`tradekill`, `kast`, `contribution_score`, `mvp` \
) VALUES \
(%d, %d, '%s', '%s', \
%d, '%s', %d, %d, %d, \
Expand All @@ -294,15 +285,43 @@ public void AddPlayerStats(KeyValues kv, MatchTeam team) {
%d, %d, %d, %d, %d, \
%d, %d, %d, %d, \
%d, %d, %d, %d, \
%d, %d, %d)",
%d, %d, %d, %d) \
ON DUPLICATE KEY UPDATE \
`rounds_played` = VALUES(`rounds_played`), \
`kills` = VALUES(`kills`), \
`deaths` = VALUES(`deaths`), \
`flashbang_assists` = VALUES(`flashbang_assists`), \
`assists` = VALUES(`assists`), \
`teamkills` = VALUES(`teamkills`), \
`headshot_kills` = VALUES(`headshot_kills`), \
`damage` = VALUES(`damage`), \
`bomb_plants` = VALUES(`bomb_plants`), \
`bomb_defuses` = VALUES(`bomb_defuses`), \
`v1` = VALUES(`v1`), \
`v2` = VALUES(`v2`), \
`v3` = VALUES(`v3`), \
`v4` = VALUES(`v4`), \
`v5` = VALUES(`v5`), \
`2k` = VALUES(`2k`), \
`3k` = VALUES(`3k`), \
`4k` = VALUES(`4k`), \
`5k` = VALUES(`5k`), \
`firstkill_t` = VALUES(`firstkill_t`), \
`firstkill_ct` = VALUES(`firstkill_ct`), \
`firstdeath_t` = VALUES(`firstdeath_t`), \
`firstdeath_ct` = VALUES(`firstdeath_ct`), \
`tradekill` = VALUES(`tradekill`), \
`kast` = VALUES(`kast`), \
`contribution_score` = VALUES(`contribution_score`), \
`mvp` = VALUES(`mvp`)",
g_MatchID, mapNumber, authSz, teamString,
roundsplayed, nameSz, kills, deaths, flashbang_assists,
assists, teamkills, headshot_kills, damage,
plants, defuses,
v1, v2, v3, v4, v5,
k2, k3, k4, k5,
firstkill_t, firstkill_ct, firstdeath_t, firstdeath_ct,
tradekill, kast, contribution_score);
tradekill, kast, contribution_score, mvp);
// clang-format on

LogDebug(queryBuffer);
Expand Down
1 change: 1 addition & 0 deletions scripting/include/get5.inc
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ native int Get5_IncreasePlayerStat(int client, const char[] statName, int amount
#define STAT_TRADEKILL "tradekill"
#define STAT_KAST "kast"
#define STAT_CONTRIBUTION_SCORE "contribution_score"
#define STAT_MVP "mvp"

public SharedPlugin __pl_get5 = {
name = "get5",
Expand Down

0 comments on commit 4d7a527

Please sign in to comment.