mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-21 21:17:25 +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 "dLogger.h"
|
||||
#include "BinaryPathFinder.h"
|
||||
#include "CDActivitiesTable.h"
|
||||
#include "CDClientManager.h"
|
||||
|
||||
#include <istream>
|
||||
|
||||
@ -56,6 +58,8 @@ void MigrationRunner::RunMigrations() {
|
||||
Game::logger->Log("MigrationRunner", "Running migration: %s", migration.name.c_str());
|
||||
if (migration.name == "dlu/5_brick_model_sd0.sql") {
|
||||
runSd0Migrations = true;
|
||||
} else if (migration.name == "dlu/10_Update_Leaderboard_Columns.sql") {
|
||||
continue;
|
||||
} else {
|
||||
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.
|
||||
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();
|
||||
bool doExit = !cdres.eof();
|
||||
cdres.finalize();
|
||||
@ -127,7 +131,7 @@ void MigrationRunner::RunSQLiteMigrations() {
|
||||
if (doExit) {
|
||||
// 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.bind((int32_t) 1, migration.name.c_str());
|
||||
cdstmt.bind((int32_t)1, migration.name.c_str());
|
||||
cdstmt.execQuery().finalize();
|
||||
cdstmt.finalize();
|
||||
continue;
|
||||
@ -148,7 +152,7 @@ void MigrationRunner::RunSQLiteMigrations() {
|
||||
|
||||
// Insert into cdclient database.
|
||||
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.finalize();
|
||||
CDClientDatabase::ExecuteQuery("COMMIT;");
|
||||
@ -156,3 +160,23 @@ void MigrationRunner::RunSQLiteMigrations() {
|
||||
|
||||
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 {
|
||||
void RunMigrations();
|
||||
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, "NumPlayed", eLDFType::LDF_TYPE_S32, 1);
|
||||
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
|
||||
switch (leaderboardType) {
|
||||
case Type::ShootingGallery:
|
||||
WriteLeaderboardRow(leaderboard, index, "HitPercentage", eLDFType::LDF_TYPE_FLOAT, 0.0f);
|
||||
// HitPercentage:3 between 0 and 1
|
||||
WriteLeaderboardRow(leaderboard, index, "RowNumber", eLDFType::LDF_TYPE_S32, entry.placement);
|
||||
// RowNumber:1
|
||||
WriteLeaderboardRow(leaderboard, index, "Score", eLDFType::LDF_TYPE_S32, entry.score);
|
||||
// Score:1
|
||||
WriteLeaderboardRow(leaderboard, index, "HitPercentage", eLDFType::LDF_TYPE_FLOAT, 0.0f);
|
||||
// HitPercentage:3 between 0 and 1
|
||||
WriteLeaderboardRow(leaderboard, index, "Score", eLDFType::LDF_TYPE_S32, entry.score);
|
||||
// Score:1
|
||||
WriteLeaderboardRow(leaderboard, index, "Streak", eLDFType::LDF_TYPE_S32, 0);
|
||||
// Streak:1
|
||||
break;
|
||||
case Type::Racing:
|
||||
WriteLeaderboardRow(leaderboard, index, "BestLapTime", eLDFType::LDF_TYPE_FLOAT, 0.0f);
|
||||
// BestLapTime:3
|
||||
WriteLeaderboardRow(leaderboard, index, "BestTime", eLDFType::LDF_TYPE_FLOAT, 0.0f);
|
||||
// BestTime:3
|
||||
WriteLeaderboardRow(leaderboard, index, "License", eLDFType::LDF_TYPE_S32, 0);
|
||||
// License:1
|
||||
WriteLeaderboardRow(leaderboard, index, "NumWins", eLDFType::LDF_TYPE_S32, 0);
|
||||
// NumWins:1
|
||||
WriteLeaderboardRow(leaderboard, index, "RowNumber", eLDFType::LDF_TYPE_U64, entry.placement);
|
||||
// RowNumber:8
|
||||
WriteLeaderboardRow(leaderboard, index, "BestLapTime", eLDFType::LDF_TYPE_FLOAT, 0.0f);
|
||||
// BestLapTime:3
|
||||
WriteLeaderboardRow(leaderboard, index, "BestTime", eLDFType::LDF_TYPE_FLOAT, 0.0f);
|
||||
// BestTime:3
|
||||
WriteLeaderboardRow(leaderboard, index, "License", eLDFType::LDF_TYPE_S32, 0);
|
||||
// License:1
|
||||
WriteLeaderboardRow(leaderboard, index, "NumWins", eLDFType::LDF_TYPE_S32, 0);
|
||||
// NumWins:1
|
||||
break;
|
||||
case Type::UnusedLeaderboard4:
|
||||
WriteLeaderboardRow(leaderboard, index, "Points", eLDFType::LDF_TYPE_S32, entry.score);
|
||||
// Points:1
|
||||
break;
|
||||
case Type::MonumentRace:
|
||||
WriteLeaderboardRow(leaderboard, index, "RowNumber", eLDFType::LDF_TYPE_S32, entry.placement);
|
||||
// RowNumber:1
|
||||
// Time:1(?)
|
||||
WriteLeaderboardRow(leaderboard, index, "Time", eLDFType::LDF_TYPE_S32, entry.time);
|
||||
// Time:1(?)
|
||||
break;
|
||||
case Type::FootRace:
|
||||
WriteLeaderboardRow(leaderboard, index, "RowNumber", eLDFType::LDF_TYPE_S32, entry.placement);
|
||||
// RowNumber:1
|
||||
WriteLeaderboardRow(leaderboard, index, "Time", eLDFType::LDF_TYPE_S32, 0);
|
||||
// Time:1
|
||||
WriteLeaderboardRow(leaderboard, index, "Time", eLDFType::LDF_TYPE_S32, entry.time);
|
||||
// Time:1
|
||||
break;
|
||||
case Type::Survival:
|
||||
WriteLeaderboardRow(leaderboard, index, "Points", eLDFType::LDF_TYPE_S32, entry.score);
|
||||
// Points:1
|
||||
WriteLeaderboardRow(leaderboard, index, "RowNumber", eLDFType::LDF_TYPE_S32, entry.placement);
|
||||
// RowNumber:1
|
||||
WriteLeaderboardRow(leaderboard, index, "Time", eLDFType::LDF_TYPE_S32, 0);
|
||||
// Time:1
|
||||
WriteLeaderboardRow(leaderboard, index, "Points", eLDFType::LDF_TYPE_S32, entry.score);
|
||||
// Points:1
|
||||
WriteLeaderboardRow(leaderboard, index, "Time", eLDFType::LDF_TYPE_S32, entry.time);
|
||||
// Time:1
|
||||
break;
|
||||
case Type::SurvivalNS:
|
||||
WriteLeaderboardRow(leaderboard, index, "RowNumber", eLDFType::LDF_TYPE_U64, entry.placement);
|
||||
// RowNumber:8
|
||||
WriteLeaderboardRow(leaderboard, index, "Time", eLDFType::LDF_TYPE_S32, entry.time);
|
||||
// Time:1
|
||||
WriteLeaderboardRow(leaderboard, index, "Wave", eLDFType::LDF_TYPE_S32, entry.score);
|
||||
// Wave:1
|
||||
WriteLeaderboardRow(leaderboard, index, "Time", eLDFType::LDF_TYPE_S32, entry.time);
|
||||
// Time:1
|
||||
WriteLeaderboardRow(leaderboard, index, "Wave", eLDFType::LDF_TYPE_S32, entry.score);
|
||||
// Wave:1
|
||||
break;
|
||||
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:
|
||||
// This type is included here simply to resolve a compiler warning on mac about unused enum types
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -37,7 +37,7 @@ public:
|
||||
Racing,
|
||||
MonumentRace,
|
||||
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,
|
||||
SurvivalNS,
|
||||
Donations,
|
||||
|
@ -150,12 +150,6 @@ int main(int argc, char** argv) {
|
||||
const bool oldCDServerExists = std::filesystem::exists(Game::assetManager->GetResPath() / "CDServer.sqlite");
|
||||
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 (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.
|
||||
@ -208,6 +202,9 @@ int main(int argc, char** argv) {
|
||||
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
|
||||
//input a username and password, with the password being hidden.
|
||||
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();
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
@ -68,9 +77,5 @@ protected:
|
||||
*/
|
||||
|
||||
TEST_F(LeaderboardTests, LeaderboardSpeedTest) {
|
||||
Leaderboard leaderboard(10, Leaderboard::InfoType::MyStanding, false, Leaderboard::Type::Survival);
|
||||
TestLeaderboard(leaderboard, 1);
|
||||
TestLeaderboard(leaderboard, 10);
|
||||
TestLeaderboard(leaderboard, 100);
|
||||
TestLeaderboard(leaderboard, 1000);
|
||||
RunTests(Leaderboard::Type::Racing);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user