mirror of
https://github.com/DarkflameUniverse/DarkflameServer
synced 2024-08-30 18:43:58 +00:00
Further work on leaderboards
- Modularize tests - Add migrations - Fix switch case so it actually breaks - Add in missing writes - Beginning work on custom migration to move the leaderboard to the final state
This commit is contained in:
parent
ed2639ce4e
commit
fcb088d263
@ -7,6 +7,8 @@
|
|||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
#include "dLogger.h"
|
#include "dLogger.h"
|
||||||
#include "BinaryPathFinder.h"
|
#include "BinaryPathFinder.h"
|
||||||
|
#include "CDActivitiesTable.h"
|
||||||
|
#include "CDClientManager.h"
|
||||||
|
|
||||||
#include <istream>
|
#include <istream>
|
||||||
|
|
||||||
@ -56,6 +58,8 @@ void MigrationRunner::RunMigrations() {
|
|||||||
Game::logger->Log("MigrationRunner", "Running migration: %s", migration.name.c_str());
|
Game::logger->Log("MigrationRunner", "Running migration: %s", migration.name.c_str());
|
||||||
if (migration.name == "dlu/5_brick_model_sd0.sql") {
|
if (migration.name == "dlu/5_brick_model_sd0.sql") {
|
||||||
runSd0Migrations = true;
|
runSd0Migrations = true;
|
||||||
|
} else if (migration.name == "dlu/10_Update_Leaderboard_Columns.sql") {
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
finalSQL.append(migration.data.c_str());
|
finalSQL.append(migration.data.c_str());
|
||||||
}
|
}
|
||||||
@ -109,7 +113,7 @@ void MigrationRunner::RunSQLiteMigrations() {
|
|||||||
|
|
||||||
// Check if there is an entry in the migration history table on the cdclient database.
|
// Check if there is an entry in the migration history table on the cdclient database.
|
||||||
cdstmt = CDClientDatabase::CreatePreppedStmt("SELECT name FROM migration_history WHERE name = ?;");
|
cdstmt = CDClientDatabase::CreatePreppedStmt("SELECT name FROM migration_history WHERE name = ?;");
|
||||||
cdstmt.bind((int32_t) 1, migration.name.c_str());
|
cdstmt.bind((int32_t)1, migration.name.c_str());
|
||||||
auto cdres = cdstmt.execQuery();
|
auto cdres = cdstmt.execQuery();
|
||||||
bool doExit = !cdres.eof();
|
bool doExit = !cdres.eof();
|
||||||
cdres.finalize();
|
cdres.finalize();
|
||||||
@ -127,7 +131,7 @@ void MigrationRunner::RunSQLiteMigrations() {
|
|||||||
if (doExit) {
|
if (doExit) {
|
||||||
// Insert into cdclient database if there is an entry in the main database but not the cdclient database.
|
// Insert into cdclient database if there is an entry in the main database but not the cdclient database.
|
||||||
cdstmt = CDClientDatabase::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);");
|
cdstmt = CDClientDatabase::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);");
|
||||||
cdstmt.bind((int32_t) 1, migration.name.c_str());
|
cdstmt.bind((int32_t)1, migration.name.c_str());
|
||||||
cdstmt.execQuery().finalize();
|
cdstmt.execQuery().finalize();
|
||||||
cdstmt.finalize();
|
cdstmt.finalize();
|
||||||
continue;
|
continue;
|
||||||
@ -148,7 +152,7 @@ void MigrationRunner::RunSQLiteMigrations() {
|
|||||||
|
|
||||||
// Insert into cdclient database.
|
// Insert into cdclient database.
|
||||||
cdstmt = CDClientDatabase::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);");
|
cdstmt = CDClientDatabase::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);");
|
||||||
cdstmt.bind((int32_t) 1, migration.name.c_str());
|
cdstmt.bind((int32_t)1, migration.name.c_str());
|
||||||
cdstmt.execQuery().finalize();
|
cdstmt.execQuery().finalize();
|
||||||
cdstmt.finalize();
|
cdstmt.finalize();
|
||||||
CDClientDatabase::ExecuteQuery("COMMIT;");
|
CDClientDatabase::ExecuteQuery("COMMIT;");
|
||||||
@ -156,3 +160,23 @@ void MigrationRunner::RunSQLiteMigrations() {
|
|||||||
|
|
||||||
Game::logger->Log("MigrationRunner", "CDServer database is up to date.");
|
Game::logger->Log("MigrationRunner", "CDServer database is up to date.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MigrationRunner::MigrateLeaderboard() {
|
||||||
|
Game::logger->Log("MigrationRunner", "Checking if leaderboard migration needs to be run...");
|
||||||
|
{
|
||||||
|
std::unique_ptr<sql::PreparedStatement> stmt(Database::CreatePreppedStmt("SELECT * FROM migration_history WHERE name = ?;"));
|
||||||
|
stmt->setString(1, "dlu/10_Update_Leaderboard_Columns.sql");
|
||||||
|
std::unique_ptr<sql::ResultSet> res(stmt->executeQuery());
|
||||||
|
if (res->next()) {
|
||||||
|
Game::logger->Log("MigrationRunner", "Leaderboard migration has already been run.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>();
|
||||||
|
auto leaderboards = activitiesTable->Query([=](const CDActivities& entry) {
|
||||||
|
return entry.leaderboardType != -1;
|
||||||
|
});
|
||||||
|
for (auto entry : leaderboards) {
|
||||||
|
Game::logger->Log("MigrationRunner", "Got leaderboard type %i for activity %i", entry.leaderboardType, entry.ActivityID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -10,4 +10,5 @@ struct Migration {
|
|||||||
namespace MigrationRunner {
|
namespace MigrationRunner {
|
||||||
void RunMigrations();
|
void RunMigrations();
|
||||||
void RunSQLiteMigrations();
|
void RunSQLiteMigrations();
|
||||||
|
void MigrateLeaderboard();
|
||||||
};
|
};
|
||||||
|
@ -41,53 +41,59 @@ void Leaderboard::Serialize(RakNet::BitStream* bitStream) const {
|
|||||||
WriteLeaderboardRow(leaderboard, index, "LastPlayed", eLDFType::LDF_TYPE_U64, entry.lastPlayed);
|
WriteLeaderboardRow(leaderboard, index, "LastPlayed", eLDFType::LDF_TYPE_U64, entry.lastPlayed);
|
||||||
WriteLeaderboardRow(leaderboard, index, "NumPlayed", eLDFType::LDF_TYPE_S32, 1);
|
WriteLeaderboardRow(leaderboard, index, "NumPlayed", eLDFType::LDF_TYPE_S32, 1);
|
||||||
WriteLeaderboardRow(leaderboard, index, "name", eLDFType::LDF_TYPE_UTF_16, entry.playerName);
|
WriteLeaderboardRow(leaderboard, index, "name", eLDFType::LDF_TYPE_UTF_16, entry.playerName);
|
||||||
|
WriteLeaderboardRow(leaderboard, index, "RowNumber", eLDFType::LDF_TYPE_S32, entry.placement);
|
||||||
|
|
||||||
// Each minigame has its own "points" system
|
// Each minigame has its own "points" system
|
||||||
switch (leaderboardType) {
|
switch (leaderboardType) {
|
||||||
case Type::ShootingGallery:
|
case Type::ShootingGallery:
|
||||||
WriteLeaderboardRow(leaderboard, index, "HitPercentage", eLDFType::LDF_TYPE_FLOAT, 0.0f);
|
WriteLeaderboardRow(leaderboard, index, "HitPercentage", eLDFType::LDF_TYPE_FLOAT, 0.0f);
|
||||||
// HitPercentage:3 between 0 and 1
|
// HitPercentage:3 between 0 and 1
|
||||||
WriteLeaderboardRow(leaderboard, index, "RowNumber", eLDFType::LDF_TYPE_S32, entry.placement);
|
WriteLeaderboardRow(leaderboard, index, "Score", eLDFType::LDF_TYPE_S32, entry.score);
|
||||||
// RowNumber:1
|
// Score:1
|
||||||
WriteLeaderboardRow(leaderboard, index, "Score", eLDFType::LDF_TYPE_S32, entry.score);
|
WriteLeaderboardRow(leaderboard, index, "Streak", eLDFType::LDF_TYPE_S32, 0);
|
||||||
// Score:1
|
// Streak:1
|
||||||
|
break;
|
||||||
case Type::Racing:
|
case Type::Racing:
|
||||||
WriteLeaderboardRow(leaderboard, index, "BestLapTime", eLDFType::LDF_TYPE_FLOAT, 0.0f);
|
WriteLeaderboardRow(leaderboard, index, "BestLapTime", eLDFType::LDF_TYPE_FLOAT, 0.0f);
|
||||||
// BestLapTime:3
|
// BestLapTime:3
|
||||||
WriteLeaderboardRow(leaderboard, index, "BestTime", eLDFType::LDF_TYPE_FLOAT, 0.0f);
|
WriteLeaderboardRow(leaderboard, index, "BestTime", eLDFType::LDF_TYPE_FLOAT, 0.0f);
|
||||||
// BestTime:3
|
// BestTime:3
|
||||||
WriteLeaderboardRow(leaderboard, index, "License", eLDFType::LDF_TYPE_S32, 0);
|
WriteLeaderboardRow(leaderboard, index, "License", eLDFType::LDF_TYPE_S32, 0);
|
||||||
// License:1
|
// License:1
|
||||||
WriteLeaderboardRow(leaderboard, index, "NumWins", eLDFType::LDF_TYPE_S32, 0);
|
WriteLeaderboardRow(leaderboard, index, "NumWins", eLDFType::LDF_TYPE_S32, 0);
|
||||||
// NumWins:1
|
// NumWins:1
|
||||||
WriteLeaderboardRow(leaderboard, index, "RowNumber", eLDFType::LDF_TYPE_U64, entry.placement);
|
break;
|
||||||
// RowNumber:8
|
case Type::UnusedLeaderboard4:
|
||||||
|
WriteLeaderboardRow(leaderboard, index, "Points", eLDFType::LDF_TYPE_S32, entry.score);
|
||||||
|
// Points:1
|
||||||
|
break;
|
||||||
case Type::MonumentRace:
|
case Type::MonumentRace:
|
||||||
WriteLeaderboardRow(leaderboard, index, "RowNumber", eLDFType::LDF_TYPE_S32, entry.placement);
|
WriteLeaderboardRow(leaderboard, index, "Time", eLDFType::LDF_TYPE_S32, entry.time);
|
||||||
// RowNumber:1
|
// Time:1(?)
|
||||||
// Time:1(?)
|
break;
|
||||||
case Type::FootRace:
|
case Type::FootRace:
|
||||||
WriteLeaderboardRow(leaderboard, index, "RowNumber", eLDFType::LDF_TYPE_S32, entry.placement);
|
WriteLeaderboardRow(leaderboard, index, "Time", eLDFType::LDF_TYPE_S32, entry.time);
|
||||||
// RowNumber:1
|
// Time:1
|
||||||
WriteLeaderboardRow(leaderboard, index, "Time", eLDFType::LDF_TYPE_S32, 0);
|
break;
|
||||||
// Time:1
|
|
||||||
case Type::Survival:
|
case Type::Survival:
|
||||||
WriteLeaderboardRow(leaderboard, index, "Points", eLDFType::LDF_TYPE_S32, entry.score);
|
WriteLeaderboardRow(leaderboard, index, "Points", eLDFType::LDF_TYPE_S32, entry.score);
|
||||||
// Points:1
|
// Points:1
|
||||||
WriteLeaderboardRow(leaderboard, index, "RowNumber", eLDFType::LDF_TYPE_S32, entry.placement);
|
WriteLeaderboardRow(leaderboard, index, "Time", eLDFType::LDF_TYPE_S32, entry.time);
|
||||||
// RowNumber:1
|
// Time:1
|
||||||
WriteLeaderboardRow(leaderboard, index, "Time", eLDFType::LDF_TYPE_S32, 0);
|
break;
|
||||||
// Time:1
|
|
||||||
case Type::SurvivalNS:
|
case Type::SurvivalNS:
|
||||||
WriteLeaderboardRow(leaderboard, index, "RowNumber", eLDFType::LDF_TYPE_U64, entry.placement);
|
WriteLeaderboardRow(leaderboard, index, "Time", eLDFType::LDF_TYPE_S32, entry.time);
|
||||||
// RowNumber:8
|
// Time:1
|
||||||
WriteLeaderboardRow(leaderboard, index, "Time", eLDFType::LDF_TYPE_S32, entry.time);
|
WriteLeaderboardRow(leaderboard, index, "Wave", eLDFType::LDF_TYPE_S32, entry.score);
|
||||||
// Time:1
|
// Wave:1
|
||||||
WriteLeaderboardRow(leaderboard, index, "Wave", eLDFType::LDF_TYPE_S32, entry.score);
|
break;
|
||||||
// Wave:1
|
|
||||||
case Type::Donations:
|
case Type::Donations:
|
||||||
// Something? idk yet.
|
WriteLeaderboardRow(leaderboard, index, "Score", eLDFType::LDF_TYPE_S32, entry.score);
|
||||||
|
// Score:1
|
||||||
|
// Something? idk yet.
|
||||||
|
break;
|
||||||
case Type::None:
|
case Type::None:
|
||||||
|
// This type is included here simply to resolve a compiler warning on mac about unused enum types
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -37,7 +37,7 @@ public:
|
|||||||
Racing,
|
Racing,
|
||||||
MonumentRace,
|
MonumentRace,
|
||||||
FootRace,
|
FootRace,
|
||||||
// There is no 4 defined anywhere in the client or cdclient
|
UnusedLeaderboard4,// There is no 4 defined anywhere in the client or cdclient
|
||||||
Survival = 5,
|
Survival = 5,
|
||||||
SurvivalNS,
|
SurvivalNS,
|
||||||
Donations,
|
Donations,
|
||||||
|
@ -150,12 +150,6 @@ int main(int argc, char** argv) {
|
|||||||
const bool oldCDServerExists = std::filesystem::exists(Game::assetManager->GetResPath() / "CDServer.sqlite");
|
const bool oldCDServerExists = std::filesystem::exists(Game::assetManager->GetResPath() / "CDServer.sqlite");
|
||||||
const bool fdbExists = std::filesystem::exists(Game::assetManager->GetResPath() / "cdclient.fdb");
|
const bool fdbExists = std::filesystem::exists(Game::assetManager->GetResPath() / "cdclient.fdb");
|
||||||
|
|
||||||
auto query = Database::CreatePreppedStmt("select name, score, time, UNIX_TIMESTAMP(last_played) as lastPlayed from leaderboard as l join charinfo as ci on ci.id = l.character_id where game_id = 1864 order by score desc, time desc limit 11;");
|
|
||||||
auto myResult = query->executeQuery();
|
|
||||||
while (myResult->next()) {
|
|
||||||
Game::logger->Log("MasterServer", "%s %i %i %i", myResult->getString("name").c_str(), myResult->getInt("score"), myResult->getInt("time"), myResult->getInt("lastPlayed"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cdServerExists) {
|
if (!cdServerExists) {
|
||||||
if (oldCDServerExists) {
|
if (oldCDServerExists) {
|
||||||
// If the file doesn't exist in the new CDServer location, copy it there. We copy because we may not have write permissions from the previous directory.
|
// If the file doesn't exist in the new CDServer location, copy it there. We copy because we may not have write permissions from the previous directory.
|
||||||
@ -208,6 +202,9 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This migration relies on cdclient data so run it last
|
||||||
|
MigrationRunner::MigrateLeaderboard();
|
||||||
|
|
||||||
//If the first command line argument is -a or --account then make the user
|
//If the first command line argument is -a or --account then make the user
|
||||||
//input a username and password, with the password being hidden.
|
//input a username and password, with the password being hidden.
|
||||||
if (argc > 1 &&
|
if (argc > 1 &&
|
||||||
|
1
migrations/dlu/10_Update_Leaderboard_Columns.sql
Normal file
1
migrations/dlu/10_Update_Leaderboard_Columns.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
# This migration is a mock. See the real migration in MigrationRunner::MigrateLeaderboard.
|
8
migrations/dlu/9_Update_Leaderboard_Storage.sql
Normal file
8
migrations/dlu/9_Update_Leaderboard_Storage.sql
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ALTER TABLE leaderboard
|
||||||
|
ADD COLUMN hitPercentage FLOAT NOT NULL DEFAULT 0,
|
||||||
|
ADD COLUMN streak INT NOT NULL DEFAULT 0,
|
||||||
|
ADD COLUMN bestLapTime FLOAT NOT NULL DEFAULT 0,
|
||||||
|
ADD COLUMN numWins INT NOT NULL DEFAULT 0,
|
||||||
|
MODIFY time FLOAT NOT NULL DEFAULT 0;
|
||||||
|
|
||||||
|
ALTER TABLE leaderboard CHANGE time bestTime float;
|
@ -32,6 +32,15 @@ protected:
|
|||||||
bitStream.Reset();
|
bitStream.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RunTests(Leaderboard::Type type) {
|
||||||
|
Game::logger->Log("LeaderboardTests", "Testing leaderboard %i for Serialize speed", type);
|
||||||
|
Leaderboard leaderboard(0, Leaderboard::InfoType::Top, false, type);
|
||||||
|
TestLeaderboard(leaderboard, 1);
|
||||||
|
TestLeaderboard(leaderboard, 10);
|
||||||
|
TestLeaderboard(leaderboard, 100);
|
||||||
|
TestLeaderboard(leaderboard, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -68,9 +77,5 @@ protected:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
TEST_F(LeaderboardTests, LeaderboardSpeedTest) {
|
TEST_F(LeaderboardTests, LeaderboardSpeedTest) {
|
||||||
Leaderboard leaderboard(10, Leaderboard::InfoType::MyStanding, false, Leaderboard::Type::Survival);
|
RunTests(Leaderboard::Type::Racing);
|
||||||
TestLeaderboard(leaderboard, 1);
|
|
||||||
TestLeaderboard(leaderboard, 10);
|
|
||||||
TestLeaderboard(leaderboard, 100);
|
|
||||||
TestLeaderboard(leaderboard, 1000);
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user