Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: weekly leaderboards and shooting gallery high score #1719

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 20 additions & 17 deletions dGame/LeaderboardManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ namespace LeaderboardManager {
std::map<GameID, Leaderboard::Type> leaderboardCache;
}

Leaderboard::Leaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, LWOOBJID relatedPlayer, const Leaderboard::Type leaderboardType) {
Leaderboard::Leaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, LWOOBJID relatedPlayer, const uint32_t numResults, const Leaderboard::Type leaderboardType) {
this->gameID = gameID;
this->weekly = weekly;
this->infoType = infoType;
this->leaderboardType = leaderboardType;
this->relatedPlayer = relatedPlayer;
m_NumResults = numResults;
EmosewaMC marked this conversation as resolved.
Show resolved Hide resolved
}

Leaderboard::~Leaderboard() {
Expand Down Expand Up @@ -144,7 +145,7 @@ void QueryToLdf(Leaderboard& leaderboard, const std::vector<ILeaderboard::Entry>
}
}

std::vector<ILeaderboard::Entry> FilterTo10(const std::vector<ILeaderboard::Entry>& leaderboard, const uint32_t relatedPlayer, const Leaderboard::InfoType infoType) {
std::vector<ILeaderboard::Entry> FilterToNumResults(const std::vector<ILeaderboard::Entry>& leaderboard, const uint32_t relatedPlayer, const Leaderboard::InfoType infoType, const uint32_t numResults) {
std::vector<ILeaderboard::Entry> toReturn;

int32_t index = 0;
Expand All @@ -155,18 +156,19 @@ std::vector<ILeaderboard::Entry> FilterTo10(const std::vector<ILeaderboard::Entr
}
}

if (leaderboard.size() < 10) {
if (leaderboard.size() < numResults) {
toReturn.assign(leaderboard.begin(), leaderboard.end());
index = 0;
} else if (index < 10) {
toReturn.assign(leaderboard.begin(), leaderboard.begin() + 10); // get the top 10 since we are in the top 10
} else if (index < numResults) {
toReturn.assign(leaderboard.begin(), leaderboard.begin() + numResults); // get the top 10 since we are in the top 10
index = 0;
} else if (index > leaderboard.size() - 10) {
toReturn.assign(leaderboard.end() - 10, leaderboard.end()); // get the bottom 10 since we are in the bottom 10
index = leaderboard.size() - 10;
} else if (index > leaderboard.size() - numResults) {
toReturn.assign(leaderboard.end() - numResults, leaderboard.end()); // get the bottom 10 since we are in the bottom 10
index = leaderboard.size() - numResults;
} else {
toReturn.assign(leaderboard.begin() + index - 5, leaderboard.begin() + index + 5); // get the 5 above and below
index -= 5;
auto half = numResults / 2;
toReturn.assign(leaderboard.begin() + index - half, leaderboard.begin() + index + half); // get the 5 above and below
index -= half;
}

int32_t i = index;
Expand All @@ -180,7 +182,7 @@ std::vector<ILeaderboard::Entry> FilterTo10(const std::vector<ILeaderboard::Entr
std::vector<ILeaderboard::Entry> FilterWeeklies(const std::vector<ILeaderboard::Entry>& leaderboard) {
// Filter the leaderboard to only include entries from the last week
const auto currentTime = std::chrono::system_clock::now();
auto epochTime = currentTime.time_since_epoch().count();
auto epochTime = std::chrono::duration_cast<std::chrono::seconds>(currentTime.time_since_epoch()).count();
constexpr auto SECONDS_IN_A_WEEK = 60 * 60 * 24 * 7; // if you think im taking leap seconds into account thats cute.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::chrono should have built-in conversion factors for a lot of this

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and that call would be?

Copy link
Collaborator

@jadebenn jadebenn Jan 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like this?

Not sure if it's feasible to store the lastPlayedTimestamp as an std::chrono::time_point, but if it is, it would avoid some of the pitfalls of using time_since_last_epoch() and count()

std::vector<ILeaderboard::Entry> FilterWeeklies(const std::vector<ILeaderboard::Entry>& leaderboard) {
    // Filter the leaderboard to only include entries from the last week
    const auto currentTime = std::chrono::system_clock::now();
    std::vector<ILeaderboard::Entry> weeklyLeaderboard;        
    for (const auto& entry : leaderboard) {
	    const auto elapsedTime = currentTime - entry.lastPlayedTimestamp;
	    if (elapsedTime < std::chrono::weeks{ 1 }) {
            weeklyLeaderboard.push_back(entry);
        }
    }
    return weeklyLeaderboard;
}

Copy link
Collaborator

@jadebenn jadebenn Jan 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, you could also use std::copy_if:

// Filter the leaderboard to only include entries from the last week
std::vector<ILeaderboard::Entry> FilterWeeklies(const std::vector<ILeaderboard::Entry>& leaderboard) {
    const auto currentTime = std::chrono::system_clock::now();
    std::vector<ILeaderboard::Entry> weeklyLeaderboard;
    std::copy_if(leaderboard.cbegin(), leaderboard.cend(), std::back_inserter(weeklyLeaderboard), [&](const auto& entry) {
        const auto elapsedTime = currentTime - entry.lastPlayedTimestamp;
        return elapsedTime < std::chrono::weeks{ 1 };
    });
    return weeklyLeaderboard;
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like this?

Not sure if it's feasible to store the lastPlayedTimestamp as an std::chrono::time_point, but if it is, it would avoid some of the pitfalls of using time_since_last_epoch() and count()

std::vector<ILeaderboard::Entry> FilterWeeklies(const std::vector<ILeaderboard::Entry>& leaderboard) {
    // Filter the leaderboard to only include entries from the last week
    const auto currentTime = std::chrono::system_clock::now();
    std::vector<ILeaderboard::Entry> weeklyLeaderboard;        
    for (const auto& entry : leaderboard) {
	    const auto elapsedTime = currentTime - entry.lastPlayedTimestamp;
	    if (elapsedTime < std::chrono::weeks{ 1 }) {
            weeklyLeaderboard.push_back(entry);
        }
    }
    return weeklyLeaderboard;
}

i dont think this will work. the timestamp in the database is already a unix timestamp and we need to compare with that, thats the whole reason im casting to seconds before the subtraction. the default is in milliseconds and as such no time meets the criteria

Copy link
Collaborator

@jadebenn jadebenn Jan 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Altered approach:

// Filter the leaderboard to only include entries from the last week
std::vector<ILeaderboard::Entry> FilterWeeklies(const std::vector<ILeaderboard::Entry>& leaderboard) {
    using namespace std::chrono;
    const auto currentTime = system_clock::now();
    std::vector<ILeaderboard::Entry> weeklyLeaderboard;
    std::copy_if(leaderboard.cbegin(), leaderboard.cend(), std::back_inserter(weeklyLeaderboard), [&](const auto& entry) {
        const auto lastPlayedTime = sys_time{ seconds{ entry.lastPlayedTimestamp } };
        return (currentTime - lastPlayedTime) < weeks{ 1 };
    });
    return weeklyLeaderboard;
}

Not sure if this is valid since I'm writing this on my phone, but hopefully you get the gist


std::vector<ILeaderboard::Entry> weeklyLeaderboard;
Expand Down Expand Up @@ -213,14 +215,15 @@ std::vector<ILeaderboard::Entry> ProcessLeaderboard(
const std::vector<ILeaderboard::Entry>& leaderboard,
const bool weekly,
const Leaderboard::InfoType infoType,
const uint32_t relatedPlayer) {
const uint32_t relatedPlayer,
const uint32_t numResults) {
std::vector<ILeaderboard::Entry> toReturn;

if (infoType == Leaderboard::InfoType::Friends) {
const auto friendsLeaderboard = FilterFriends(leaderboard, relatedPlayer);
toReturn = FilterTo10(weekly ? FilterWeeklies(friendsLeaderboard) : friendsLeaderboard, relatedPlayer, infoType);
toReturn = FilterToNumResults(weekly ? FilterWeeklies(friendsLeaderboard) : friendsLeaderboard, relatedPlayer, infoType, numResults);
} else {
toReturn = FilterTo10(weekly ? FilterWeeklies(leaderboard) : leaderboard, relatedPlayer, infoType);
toReturn = FilterToNumResults(weekly ? FilterWeeklies(leaderboard) : leaderboard, relatedPlayer, infoType, numResults);
}

return toReturn;
Expand Down Expand Up @@ -255,7 +258,7 @@ void Leaderboard::SetupLeaderboard(bool weekly) {
break;
}

const auto processedLeaderboard = ProcessLeaderboard(leaderboardRes, weekly, infoType, relatedPlayer);
const auto processedLeaderboard = ProcessLeaderboard(leaderboardRes, weekly, infoType, relatedPlayer, m_NumResults);

QueryToLdf(*this, processedLeaderboard);
}
Expand Down Expand Up @@ -301,8 +304,8 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, const GameID activi
}
}

void LeaderboardManager::SendLeaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, const LWOOBJID playerID, const LWOOBJID targetID) {
Leaderboard leaderboard(gameID, infoType, weekly, playerID, GetLeaderboardType(gameID));
void LeaderboardManager::SendLeaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, const LWOOBJID playerID, const LWOOBJID targetID, const uint32_t numResults) {
Leaderboard leaderboard(gameID, infoType, weekly, playerID, numResults, GetLeaderboardType(gameID));
leaderboard.SetupLeaderboard(weekly);
leaderboard.Send(targetID);
}
Expand Down
5 changes: 3 additions & 2 deletions dGame/LeaderboardManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class Leaderboard {
None
};
Leaderboard() = delete;
Leaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, LWOOBJID relatedPlayer, const Leaderboard::Type = None);
Leaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, LWOOBJID relatedPlayer, const uint32_t numResults, const Leaderboard::Type = None);

~Leaderboard();

Expand Down Expand Up @@ -79,6 +79,7 @@ class Leaderboard {
InfoType infoType;
Leaderboard::Type leaderboardType;
bool weekly;
uint32_t m_NumResults;
public:
LeaderboardEntry& PushBackEntry() {
return entries.emplace_back();
Expand All @@ -90,7 +91,7 @@ class Leaderboard {
};

namespace LeaderboardManager {
void SendLeaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, const LWOOBJID playerID, const LWOOBJID targetID);
void SendLeaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, const LWOOBJID playerID, const LWOOBJID targetID, const uint32_t numResults);

void SaveScore(const LWOOBJID& playerID, const GameID activityId, const float primaryScore, const float secondaryScore = 0, const float tertiaryScore = 0);

Expand Down
2 changes: 1 addition & 1 deletion dGame/dGameMessages/GameMessages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1691,7 +1691,7 @@ void GameMessages::HandleRequestActivitySummaryLeaderboardData(RakNet::BitStream

bool weekly = inStream.ReadBit();

LeaderboardManager::SendLeaderboard(gameID, queryType, weekly, entity->GetObjectID(), entity->GetObjectID());
LeaderboardManager::SendLeaderboard(gameID, queryType, weekly, entity->GetObjectID(), entity->GetObjectID(), 10);
EmosewaMC marked this conversation as resolved.
Show resolved Hide resolved
}

void GameMessages::HandleActivityStateChangeRequest(RakNet::BitStream& inStream, Entity* entity) {
Expand Down
2 changes: 1 addition & 1 deletion dScripts/ActivityManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void ActivityManager::GetLeaderboardData(Entity* self, const LWOOBJID playerID,
auto* sac = self->GetComponent<ScriptedActivityComponent>();
uint32_t gameID = sac != nullptr ? sac->GetActivityID() : self->GetLOT();
// Save the new score to the leaderboard and show the leaderboard to the player
LeaderboardManager::SendLeaderboard(activityID, Leaderboard::InfoType::MyStanding, false, playerID, self->GetObjectID());
LeaderboardManager::SendLeaderboard(activityID, Leaderboard::InfoType::MyStanding, false, playerID, self->GetObjectID(), numResults);
}

void ActivityManager::ActivityTimerStart(Entity* self, const std::string& timerName, const float_t updateInterval,
Expand Down
2 changes: 1 addition & 1 deletion dScripts/ai/MINIGAME/SG_GF/SERVER/SGCannon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ void SGCannon::StartGame(Entity* self) {

auto* player = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(PlayerIDVariable));
if (player != nullptr) {
GetLeaderboardData(self, player->GetObjectID(), GetActivityID(self), 1);
GetLeaderboardData(self, player->GetObjectID(), GetConstants().activityID, 10);
EmosewaMC marked this conversation as resolved.
Show resolved Hide resolved
LOG("Sending ActivityStart");
GameMessages::SendActivityStart(self->GetObjectID(), player->GetSystemAddress());

Expand Down
Loading