From 0f307ac4be582950f306a275c0dd35ad0ef9187c Mon Sep 17 00:00:00 2001 From: David Markowitz Date: Mon, 8 May 2023 02:46:55 -0700 Subject: [PATCH] Fix bugs - Reinforce Query formatting - Guarantee 11 rows are selected at a time by ranking by id, should there be more than an 11 way tie. --- dGame/LeaderboardManager.cpp | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/dGame/LeaderboardManager.cpp b/dGame/LeaderboardManager.cpp index 826fcef3..83703724 100644 --- a/dGame/LeaderboardManager.cpp +++ b/dGame/LeaderboardManager.cpp @@ -69,7 +69,7 @@ void Leaderboard::SetupLeaderboard() { SELECT leaderboard.*, charinfo.name, RANK() OVER ( - ORDER BY %s + ORDER BY %s, UNIX_TIMESTAMP(last_played) ASC, id DESC ) AS ranking FROM leaderboard JOIN charinfo on charinfo.id = leaderboard.character_id WHERE game_id = ? %s @@ -274,16 +274,17 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, GameID gameID, Lead } std::string FormatInsert(const std::string& columns, const std::string& format, va_list args, bool useUpdate) { - const char* insert = "INSERT"; - const char* update = "UPDATE"; - const char* queryType = useUpdate ? update : insert; + const char* insertClause = "INSERT"; + const char* updateClause = "UPDATE"; + const char* queryType = useUpdate ? updateClause : insertClause; - const char* scoreFilter = "character_id = ? AND game_id = ?"; - const char* usedFilter = useUpdate ? scoreFilter : ""; + const char* insertFilter = ", character_id = ?, game_id = ?"; + const char* updateFilter = "WHERE character_id = ? AND game_id = ?"; + const char* usedFilter = useUpdate ? updateFilter : insertFilter; constexpr uint16_t STRING_LENGTH = 400; char formattedInsert[STRING_LENGTH]; - auto queryBase = "%s leaderboard SET %s, character_id = ?, game_id = ? %s;"; + auto queryBase = "%s leaderboard SET %s %s;"; snprintf(formattedInsert, STRING_LENGTH, queryBase, queryType, format.c_str(), usedFilter); char finishedQuery[STRING_LENGTH]; @@ -406,6 +407,9 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, GameID gameID, Lead int32_t oldScore = myScoreResult->getInt("score"); int32_t points; points = va_arg(argsCopy, int32_t); + if (points > oldScore) { + saveQuery = FormatInsert(selectedColumns, insertFormat, args, true); + } // Compare score, if HIGHER save break; } @@ -413,6 +417,9 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, GameID gameID, Lead int32_t oldTime = myScoreResult->getInt("bestTime"); int32_t time; time = va_arg(argsCopy, int32_t); + if (time < oldTime) { + saveQuery = FormatInsert(selectedColumns, insertFormat, args, true); + } // Compare time, if LOWER save break; } @@ -420,6 +427,9 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, GameID gameID, Lead int32_t oldTime = myScoreResult->getInt("bestTime"); int32_t time; time = va_arg(argsCopy, int32_t); + if (time < oldTime) { + saveQuery = FormatInsert(selectedColumns, insertFormat, args, true); + } // Compare time, if HIGHER save break; } @@ -431,6 +441,9 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, GameID gameID, Lead int32_t oldTime = myScoreResult->getInt("bestTime"); int32_t time; time = va_arg(argsCopy, int32_t); + if (points > oldPoints || (points == oldPoints && time < oldTime)) { + saveQuery = FormatInsert(selectedColumns, insertFormat, args, true); + } // Compare points, if HIGHER save, if TIED compare time, if LOWER save // If classic_survival_scoring is 1, reverse the order of the points and time columns break; @@ -443,6 +456,9 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, GameID gameID, Lead int32_t oldWave = myScoreResult->getInt("score"); int32_t wave; wave = va_arg(argsCopy, int32_t); + if (time < oldTime || (time == oldTime && wave > oldWave)) { + saveQuery = FormatInsert(selectedColumns, insertFormat, args, true); + } // Compare wave, if HIGHER save, if TIED compare time, if LOWER save break; } @@ -450,6 +466,9 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, GameID gameID, Lead int32_t oldScore = myScoreResult->getInt("score"); int32_t score; score = va_arg(argsCopy, int32_t); + if (score > oldScore) { + saveQuery = FormatInsert(selectedColumns, insertFormat, args, true); + } // Compare score, if HIGHER save break; } @@ -458,6 +477,7 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, GameID gameID, Lead Game::logger->Log("LeaderboardManager", "Warning: Saving score for leaderboard of type None. Are you sure this is intended?"); break; } + default: Game::logger->Log("LeaderboardManager", "Unknown leaderboard type %i. Cannot save score!", leaderboardType); break;